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


Commits:
6f5bc026 by Mark Sapiro at 2022-02-12T06:50:04+00:00
Apply non-None nonmember.moderation_action before *_these_nonmembers.

- - - - -
c5ad1ca4 by Mark Sapiro at 2022-02-12T06:50:04+00:00
Merge branch 'nonmember' into 'master'

Apply non-None nonmember.moderation_action before *_these_nonmembers.

Closes #978

See merge request mailman/mailman!961
- - - - -


3 changed files:

- src/mailman/docs/NEWS.rst
- src/mailman/rules/moderation.py
- src/mailman/rules/tests/test_moderation.py


Changes:

=====================================
src/mailman/docs/NEWS.rst
=====================================
@@ -37,6 +37,8 @@ Bugs fixed
   it can be updated during that time. (Closes #724)
 * The ``mailman import21`` now always imports owners/moderators with
   ``DeliveryStatus.enabled``.  (Closes #977)
+* A specific nonmember moderation action will be checked for and applied before
+  testing the legacy ``*_these_nonmembers`` settings.  (Closes #978)
 
 REST
 ====


=====================================
src/mailman/rules/moderation.py
=====================================
@@ -95,6 +95,20 @@ class MemberModeration:
         return False
 
 
+def _do_action(msgdata, action, sender):
+    if action is Action.defer:
+        # The regular moderation rules apply.
+        return False
+    else:
+        # We must stringify the moderation action so that it can be
+        # stored in the pending request table.
+        with _.defer_translation():
+            # This will be translated at the point of use.
+            reason = _('The message is not from a list member')
+        _record_action(msgdata, action.name, sender, reason)
+        return True
+
+
 def _record_action(msgdata, action, sender, reason):
     msgdata['member_moderation_action'] = action
     msgdata['moderation_sender'] = sender
@@ -154,7 +168,13 @@ class NonmemberModeration:
             assert nonmember is not None, (
                 "sender {} didn't get subscribed as a nonmember".format(sender)
                 )
-            # Check the '*_these_nonmembers' properties first.  XXX These are
+            action = nonmember.moderation_action
+            if action is not None:
+                # Do this first so a specific nonmember.moderation_action
+                # trumps the legacy settings.
+                return _do_action(msgdata, action, sender)
+            # nonmember has no moderation action so check the
+            # '*_these_nonmembers' properties.  XXX These are
             # legacy attributes from MM2.1; their database type is 'pickle' and
             # they should eventually get replaced.
             for action_name in ('accept', 'hold', 'reject', 'discard'):
@@ -174,19 +194,8 @@ class NonmemberModeration:
                                 action_name)
                         _record_action(msgdata, action_name, sender, reason)
                         return True
-            action = (mlist.default_nonmember_action
-                      if nonmember.moderation_action is None
-                      else nonmember.moderation_action)
-            if action is Action.defer:
-                # The regular moderation rules apply.
-                return False
-            elif action is not None:
-                # We must stringify the moderation action so that it can be
-                # stored in the pending request table.
-                with _.defer_translation():
-                    # This will be translated at the point of use.
-                    reason = _('The message is not from a list member')
-                _record_action(msgdata, action.name, sender, reason)
-                return True
+            # No nonmember.moderation.action and no legacy hits.
+            action = mlist.default_nonmember_action
+            return _do_action(msgdata, action, sender)
         # The sender must be a member, so this rule does not match.
         return False


=====================================
src/mailman/rules/tests/test_moderation.py
=====================================
@@ -109,7 +109,6 @@ A message body.
 
     def test_these_nonmembers(self):
         # Test the legacy *_these_nonmembers attributes.
-        user_manager = getUtility(IUserManager)
         actions = {
             'a...@example.com': 'accept',
             'b...@example.com': 'hold',
@@ -151,6 +150,59 @@ A message body.
                     msgdata['member_moderation_action'], action_name,
                     'Wrong action for {}: {}'.format(address, action_name))
 
+    def test_specific_nonmember_action_trumps_legacy(self):
+        # A specific nonmember.moderation_action trumps *_these_nonmembers.
+        rule = moderation.NonmemberModeration()
+        user_manager = getUtility(IUserManager)
+        address = 'a...@example.com'
+        # Add Anne to hold_these_nonmembers and create a nonmember with
+        # moderation_action = Action.defer
+        setattr(self._mlist, 'hold_these_nonmembers', [address])
+        anne = user_manager.create_address(address)
+        nonmember = self._mlist.subscribe(anne, MemberRole.nonmember)
+        nonmember.moderation_action = Action.defer
+        msg = mfs("""\
+From: {}
+To: t...@example.com
+Subject: A test message
+Message-ID: <ant>
+MIME-Version: 1.0
+
+A message body.
+""".format(address))
+        msgdata = {}
+        result = rule.check(self._mlist, msg, msgdata)
+        self.assertFalse(
+            result, 'NonmemberModeration rule should miss')
+
+    def test_nonmember_action_none_ignored(self):
+        # A specific nonmember.moderation_action trumps *_these_nonmembers.
+        rule = moderation.NonmemberModeration()
+        user_manager = getUtility(IUserManager)
+        address = 'a...@example.com'
+        # Add Anne to hold_these_nonmembers and create a nonmember with
+        # moderation_action = None
+        setattr(self._mlist, 'hold_these_nonmembers', [address])
+        anne = user_manager.create_address(address)
+        nonmember = self._mlist.subscribe(anne, MemberRole.nonmember)
+        nonmember.moderation_action = None
+        msg = mfs("""\
+From: {}
+To: t...@example.com
+Subject: A test message
+Message-ID: <ant>
+MIME-Version: 1.0
+
+A message body.
+""".format(address))
+        msgdata = {}
+        result = rule.check(self._mlist, msg, msgdata)
+        self.assertTrue(result, 'NonmemberModeration rule should hit')
+        self.assertIn('member_moderation_action', msgdata)
+        self.assertEqual(
+            msgdata['member_moderation_action'], 'hold',
+            'Wrong action for {}: {}'.format(address, 'hold'))
+
     def test_nonmember_fallback_to_list_defaults(self):
         # https://gitlab.com/mailman/mailman/issues/189
         self._mlist.default_nonmember_action = Action.hold



View it on GitLab: 
https://gitlab.com/mailman/mailman/-/compare/8bbffb6b0bca6207b567ecf24cdf503516b46d39...c5ad1ca4c17827353b4096c7e993ac5e25d230af

-- 
View it on GitLab: 
https://gitlab.com/mailman/mailman/-/compare/8bbffb6b0bca6207b567ecf24cdf503516b46d39...c5ad1ca4c17827353b4096c7e993ac5e25d230af
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