Aurélien Bompard has proposed merging lp:~abompard/mailman/moderation_reasons 
into lp:mailman.

Requested reviews:
  Mailman Coders (mailman-coders)

For more details, see:
https://code.launchpad.net/~abompard/mailman/moderation_reasons/+merge/216392

Currently moderation reasons are always 'XXX'. This branch fixes that with a 
message that comes from the moderation rules that matched.
-- 
https://code.launchpad.net/~abompard/mailman/moderation_reasons/+merge/216392
Your team Mailman Coders is requested to review the proposed merge of 
lp:~abompard/mailman/moderation_reasons into lp:mailman.
=== modified file 'src/mailman/app/docs/chains.rst'
--- src/mailman/app/docs/chains.rst	2012-03-07 23:45:09 +0000
+++ src/mailman/app/docs/chains.rst	2014-04-17 20:19:21 +0000
@@ -132,7 +132,7 @@
         List:    [email protected]
         From:    [email protected]
         Subject: My first post
-        Reason:  XXX
+        Reasons:  (n/a)
     <BLANKLINE>
     At your convenience, visit:
     <BLANKLINE>
@@ -189,7 +189,7 @@
     <BLANKLINE>
     The reason it is being held:
     <BLANKLINE>
-        XXX
+        (n/a)
     <BLANKLINE>
     Either the message will get posted to the list, or you will receive
     notification of the moderator's decision.  If you would like to cancel

=== modified file 'src/mailman/chains/hold.py'
--- src/mailman/chains/hold.py	2014-01-01 14:59:42 +0000
+++ src/mailman/chains/hold.py	2014-04-17 20:19:21 +0000
@@ -26,6 +26,7 @@
 
 
 import logging
+import re
 
 from email.mime.message import MIMEMessage
 from email.mime.text import MIMEText
@@ -138,7 +139,6 @@
         if rule_misses:
             msg['X-Mailman-Rule-Misses'] = SEMISPACE.join(rule_misses)
         # Hold the message by adding it to the list's request database.
-        # XXX How to calculate the reason?
         request_id = hold_message(mlist, msg, msgdata, None)
         # Calculate a confirmation token to send to the author of the
         # message.
@@ -158,11 +158,13 @@
             original_subject = _('(no subject)')
         else:
             original_subject = oneline(original_subject, charset)
+        reasons = msgdata.get("moderation_reasons", [_("(n/a)")])
         substitutions = dict(
             listname    = mlist.fqdn_listname,
             subject     = original_subject,
             sender      = msg.sender,
-            reason      = 'XXX', #reason,
+            reasons     = "\r\n".join(
+                ['    ' + wrap(_(r), column=66) for r in reasons]),
             confirmurl  = '{0}/{1}'.format(mlist.script_url('confirm'), token),
             admindb_url = mlist.script_url('admindb'),
             )
@@ -209,7 +211,8 @@
                 charset = language.charset
                 # We need to regenerate or re-translate a few values in the
                 # substitution dictionary.
-                #d['reason'] = _(reason) # XXX reason
+                substitutions["reasons"] = wrap(
+                        ", ".join([_(r) for r in reasons]), column=55)
                 substitutions['subject'] = original_subject
                 # craft the admin notification message and deliver it
                 subject = _(
@@ -240,9 +243,7 @@
                 nmsg.attach(MIMEMessage(dmsg))
                 nmsg.send(mlist, **dict(tomoderators=True))
         # Log the held message
-        # XXX reason
-        reason = 'n/a'
         log.info('HOLD: %s post from %s held, message-id=%s: %s',
                  mlist.fqdn_listname, msg.sender,
-                 msg.get('message-id', 'n/a'), reason)
+                 msg.get('message-id', 'n/a'), " ; ".join(reasons))
         notify(HoldEvent(mlist, msg, msgdata, self))

=== modified file 'src/mailman/chains/tests/test_hold.py'
--- src/mailman/chains/tests/test_hold.py	2014-01-01 14:59:42 +0000
+++ src/mailman/chains/tests/test_hold.py	2014-04-17 20:19:21 +0000
@@ -29,10 +29,14 @@
 from zope.component import getUtility
 
 from mailman.app.lifecycle import create_list
