summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Sapiro2016-11-04 22:04:30 -0700
committerMark Sapiro2016-11-04 22:04:30 -0700
commit838f20ddf1b772e19f2ae6dc3a064747f6ab459e (patch)
tree0e49b35e2599fa058261c127d6909a26e4c04ead
parentfdac1fbf0016d53e59d59bee026c27be77bcaccb (diff)
downloadmailman-838f20ddf1b772e19f2ae6dc3a064747f6ab459e.tar.gz
mailman-838f20ddf1b772e19f2ae6dc3a064747f6ab459e.tar.zst
mailman-838f20ddf1b772e19f2ae6dc3a064747f6ab459e.zip
-rw-r--r--src/mailman/chains/builtin.py6
-rw-r--r--src/mailman/rules/dmarc.py23
-rw-r--r--src/mailman/rules/docs/dmarc-moderation.rst123
3 files changed, 32 insertions, 120 deletions
diff --git a/src/mailman/chains/builtin.py b/src/mailman/chains/builtin.py
index f31fb6ed2..76b4716c7 100644
--- a/src/mailman/chains/builtin.py
+++ b/src/mailman/chains/builtin.py
@@ -38,8 +38,10 @@ class BuiltInChain:
description = _('The built-in moderation chain.')
_link_descriptions = (
- # First check DMARC and maybe reject or discard.
- ('dmarc-moderation', LinkAction.defer, None),
+ # First check DMARC. For a reject or discard, the rule hits and we
+ # jump to the moderation chain to do the action. Otherwise, the rule
+ # misses buts sets msgdata['dmarc'] for the handler.
+ ('dmarc-moderation', LinkAction.jump, 'moderation'),
('approved', LinkAction.jump, 'accept'),
('emergency', LinkAction.jump, 'hold'),
('loop', LinkAction.jump, 'discard'),
diff --git a/src/mailman/rules/dmarc.py b/src/mailman/rules/dmarc.py
index 67a8d9045..b22d50ea3 100644
--- a/src/mailman/rules/dmarc.py
+++ b/src/mailman/rules/dmarc.py
@@ -25,8 +25,6 @@ from dns.exception import DNSException
from email.utils import parseaddr
from lazr.config import as_timedelta
from mailman import public
-from mailman.chains.discard import DiscardChain
-from mailman.chains.reject import RejectChain
from mailman.config import config
from mailman.core.i18n import _
from mailman.interfaces.mailinglist import DMARCModerationAction
@@ -246,14 +244,15 @@ class DMARCModeration:
return False
dn, addr = parseaddr(msg.get('from'))
if _IsDMARCProhibited(mlist, addr):
- # This is something of a kludge, but we can't have this rule be
- # a chain in the normal way, because a hit will cause the message
- # to be held. We just flag the hit for the handler, but jump
- # to the reject or discard chain if appropriate.
+ # If dmarc_moderation_action is discard or reject, this rule fires
+ # and jumps to the 'moderation' chain to do the actual discard.
+ # Otherwise, the rule misses but sets a flag for the dmarc handler
+ # to do the appropriate action.
msgdata['dmarc'] = True
if mlist.dmarc_moderation_action == DMARCModerationAction.discard:
- DiscardChain()._process(mlist, msg, msgdata)
- if mlist.dmarc_moderation_action == DMARCModerationAction.reject:
+ msgdata['moderation_action'] = 'discard'
+ msgdata['moderation_reasons'] = _('DMARC moderation')
+ elif mlist.dmarc_moderation_action == DMARCModerationAction.reject:
listowner = mlist.owner_address # noqa F841
reason = (mlist.dmarc_moderation_notice or
_('You are not allowed to post to this mailing '
@@ -263,7 +262,9 @@ class DMARCModeration:
'that your messages are being rejected in error, '
'contact the mailing list owner at ${listowner}.'))
msgdata['moderation_reasons'] = [wrap(reason)]
- # Add the hit for the reject notice.
- msgdata.setdefault('rule_hits', []).append('dmarc-moderation')
- RejectChain()._process(mlist, msg, msgdata)
+ msgdata['moderation_action'] = 'reject'
+ else:
+ return False
+ msgdata['moderation_sender'] = addr
+ return True
return False
diff --git a/src/mailman/rules/docs/dmarc-moderation.rst b/src/mailman/rules/docs/dmarc-moderation.rst
index fb9ac3ac5..c2210011a 100644
--- a/src/mailman/rules/docs/dmarc-moderation.rst
+++ b/src/mailman/rules/docs/dmarc-moderation.rst
@@ -78,12 +78,6 @@ Subdomains which don't have a policy will check the organizational domain.
The list's action can also be set to immediately discard or reject the
message.
- >>> from mailman.interfaces.chain import ChainEvent
- >>> from mailman.testing.helpers import event_subscribers
- >>> def handler(event):
- ... if isinstance(event, ChainEvent):
- ... print(event.__class__.__name__,
- ... event.chain.name, event.msg['message-id'])
>>> mlist.dmarc_moderation_action = DMARCModerationAction.discard
>>> msg = message_from_string("""\
... From: aperson@yahoo.com
@@ -93,12 +87,12 @@ message.
...
... """)
>>> msgdata = {}
- >>> with event_subscribers(handler):
- ... rule.check(mlist, msg, msgdata)
- DiscardEvent discard <xxx_message_id@yahoo.com>
- False
+ >>> rule.check(mlist, msg, msgdata)
+ True
>>> msgdata['dmarc']
True
+ >>> msgdata['moderation_action']
+ 'discard'
We can reject the message with a default reason.
@@ -111,59 +105,14 @@ We can reject the message with a default reason.
...
... """)
>>> msgdata = {}
- >>> with event_subscribers(handler):
- ... rule.check(mlist, msg, msgdata)
- RejectEvent reject <xxx_message_id@yahoo.com>
- False
+ >>> rule.check(mlist, msg, msgdata)
+ True
>>> msgdata['dmarc']
True
-
-There is now a reject message in the virgin queue.
-
- >>> from mailman.testing.helpers import get_queue_messages
- >>> messages = get_queue_messages('virgin')
- >>> len(messages)
- 1
- >>> print(messages[0].msg.as_string())
- Subject: A posted message
- From: _xtest-owner@example.com
- To: aperson@yahoo.com
- MIME-Version: 1.0
- Content-Type: multipart/mixed; boundary="..."
- Message-ID: <...>
- Date: ...
- Precedence: bulk
- <BLANKLINE>
- --...
- Content-Type: text/plain; charset="us-ascii"
- MIME-Version: 1.0
- Content-Transfer-Encoding: 7bit
- <BLANKLINE>
- <BLANKLINE>
- Your message to the _xtest mailing-list was rejected for the following
- reasons:
- <BLANKLINE>
- You are not allowed to post to this mailing list From: a domain which
- publishes a DMARC policy of reject or quarantine, and your message has
- been automatically rejected. If you think that your messages are
- being rejected in error, contact the mailing list owner at
- _xtest-owner@example.com.
- <BLANKLINE>
- The original message as received by Mailman is attached.
- <BLANKLINE>
- --...
- Content-Type: message/rfc822
- MIME-Version: 1.0
- <BLANKLINE>
- From: aperson@yahoo.com
- To: _xtest@example.com
- Subject: A posted message
- Message-ID: <xxx_message_id@yahoo.com>
- X-Mailman-Rule-Hits: dmarc-moderation
- <BLANKLINE>
- <BLANKLINE>
- --...--
- <BLANKLINE>
+ >>> msgdata['moderation_action']
+ 'reject'
+ >>> msgdata['moderation_reasons']
+ ['You are not allowed to post to this mailing list From: a domain ...
And, we can reject with a custom message.
@@ -176,51 +125,11 @@ And, we can reject with a custom message.
...
... """)
>>> msgdata = {}
- >>> with event_subscribers(handler):
- ... rule.check(mlist, msg, msgdata)
- RejectEvent reject <xxx_message_id@yahoo.com>
- False
+ >>> rule.check(mlist, msg, msgdata)
+ True
>>> msgdata['dmarc']
True
-
-Check the the virgin queue.
-
- >>> messages = get_queue_messages('virgin')
- >>> len(messages)
- 1
- >>> print(messages[0].msg.as_string())
- Subject: A posted message
- From: _xtest-owner@example.com
- To: aperson@yahoo.com
- MIME-Version: 1.0
- Content-Type: multipart/mixed; boundary="..."
- Message-ID: <...>
- Date: ...
- Precedence: bulk
- <BLANKLINE>
- --...
- Content-Type: text/plain; charset="us-ascii"
- MIME-Version: 1.0
- Content-Transfer-Encoding: 7bit
- <BLANKLINE>
- <BLANKLINE>
- Your message to the _xtest mailing-list was rejected for the following
- reasons:
- <BLANKLINE>
- A silly reason
- <BLANKLINE>
- The original message as received by Mailman is attached.
- <BLANKLINE>
- --...
- Content-Type: message/rfc822
- MIME-Version: 1.0
- <BLANKLINE>
- From: aperson@yahoo.com
- To: _xtest@example.com
- Subject: A posted message
- Message-ID: <xxx_message_id@yahoo.com>
- X-Mailman-Rule-Hits: dmarc-moderation
- <BLANKLINE>
- <BLANKLINE>
- --...--
- <BLANKLINE>
+ >>> msgdata['moderation_action']
+ 'reject'
+ >>> msgdata['moderation_reasons']
+ ['A silly reason']