Mark Sapiro pushed to branch master at GNU Mailman / Mailman Core


Commits:
a43b7cc5 by Mark Sapiro at 2021-06-12T13:22:47-07:00
Missing held messages can now be accepted and/or forwarded.

- - - - -
f8760c92 by Mark Sapiro at 2021-06-12T22:45:40+00:00
Merge branch 'lost' into 'master'

Missing held messages can now be accepted and/or forwarded.

Closes #914

See merge request mailman/mailman!874
- - - - -


3 changed files:

- src/mailman/app/moderator.py
- src/mailman/app/tests/test_moderation.py
- src/mailman/docs/NEWS.rst


Changes:

=====================================
src/mailman/app/moderator.py
=====================================
@@ -92,6 +92,19 @@ def hold_message(mlist, msg, msgdata=None, reason=None):
     return request_id
 
 
+def _lost_message(mlist, subject, sender, message_id):
+    # Create a substitute for a message not found in the message store.
+    text = _("""\
+The content of this message was lost. It was probably cross-posted to
+multiple lists and previously handled on another list.
+""")
+    msg = UserNotification(
+        mlist.posting_address, sender, subject, text, mlist.preferred_language)
+    del msg['message-id']
+    msg['Message-ID'] = message_id
+    return msg
+
+
 @public
 def handle_message(mlist, id, action, comment=None, forward=None):
     message_store = getUtility(IMessageStore)
@@ -121,6 +134,8 @@ def handle_message(mlist, id, action, comment=None, 
forward=None):
     elif action is Action.accept:
         # Start by getting the message from the message store.
         msg = message_store.get_message_by_id(message_id)
+        if msg is None:
+            msg = _lost_message(mlist, subject, sender, message_id)
         # Delete moderation-specific entries from the message metadata.
         for key in list(msgdata):
             if key.startswith('_mod_'):
@@ -148,6 +163,8 @@ def handle_message(mlist, id, action, comment=None, 
forward=None):
     if forward:
         # Get a copy of the original message from the message store.
         msg = message_store.get_message_by_id(message_id)
+        if msg is None:
+            msg = _lost_message(mlist, subject, sender, message_id)
         # It's possible the forwarding address list is a comma separated list
         # of display_name/address pairs.
         addresses = [addr[1] for addr in getaddresses(forward)]


=====================================
src/mailman/app/tests/test_moderation.py
=====================================
@@ -96,6 +96,44 @@ Message-ID: <alpha>
         self.assertEqual(message['x-mailfrom'], 'test-boun...@example.com')
         self.assertEqual(message['x-rcptto'], 'b...@example.com')
 
+    def test_missing_accepted_message_gets_posted(self):
+        # A message that is accepted by the moderator should get posted to the
+        # mailing list.  LP: #827697
+        msgdata = dict(listname='t...@example.com',
+                       recipients=['b...@example.com'])
+        request_id = hold_message(self._mlist, self._msg, msgdata)
+        message_store = getUtility(IMessageStore)
+        message_store.delete_message('<alpha>')
+        handle_message(self._mlist, request_id, Action.accept)
+        self._in.run()
+        self._pipeline.run()
+        self._out.run()
+        messages = list(SMTPLayer.smtpd.messages)
+        self.assertEqual(len(messages), 1)
+        message = messages[0]
+        # We don't need to test the entire posted message, just the bits that
+        # prove it got sent out.
+        self.assertIn('x-mailman-version', message)
+        self.assertIn('x-peer', message)
+        # The X-Mailman-Approved-At header has local timezone information in
+        # it, so test that separately.
+        self.assertEqual(message['x-mailman-approved-at'][:-5],
+                         'Mon, 01 Aug 2005 07:49:23 ')
+        del message['x-mailman-approved-at']
+        # The Message-ID matches the original.
+        self.assertEqual(message['message-id'], '<alpha>')
+        # Anne sent the message and the mailing list received it.
+        self.assertEqual(message['from'], 'a...@example.com')
+        self.assertEqual(message['to'], 't...@example.com')
+        # The Subject header has the list's prefix.
+        self.assertEqual(message['subject'], '[Test] hold me')
+        # The list's -bounce address is the actual sender, and Bart is the
+        # only actual recipient.  These headers are added by the testing
+        # framework and don't show up in production.  They match the RFC 5321
+        # envelope.
+        self.assertEqual(message['x-mailfrom'], 'test-boun...@example.com')
+        self.assertEqual(message['x-rcptto'], 'b...@example.com')
+
     def test_hold_action_alias_for_defer(self):
         # In handle_message(), the 'hold' action is the same as 'defer' for
         # purposes of this API.
@@ -130,6 +168,23 @@ Message-ID: <alpha>
         self.assertEqual(list(items[0].msgdata['recipients']),
                          ['z...@example.com'])
 
+    def test_missing_forward(self):
+        # We can forward the message to an email address.
+        request_id = hold_message(self._mlist, self._msg)
+        message_store = getUtility(IMessageStore)
+        message_store.delete_message('<alpha>')
+        handle_message(self._mlist, request_id, Action.discard,
+                       forward=['z...@example.com'])
+        # The forwarded message lives in the virgin queue.
+        items = get_queue_messages('virgin', expected_count=1)
+        self.assertEqual(str(items[0].msg['subject']),
+                         'Forward of moderated message')
+        self.assertEqual(list(items[0].msgdata['recipients']),
+                         ['z...@example.com'])
+        payload = items[0].msg.get_payload()[0]
+        self.assertIsNotNone(payload)
+        self.assertEqual('<alpha>', payload['message-id'])
+
     def test_survive_a_deleted_message(self):
         # When the message that should be deleted is not found in the store,
         # no error is raised.


=====================================
src/mailman/docs/NEWS.rst
=====================================
@@ -73,6 +73,8 @@ Bugs
   (Closes #892)
 * DMARC policy discovery ignores domains with multiple DMARC records per
   RFC 7849.  (Closes #907)
+* Held messages missing from the message store can now be accepted and/or
+  forwarded.  (closes #914)
 
 Command line
 ------------



View it on GitLab: 
https://gitlab.com/mailman/mailman/-/compare/c7b79d173ff95eebbea251d41945381d0332ca37...f8760c92b8ed4162bda1629d68edc774eb188303

-- 
View it on GitLab: 
https://gitlab.com/mailman/mailman/-/compare/c7b79d173ff95eebbea251d41945381d0332ca37...f8760c92b8ed4162bda1629d68edc774eb188303
You're receiving this email because of your account on gitlab.com.


_______________________________________________
Mailman-checkins mailing list -- mailman-checkins@python.org
To unsubscribe send an email to mailman-checkins-le...@python.org
https://mail.python.org/mailman3/lists/mailman-checkins.python.org/
Member address: arch...@jab.org

Reply via email to