-from mailman.chains.hold import autorespond_to_sender
+from mailman.chains.hold import autorespond_to_sender, HoldChain
+from mailman.email.message import Message
 from mailman.interfaces.autorespond import IAutoResponseSet, Response
 from mailman.interfaces.usermanager import IUserManager
-from mailman.testing.helpers import configuration, get_queue_messages
+from mailman.testing.helpers import (
+    configuration,
+    get_queue_messages,
+    specialized_message_from_string as mfs)
 from mailman.testing.layers import ConfigLayer
 
 
@@ -89,3 +93,48 @@
 
 If you believe this message is in error, or if you have any questions,
 please contact the list owner at [email protected].""")
+
+
+
+class TestHoldChain(unittest.TestCase):
+    """Test the hold chain code."""
+
+    layer = ConfigLayer
+
+    def setUp(self):
+        self._mlist = create_list('[email protected]')
+
+    def test_hold_chain(self):
+        msg = mfs("""\
+From: [email protected]
+To: [email protected]
+Subject: A message
+Message-ID: <ant>
+MIME-Version: 1.0
+
+A message body.
+""")
+        metadata = {
+            "moderation_reasons": [
+                "TEST-REASON-1",
+                "TEST-REASON-2",
+            ],
+        }
+        chain = HoldChain()
+        chain._process(self._mlist, msg, metadata)
+        messages = get_queue_messages('virgin')
+        self.assertEqual(len(messages), 2)
+        sent_msgs = {}
+        for msg_bag in messages:
+            if msg_bag.msg["To"] == "[email protected]":
+                sent_msgs["owner"] = msg_bag.msg
+            elif msg_bag.msg["To"] == "[email protected]":
+                sent_msgs["sender"] = msg_bag.msg
+            else:
+                self.fail("Unexpected message: %s" % msg_bag.msg)
+        self.assertTrue("TEST-REASON-1, TEST-REASON-2" in
+                        sent_msgs["owner"].as_string())
+        self.assertTrue("    TEST-REASON-1" in
+                        sent_msgs["sender"].as_string())
+        self.assertTrue("    TEST-REASON-2" in
+                        sent_msgs["sender"].as_string())

=== modified file 'src/mailman/rules/docs/moderation.rst'
--- src/mailman/rules/docs/moderation.rst	2013-06-19 02:43:40 +0000
+++ src/mailman/rules/docs/moderation.rst	2014-04-17 20:19:21 +0000
@@ -51,8 +51,9 @@
     >>> member_rule.check(mlist, member_msg, msgdata)
     True
     >>> dump_msgdata(msgdata)
-    moderation_action: hold
-    moderation_sender: [email protected]
+    moderation_action : hold
+    moderation_reasons: [u'The message comes from a moderated member']
+    moderation_sender : [email protected]
 
 
 Nonmembers
@@ -87,8 +88,9 @@
     >>> nonmember_rule.check(mlist, nonmember_msg, msgdata)
     True
     >>> dump_msgdata(msgdata)
-    moderation_action: hold
-    moderation_sender: [email protected]
+    moderation_action : hold
+    moderation_reasons: [u'The message is not from a list member']
+    moderation_sender : [email protected]
 
 Of course, the nonmember action can be set to defer the decision, in which
 case the rule does not match.
@@ -140,8 +142,9 @@
     >>> nonmember_rule.check(mlist, msg, msgdata)
     True
     >>> dump_msgdata(msgdata)
-    moderation_action: hold
-    moderation_sender: [email protected]
+    moderation_action : hold
+    moderation_reasons: [u'The message is not from a list member']
+    moderation_sender : [email protected]
 
     >>> dump_list(mlist.members.members, key=memberkey)
     <Member: Anne Person <[email protected]>

=== modified file 'src/mailman/rules/moderation.py'
--- src/mailman/rules/moderation.py	2014-03-15 19:13:46 +0000
+++ src/mailman/rules/moderation.py	2014-04-17 20:19:21 +0000
@@ -59,6 +59,10 @@
                 # stored in the pending request table.
                 msgdata['moderation_action'] = action.name
                 msgdata['moderation_sender'] = sender
+                if 'moderation_reasons' not in msgdata:
+                    msgdata['moderation_reasons'] = []
+                msgdata['moderation_reasons'].append(
+                        _('The message comes from a moderated member'))
                 return True
         # The sender is not a member so this rule does not match.
         return False
@@ -104,6 +108,10 @@
                 # stored in the pending request table.
                 msgdata['moderation_action'] = action.name
                 msgdata['moderation_sender'] = sender
+                if 'moderation_reasons' not in msgdata:
+                    msgdata['moderation_reasons'] = []
+                msgdata['moderation_reasons'].append(
+                        _('The message is not from a list member'))
                 return True
         # The sender must be a member, so this rule does not match.
         return False

=== modified file 'src/mailman/rules/tests/test_moderation.py'
--- src/mailman/rules/tests/test_moderation.py	2014-03-15 19:13:46 +0000
+++ src/mailman/rules/tests/test_moderation.py	2014-04-17 20:19:21 +0000
@@ -28,6 +28,7 @@
 import unittest
 
 from mailman.app.lifecycle import create_list
+from mailman.interfaces.action import Action
 from mailman.interfaces.member import MemberRole
 from mailman.interfaces.usermanager import IUserManager
 from mailman.rules import moderation
@@ -76,3 +77,37 @@
         # Bill is not a member.
         bill_member = self._mlist.members.get_member('[email protected]')
         self.assertIsNone(bill_member)
+
+    def test_moderation_reason(self):
+        user_manager = getUtility(IUserManager)
+        anne = user_manager.create_address('[email protected]')
+        msg = mfs("""\
+From: [email protected]
+To: [email protected]
+Subject: A test message
+Message-ID: <ant>
+MIME-Version: 1.0
+
+A message body.
+""")
+        # Anne is in the message's senders list.
+        self.assertIn('[email protected]', msg.senders)
+        # Now run the rule
+        rule = moderation.NonmemberModeration()
+        msgdata = {}
+        result = rule.check(self._mlist, msg, msgdata)
+        self.assertTrue(result, 'NonmemberModeration rule should hit')
+        # The reason for moderation should be in the msgdata
+        self.assertTrue("moderation_reasons" in msgdata)
+        self.assertEqual(len(msgdata["moderation_reasons"]), 1)
+        # Now make Anne a moderated member
+        anne_member = self._mlist.subscribe(anne, MemberRole.member)
+        anne_member.moderation_action = Action.hold
+        # ...and run the rule again
+        rule = moderation.MemberModeration()
+        msgdata = {}
+        result = rule.check(self._mlist, msg, msgdata)
+        self.assertTrue(result, 'MemberModeration rule should hit')
+        # The reason for moderation should be in the msgdata
+        self.assertTrue("moderation_reasons" in msgdata)
+        self.assertEqual(len(msgdata["moderation_reasons"]), 1)

=== modified file 'src/mailman/templates/en/postauth.txt'
--- src/mailman/templates/en/postauth.txt	2008-09-29 06:44:19 +0000
+++ src/mailman/templates/en/postauth.txt	2014-04-17 20:19:21 +0000
@@ -4,10 +4,10 @@
     List:    $listname
     From:    $sender
     Subject: $subject
-    Reason:  $reason
+    Reasons: $reasons
 
 At your convenience, visit:
 
     $admindb_url
-        
+
 to approve or deny the request.

=== modified file 'src/mailman/templates/en/postheld.txt'
--- src/mailman/templates/en/postheld.txt	2008-09-29 06:44:19 +0000
+++ src/mailman/templates/en/postheld.txt	2014-04-17 20:19:21 +0000
@@ -6,7 +6,7 @@
 
 The reason it is being held:
 
-    $reason
+$reasons
 
 Either the message will get posted to the list, or you will receive
 notification of the moderator's decision.  If you would like to cancel

_______________________________________________
Mailman-coders mailing list
[email protected]
https://mail.python.org/mailman/listinfo/mailman-coders

Reply via email to