summaryrefslogtreecommitdiff
path: root/src/mailman/chains
diff options
context:
space:
mode:
Diffstat (limited to 'src/mailman/chains')
-rw-r--r--src/mailman/chains/builtin.py7
-rw-r--r--src/mailman/chains/docs/moderation.txt82
-rw-r--r--src/mailman/chains/moderation.py (renamed from src/mailman/chains/membermod.py)53
3 files changed, 80 insertions, 62 deletions
diff --git a/src/mailman/chains/builtin.py b/src/mailman/chains/builtin.py
index c81f6700f..48e4bd535 100644
--- a/src/mailman/chains/builtin.py
+++ b/src/mailman/chains/builtin.py
@@ -51,8 +51,9 @@ class BuiltInChain:
('approved', LinkAction.jump, 'accept'),
('emergency', LinkAction.jump, 'hold'),
('loop', LinkAction.jump, 'discard'),
- # Do all of the following before deciding whether to hold the message
- # for moderation.
+ # Determine whether the member or nonmember has an action shortcut.
+ ('moderation', LinkAction.jump, 'moderation'),
+ # Do all of the following before deciding whether to hold the message.
('administrivia', LinkAction.defer, None),
('implicit-dest', LinkAction.defer, None),
('max-recipients', LinkAction.defer, None),
@@ -62,8 +63,6 @@ class BuiltInChain:
('suspicious-header', LinkAction.defer, None),
# Now if any of the above hit, jump to the hold chain.
('any', LinkAction.jump, 'hold'),
- # Hold the message if the sender is a moderated member.
- ('member-moderation', LinkAction.jump, 'member-moderation'),
# Take a detour through the header matching chain, which we'll create
# later.
('truth', LinkAction.detour, 'header-match'),
diff --git a/src/mailman/chains/docs/moderation.txt b/src/mailman/chains/docs/moderation.txt
index c95b8cac4..33bf63df9 100644
--- a/src/mailman/chains/docs/moderation.txt
+++ b/src/mailman/chains/docs/moderation.txt
@@ -8,14 +8,32 @@ moderator approval.
>>> mlist = create_list('test@example.com')
+Members and nonmembers have a *moderation action* which can shortcut the
+normal moderation checks. The built-in chain does just a few checks first,
+such as seeing if the message has a matching `Approved:` header, or if the
+emergency flag has been set on the mailing list, or whether a mail loop has
+been detected.
+
+After those, the moderation action for the sender is checked. Members
+generally have a `defer` action, meaning the normal moderation checks are
+done, but it is also common for first-time posters to have a `hold` action,
+meaning that their messages are held for moderator approval for a while.
+
+Nonmembers almost always have a `hold` action, though some mailing lists may
+choose to set this default action to `discard`, meaning their posts would be
+immediately thrown away.
+
+XXX What about default nonmember actions when the poster has not been
+registered as a nonmember?
+
Member moderation
=================
-Posts by list members are moderated if the member's moderation flag is set.
-The default setting for the moderation flag of new members is determined by
-the mailing list's settings. By default, a mailing list is not set to
-moderate new member postings.
+Posts by list members are moderated if the member's moderation action is not
+deferred. The default setting for the moderation action of new members is
+determined by the mailing list's settings. By default, a mailing list is not
+set to moderate new member postings.
>>> from mailman.app.membership import add_member
>>> from mailman.interfaces.member import DeliveryMode
@@ -23,8 +41,8 @@ moderate new member postings.
... DeliveryMode.regular, 'en')
>>> member
<Member: Anne <anne@example.com> on test@example.com as MemberRole.member>
- >>> member.is_moderated
- False
+ >>> print member.moderation_action
+ Action.defer
In order to find out whether the message is held or accepted, we can subscribe
to Zope events that are triggered on each case.
@@ -68,6 +86,7 @@ built-in chain. No rules hit and so the message is accepted.
approved
emergency
loop
+ moderation
administrivia
implicit-dest
max-recipients
@@ -75,12 +94,14 @@ built-in chain. No rules hit and so the message is accepted.
news-moderation
no-subject
suspicious-header
- member-moderation
-However, when Anne's moderation flag is set, and the list's member moderation
-action is set to `hold`, her post is held for moderation.
+However, when Anne's moderation action is set to `hold`, her post is held for
+moderator approval.
::
+ >>> from mailman.interfaces.action import Action
+ >>> member.moderation_action = Action.hold
+
>>> msg = message_from_string("""\
... From: anne@example.com
... To: test@example.com
@@ -89,33 +110,21 @@ action is set to `hold`, her post is held for moderation.
... This is a test.
... """)
- >>> member.is_moderated = True
- >>> print mlist.member_moderation_action
- Action.hold
-
>>> process(mlist, msg, {}, 'built-in')
<mailman.chains.hold.HoldNotification ...>
<mailman.chains.hold.HoldChain ...>
Subject: badger
Hits:
- member-moderation
+ moderation
Misses:
approved
emergency
loop
- administrivia
- implicit-dest
- max-recipients
- max-size
- news-moderation
- no-subject
- suspicious-header
The list's member moderation action can also be set to `discard`...
::
- >>> from mailman.interfaces.action import Action
- >>> mlist.member_moderation_action = Action.discard
+ >>> member.moderation_action = Action.discard
>>> msg = message_from_string("""\
... From: anne@example.com
@@ -130,22 +139,15 @@ The list's member moderation action can also be set to `discard`...
<mailman.chains.discard.DiscardChain ...>
Subject: cougar
Hits:
- member-moderation
+ moderation
Misses:
approved
emergency
loop
- administrivia
- implicit-dest
- max-recipients
- max-size
- news-moderation
- no-subject
- suspicious-header
... or `reject`.
- >>> mlist.member_moderation_action = Action.reject
+ >>> member.moderation_action = Action.reject
>>> msg = message_from_string("""\
... From: anne@example.com
@@ -160,18 +162,18 @@ The list's member moderation action can also be set to `discard`...
<mailman.chains.reject.RejectChain ...>
Subject: dingo
Hits:
- member-moderation
+ moderation
Misses:
approved
emergency
loop
- administrivia
- implicit-dest
- max-recipients
- max-size
- news-moderation
- no-subject
- suspicious-header
+
+
+Nonmembers
+==========
+
+XXX
+
.. Clean up
>>> zope.event.subscribers.remove(on_chain)
diff --git a/src/mailman/chains/membermod.py b/src/mailman/chains/moderation.py
index 4a220b59d..1b5ab47b6 100644
--- a/src/mailman/chains/membermod.py
+++ b/src/mailman/chains/moderation.py
@@ -15,18 +15,30 @@
# You should have received a copy of the GNU General Public License along with
# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-"""Member moderation chain.
+"""Moderation chain.
-When a member's moderation flag is set, the built-in chain jumps to this
-chain, which just checks the mailing list's member moderation action. Based
-on this value, one of the normal termination chains is jumped to.
+When a member or nonmember posting to the mailing list has a moderation action
+that is not `defer`, the built-in chain jumps to this chain. This chain then
+determines the disposition of the message based on the member's or nonmember's
+moderation action.
+
+For example, these actions jump to the appropriate terminal chain:
+
+ * accept - the message is immediately accepted
+ * hold - the message is held for moderator approval
+ * reject - the message is bounced
+ * discard - the message is immediately thrown away
+
+Note that if the moderation action is `defer` then the normal decisions are
+made as to the disposition of the message. `defer` is the default for
+members, while `hold` is the default for nonmembers.
"""
from __future__ import absolute_import, unicode_literals
__metaclass__ = type
__all__ = [
- 'MemberModerationChain',
+ 'ModerationChain',
]
@@ -40,33 +52,38 @@ from mailman.interfaces.chain import IChain, LinkAction
-class MemberModerationChain:
+class ModerationChain:
"""Dynamically produce a link jumping to the appropriate terminal chain.
The terminal chain will be one of the Accept, Hold, Discard, or Reject
- chains, based on the mailing list's member moderation action setting.
+ chains, based on the member's or nonmember's moderation action setting.
"""
implements(IChain)
- name = 'member-moderation'
- description = _('Member moderation chain')
- is_abstract = False
+ name = 'moderation'
+ description = _('Moderation chain')
def get_links(self, mlist, msg, msgdata):
"""See `IChain`."""
+ # Get the moderation action from the message metadata. It can only be
+ # one of the expected values (i.e. not Action.defer). See the
+ # moderation.py rule for details. This is stored in the metadata as a
+ # string so that it can be stored in the pending table.
+ action = Action[msgdata.get('moderation_action')]
# defer and accept are not valid moderation actions.
- jump_chains = {
+ jump_chain = {
+ Action.accept: 'accept',
+ Action.discard: 'discard',
Action.hold: 'hold',
Action.reject: 'reject',
- Action.discard: 'discard',
- }
- chain_name = jump_chains.get(mlist.member_moderation_action)
- assert chain_name is not None, (
- '{0}: Invalid member_moderation_action: {1}'.format(
- mlist.fqdn_listname, mlist.member_moderation_action))
+ }.get(action)
+ assert jump_chain is not None, (
+ '{0}: Invalid moderation action: {1} for sender: {2}'.format(
+ mlist.fqdn_listname, action,
+ msgdata.get('moderation_sender', '(unknown)')))
truth = config.rules['truth']
- chain = config.chains[chain_name]
+ chain = config.chains[jump_chain]
return iter([
Link(truth, LinkAction.jump, chain),
])