summaryrefslogtreecommitdiff
path: root/src/mailman/rules
diff options
context:
space:
mode:
authorBarry Warsaw2016-04-01 15:14:51 -0400
committerBarry Warsaw2016-04-01 15:14:51 -0400
commitf7e9e4698bdd4cee39c9eb485296cbbfa32369a9 (patch)
tree6dc8557009cbddb4e416faecc329b38b1cc0ad0b /src/mailman/rules
parentafdd3b6deb32cd8cfdad291aba173a63064514f8 (diff)
downloadmailman-f7e9e4698bdd4cee39c9eb485296cbbfa32369a9.tar.gz
mailman-f7e9e4698bdd4cee39c9eb485296cbbfa32369a9.tar.zst
mailman-f7e9e4698bdd4cee39c9eb485296cbbfa32369a9.zip
Diffstat (limited to 'src/mailman/rules')
-rw-r--r--src/mailman/rules/docs/moderation.rst41
-rw-r--r--src/mailman/rules/moderation.py10
-rw-r--r--src/mailman/rules/tests/test_moderation.py26
3 files changed, 48 insertions, 29 deletions
diff --git a/src/mailman/rules/docs/moderation.rst b/src/mailman/rules/docs/moderation.rst
index 56602189b..d1cc5fd67 100644
--- a/src/mailman/rules/docs/moderation.rst
+++ b/src/mailman/rules/docs/moderation.rst
@@ -3,9 +3,9 @@ Moderation
==========
All members and nonmembers have a moderation action, which defaults to the
-list's default action. When the action is not `defer`, the `moderation` rule
-flags the message as needing moderation. This might be to automatically
-accept, discard, reject, or hold the message.
+appropriate list's default action. When the action is not `defer`, the
+`moderation` rule flags the message as needing moderation. This might be to
+automatically accept, discard, reject, or hold the message.
Two separate rules check for member and nonmember moderation. Member
moderation happens early in the built-in chain, while nonmember moderation
@@ -22,15 +22,19 @@ Member moderation
member-moderation
Anne, a mailing list member, sends a message to the mailing list. Her
-postings are not moderated.
-::
+moderation action is not set.
>>> from mailman.testing.helpers import subscribe
- >>> subscribe(mlist, 'Anne')
+ >>> member = subscribe(mlist, 'Anne')
+ >>> member
<Member: Anne Person <aperson@example.com> on test@example.com
as MemberRole.member>
+ >>> print(member.moderation_action)
+ None
+
+Because the list's default member action is set to `defer`, Anne's posting is
+not moderated.
- >>> member = mlist.members.get_member('aperson@example.com')
>>> print(mlist.default_member_action)
Action.defer
@@ -46,8 +50,9 @@ Because Anne is not moderated, the member moderation rule does not match.
False
Once the member's moderation action is set to something other than `defer` or
-``None``, the rule matches. Also, the message metadata has a few extra pieces
-of information for the eventual moderation chain.
+``None`` (given the list's current default member moderation action), the rule
+matches. Also, the message metadata has a few extra pieces of information for
+the eventual moderation chain.
>>> from mailman.interfaces.action import Action
>>> member.moderation_action = Action.hold
@@ -71,20 +76,26 @@ postings are held for moderator approval.
nonmember-moderation
Bart, who is not a member of the mailing list, sends a message to the list.
-::
+He has no explicit nonmember moderation action.
>>> from mailman.interfaces.member import MemberRole
- >>> subscribe(mlist, 'Bart', MemberRole.nonmember)
+ >>> nonmember = subscribe(mlist, 'Bart', MemberRole.nonmember)
+ >>> nonmember
<Member: Bart Person <bperson@example.com> on test@example.com
as MemberRole.nonmember>
+ >>> print(nonmember.moderation_action)
+ None
+
+The list's default nonmember moderation action is to hold postings by
+nonmembers.
- >>> nonmember = mlist.nonmembers.get_member('bperson@example.com')
>>> print(mlist.default_nonmember_action)
Action.hold
-When Bart is registered as a nonmember of the list, his moderation action is
-set to hold by default. Thus the rule matches and the message metadata again
-carries some useful information.
+Since Bart is registered as a nonmember of the list, and his moderation action
+is set to None, the action falls back to the list's default nonmember
+moderation action, which is to hold the post for moderator approval. Thus the
+rule matches and the message metadata again carries some useful information.
>>> nonmember_msg = message_from_string("""\
... From: bperson@example.com
diff --git a/src/mailman/rules/moderation.py b/src/mailman/rules/moderation.py
index 9c89cf0b2..d3dc07a8f 100644
--- a/src/mailman/rules/moderation.py
+++ b/src/mailman/rules/moderation.py
@@ -44,8 +44,9 @@ class MemberModeration:
member = mlist.members.get_member(sender)
if member is None:
return False
- action = (member.moderation_action
- or mlist.default_member_action)
+ action = (mlist.default_member_action
+ if member.moderation_action is None
+ else member.moderation_action)
if action is Action.defer:
# The regular moderation rules apply.
return False
@@ -114,8 +115,9 @@ class NonmemberModeration:
_record_action(msgdata, action, sender,
reason.format(action))
return True
- action = (nonmember.moderation_action
- or mlist.default_nonmember_action)
+ 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
diff --git a/src/mailman/rules/tests/test_moderation.py b/src/mailman/rules/tests/test_moderation.py
index 3e80aeeb5..05bae5e1b 100644
--- a/src/mailman/rules/tests/test_moderation.py
+++ b/src/mailman/rules/tests/test_moderation.py
@@ -160,15 +160,19 @@ MIME-Version: 1.0
A message body.
""")
- # First, the message should get held
+ # First, the message should get held.
msgdata = {}
result = rule.check(self._mlist, msg, msgdata)
self.assertTrue(result)
- self.assertEqual(msgdata.get('moderation_action'), 'hold')
- # Then the list's default nonmember action is changed
+ self.assertEqual(msgdata['moderation_action'], 'hold')
+ # As a side-effect, Anne has been added as a nonmember with a
+ # moderation action that falls back to the list's default.
+ anne = self._mlist.nonmembers.get_member('anne@example.com')
+ self.assertIsNone(anne.moderation_action)
+ # Then the list's default nonmember action is changed.
self._mlist.default_nonmember_action = Action.discard
- msg.replace_header('Message-ID', '<ant2>')
- # This time, the message should be discarded
+ msg.replace_header('Message-ID', '<bee>')
+ # This time, the message should be discarded.
result = rule.check(self._mlist, msg, msgdata)
self.assertTrue(result)
self.assertEqual(msgdata.get('moderation_action'), 'discard')
@@ -178,7 +182,9 @@ A message body.
self._mlist.default_member_action = Action.accept
user_manager = getUtility(IUserManager)
anne = user_manager.create_address('anne@example.com')
- self._mlist.subscribe(anne, MemberRole.member)
+ member = self._mlist.subscribe(anne, MemberRole.member)
+ # Anne's moderation rule falls back to the list default.
+ self.assertIsNone(member.moderation_action)
rule = moderation.MemberModeration()
msg = mfs("""\
From: anne@example.com
@@ -189,15 +195,15 @@ MIME-Version: 1.0
A message body.
""")
- # First, the message should get held
+ # First, the message gets accepted.
msgdata = {}
result = rule.check(self._mlist, msg, msgdata)
self.assertTrue(result)
self.assertEqual(msgdata.get('moderation_action'), 'accept')
- # Then the list's default nonmember action is changed
+ # Then the list's default member action is changed.
self._mlist.default_member_action = Action.hold
- msg.replace_header('Message-ID', '<ant2>')
- # This time, the message should be discarded
+ msg.replace_header('Message-ID', '<bee>')
+ # This time, the message is held.
result = rule.check(self._mlist, msg, msgdata)
self.assertTrue(result)
self.assertEqual(msgdata.get('moderation_action'), 'hold')