diff --git a/multischleuder/conflict.py b/multischleuder/conflict.py index 111b793..3183620 100644 --- a/multischleuder/conflict.py +++ b/multischleuder/conflict.py @@ -17,7 +17,7 @@ from datetime import datetime import pgpy # type: ignore from multischleuder.reporting import KeyConflictMessage, Message, UserConflictMessage -from multischleuder.types import SchleuderKey, SchleuderSubscriber +from multischleuder.types import SchleuderKey, SchleuderList, SchleuderSubscriber class KeyConflictResolution: @@ -36,7 +36,9 @@ class KeyConflictResolution: def resolve(self, target: str, mail_from: str, - subscriptions: List[SchleuderSubscriber]) -> Tuple[List[SchleuderSubscriber], List[Optional[Message]]]: + subscriptions: List[SchleuderSubscriber], + sources: List[SchleuderList]) -> Tuple[List[SchleuderSubscriber], List[Optional[Message]]]: + sourcemap: Dict[int, str] = {s.id: s.name for s in sources} conflicts: List[Optional[Message]] = [] # First check for keys that are being used by more than one subscriber @@ -47,7 +49,7 @@ class KeyConflictResolution: keys.setdefault(s.key.fingerprint, []).append(s) key_resolved: List[SchleuderSubscriber] = [] for k in keys.values(): - rk, m = self._resolve_users(target, mail_from, k) + rk, m = self._resolve_users(target, mail_from, k, sourcemap) if rk is not None: key_resolved.append(rk) if m is not None: @@ -60,7 +62,7 @@ class KeyConflictResolution: # Perform conflict resolution for each set of subscribers with the same email resolved: List[SchleuderSubscriber] = [] for c in subs.values(): - r, msg = self._resolve_keys(target, mail_from, c) + r, msg = self._resolve_keys(target, mail_from, c, sourcemap) if r is not None: resolved.append(r) if msg is not None: @@ -70,7 +72,8 @@ class KeyConflictResolution: def _resolve_keys(self, target: str, mail_from: str, - subscriptions: List[SchleuderSubscriber]) \ + subscriptions: List[SchleuderSubscriber], + sourcemap: Dict[int, str]) \ -> Tuple[Optional[SchleuderSubscriber], Optional[Message]]: notnull = [s for s in subscriptions if s.key is not None] if len(notnull) == 0: @@ -96,7 +99,8 @@ class KeyConflictResolution: subscriptions, digest, mail_from, - self._key_template + self._key_template, + sourcemap ) # Return the result of conflict resolution return earliest, msg @@ -104,7 +108,8 @@ class KeyConflictResolution: def _resolve_users(self, target: str, mail_from: str, - subscriptions: List[SchleuderSubscriber]) \ + subscriptions: List[SchleuderSubscriber], + sourcemap: Dict[int, str]) \ -> Tuple[Optional[SchleuderSubscriber], Optional[List[Message]]]: notnull = [s for s in subscriptions if s.key is not None] if len(notnull) == 0: @@ -133,7 +138,8 @@ class KeyConflictResolution: subscriptions, digest, mail_from, - self._user_template + self._user_template, + sourcemap )) # Return the result of conflict resolution return earliest, msgs diff --git a/multischleuder/processor.py b/multischleuder/processor.py index 3d76d7f..9c1fea4 100644 --- a/multischleuder/processor.py +++ b/multischleuder/processor.py @@ -50,7 +50,7 @@ class MultiList: continue all_subs.append(s) # ... which is taken care of by the key conflict resolution routine - resolved, conflicts = self._kcr.resolve(self._target, self._mail_from, all_subs) + resolved, conflicts = self._kcr.resolve(self._target, self._mail_from, all_subs, sources) self._reporter.add_messages(conflicts) intended_subs: Set[SchleuderSubscriber] = set(resolved) intended_keys: Set[SchleuderKey] = {s.key for s in intended_subs if s.key is not None} diff --git a/multischleuder/reporting.py b/multischleuder/reporting.py index 6019bcc..4bac4d4 100644 --- a/multischleuder/reporting.py +++ b/multischleuder/reporting.py @@ -91,14 +91,16 @@ class KeyConflictMessage(Message): affected: List[SchleuderSubscriber], digest: str, mail_from: str, - template: str): + template: str, + sourcemap: Dict[int, str]): # Render the message body fpr = 'no key' if chosen.key is None else chosen.key.fingerprint _chosen = f'{fpr} {chosen.email}' _affected = '' for a in affected: fpr = 'no key' if a.key is None else a.key.fingerprint - _affected += f'{fpr} {a.schleuder}\n' + aschleuder: str = sourcemap.get(a.schleuder, 'unknown') + _affected += f'{fpr} {aschleuder}\n' content = template.format( subscriber=chosen.email, schleuder=schleuder, @@ -128,13 +130,15 @@ class UserConflictMessage(Message): affected: List[SchleuderSubscriber], digest: str, mail_from: str, - template: str): + template: str, + sourcemap: Dict[int, str]): # Render the message body assert chosen.key is not None _chosen = chosen.email _affected = '' for a in affected: - _affected += f'{a.email} {a.schleuder}\n' + aschleuder: str = sourcemap.get(a.schleuder, 'unknown') + _affected += f'{a.email} {aschleuder}\n' content = template.format( subscriber=subscriber, fingerprint=chosen.key.fingerprint, diff --git a/multischleuder/test/test_conflict.py b/multischleuder/test/test_conflict.py index 7da79e2..b19a8b1 100644 --- a/multischleuder/test/test_conflict.py +++ b/multischleuder/test/test_conflict.py @@ -123,7 +123,7 @@ class TestKeyConflictResolution(unittest.TestCase): contents.seek(io.SEEK_END) # Opened with 'a+' with patch('builtins.open', mock_open(read_data=_CONFLICT_STATE_NONE)) as mock_statefile: mock_statefile().__enter__.return_value = contents - resolved, messages = kcr.resolve('', '', []) + resolved, messages = kcr.resolve('', '', [], []) self.assertEqual(0, len(resolved)) self.assertEqual(0, len(messages)) @@ -133,7 +133,7 @@ class TestKeyConflictResolution(unittest.TestCase): date1 = datetime(2022, 4, 15, 5, 23, 42, 0, tzinfo=tzutc()) sub1 = SchleuderSubscriber(3, 'foo@example.org', key1, sch1.id, date1) kcr = KeyConflictResolution(3600, '/tmp/state.json', _KEY_TEMPLATE, _USER_TEMPLATE) - resolved, messages = kcr.resolve('', '', [sub1]) + resolved, messages = kcr.resolve('', '', [sub1], [sch1]) self.assertEqual(1, len(resolved)) self.assertEqual(sub1, resolved[0]) self.assertEqual(0, len(messages)) @@ -158,7 +158,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(1, len(resolved)) self.assertEqual('2FBBC0DF97FDBF1E4B704EEDE39EF4FAC420BEB6', resolved[0].key.fingerprint) @@ -185,7 +186,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(1, len(resolved)) self.assertEqual('135AFA0FB3FF584828911208B7913308392972A4', resolved[0].key.fingerprint) @@ -222,7 +224,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(1, len(resolved)) self.assertEqual('2FBBC0DF97FDBF1E4B704EEDE39EF4FAC420BEB6', resolved[0].key.fingerprint) @@ -242,7 +245,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1]) + subscriptions=[sub1], + sources=[sch1]) self.assertEqual(0, len(resolved)) self.assertEqual(0, len(messages)) @@ -266,7 +270,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(1, len(resolved)) self.assertEqual('bar@example.org', resolved[0].email) @@ -318,7 +323,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2, sub3]) + subscriptions=[sub1, sub2, sub3], + sources=[sch1, sch2]) self.assertEqual(2, len(resolved)) foo, bar = resolved @@ -369,7 +375,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, msgs = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(0, len(msgs)) def test_send_messages_brokenstate(self): @@ -391,7 +398,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, msgs = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(0, len(msgs)) def test_send_messages_emptystate(self): @@ -412,7 +420,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, msgs = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(1, len(msgs)) now = datetime.utcnow().timestamp() @@ -442,7 +451,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, msgs = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(1, len(msgs)) now = datetime.utcnow().timestamp() @@ -472,7 +482,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(1, len(messages)) msg = messages[0] @@ -503,7 +514,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(0, len(messages)) now = datetime.utcnow().timestamp() @@ -536,7 +548,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2]) + subscriptions=[sub1, sub2], + sources=[sch1, sch2]) self.assertEqual(1, len(messages)) now = datetime.utcnow().timestamp() @@ -568,7 +581,8 @@ class TestKeyConflictResolution(unittest.TestCase): resolved, messages = kcr.resolve( target='test@schleuder.example.org', mail_from='test-owner@schleuder.example.org', - subscriptions=[sub1, sub2, sub3]) + subscriptions=[sub1, sub2, sub3], + sources=[sch1, sch2, sch3]) self.assertEqual(1, len(messages)) msg = messages[0].mime pgp = pgpy.PGPMessage.from_blob(msg.get_payload()[1].get_payload(decode=True)) diff --git a/multischleuder/test/test_multilist.py b/multischleuder/test/test_multilist.py index 87587bb..57c1e2a 100644 --- a/multischleuder/test/test_multilist.py +++ b/multischleuder/test/test_multilist.py @@ -14,7 +14,8 @@ from multischleuder.types import SchleuderKey, SchleuderList, SchleuderSubscribe def _resolve(target: str, mail_from: str, - subscriptions: List[SchleuderSubscriber]) -> Tuple[List[SchleuderSubscriber], List[Message]]: + subscriptions: List[SchleuderSubscriber], + sources: List[SchleuderList]) -> Tuple[List[SchleuderSubscriber], List[Message]]: # Mock conflict resolution that does not send or prepare messages subs: Dict[str, List[SchleuderSubscriber]] = {} for s in subscriptions: diff --git a/multischleuder/test/test_reporting.py b/multischleuder/test/test_reporting.py index c3f4bbe..9663e21 100644 --- a/multischleuder/test/test_reporting.py +++ b/multischleuder/test/test_reporting.py @@ -18,7 +18,8 @@ def one_of_each_kind(): affected=[sub], digest='digest', mail_from='test-owner@example.org', - template='averylongmessage') + template='averylongmessage', + sourcemap={1: 'test@example.org'}) msg2 = AdminReport( schleuder='test@example.org', mail_to='admin@example.org', @@ -36,7 +37,8 @@ def one_of_each_kind(): affected=[sub2], digest='digest', mail_from='test-owner@example.org', - template='averylongmessage') + template='averylongmessage', + sourcemap={1: 'test@example.org'}) return [msg1, msg2, msg3] diff --git a/multischleuder/test/test_smtp.py b/multischleuder/test/test_smtp.py index a858d11..2f8ab2a 100644 --- a/multischleuder/test/test_smtp.py +++ b/multischleuder/test/test_smtp.py @@ -176,7 +176,8 @@ class TestSmtpClient(unittest.TestCase): affected=[sub], digest='digest', mail_from='test-owner@example.org', - template='averylongmessage') + template='averylongmessage', + sourcemap={1: 'foo@example.org'}) msg2 = AdminReport( schleuder='test@example.org', mail_to='admin@example.org', @@ -209,7 +210,8 @@ class TestSmtpClient(unittest.TestCase): affected=[sub], digest='digest', mail_from='test-owner@example.org', - template='averylongmessage') + template='averylongmessage', + sourcemap={1: 'foo@example.org'}) client.send_messages([msg1]) ctrl.stop() self.assertFalse(ctrl.handler.connected)