summaryrefslogtreecommitdiff
path: root/Mailman/rules
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/rules')
-rw-r--r--Mailman/rules/docs/administrivia.txt3
-rw-r--r--Mailman/rules/docs/approve.txt3
-rw-r--r--Mailman/rules/docs/emergency.txt77
-rw-r--r--Mailman/rules/docs/implicit-dest.txt3
-rw-r--r--Mailman/rules/docs/loop.txt3
-rw-r--r--Mailman/rules/docs/max-size.txt3
-rw-r--r--Mailman/rules/docs/moderation.txt5
-rw-r--r--Mailman/rules/docs/news-moderation.txt3
-rw-r--r--Mailman/rules/docs/no-subject.txt3
-rw-r--r--Mailman/rules/docs/recipients.txt3
-rw-r--r--Mailman/rules/docs/rules.txt96
-rw-r--r--Mailman/rules/docs/suspicious.txt3
-rw-r--r--Mailman/rules/emergency.py2
13 files changed, 116 insertions, 91 deletions
diff --git a/Mailman/rules/docs/administrivia.txt b/Mailman/rules/docs/administrivia.txt
index 0e48fdd1b..de802fa85 100644
--- a/Mailman/rules/docs/administrivia.txt
+++ b/Mailman/rules/docs/administrivia.txt
@@ -9,8 +9,7 @@ used to catch messages posted to the list which should have been sent to the
>>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
>>> mlist.administrivia = True
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('administrivia')
+ >>> rule = config.rules['administrivia']
>>> rule.name
'administrivia'
diff --git a/Mailman/rules/docs/approve.txt b/Mailman/rules/docs/approve.txt
index ea07058f8..32367a76b 100644
--- a/Mailman/rules/docs/approve.txt
+++ b/Mailman/rules/docs/approve.txt
@@ -20,8 +20,7 @@ which is shared among all the administrators.
The 'approved' rule determines whether the message contains the proper
approval or not.
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('approved')
+ >>> rule = config.rules['approved']
>>> rule.name
'approved'
diff --git a/Mailman/rules/docs/emergency.txt b/Mailman/rules/docs/emergency.txt
new file mode 100644
index 000000000..685d7bcb6
--- /dev/null
+++ b/Mailman/rules/docs/emergency.txt
@@ -0,0 +1,77 @@
+Emergency
+=========
+
+When the mailing list has its emergency flag set, all messages posted to the
+list are held for moderator approval.
+
+ >>> from Mailman.app.lifecycle import create_list
+ >>> mlist = create_list(u'_xtest@example.com')
+ >>> mlist.web_page_url = u'http://www.example.com/'
+ >>> msg = message_from_string("""\
+ ... From: aperson@example.com
+ ... To: _xtest@example.com
+ ... Subject: My first post
+ ... Message-ID: <first>
+ ...
+ ... An important message.
+ ... """)
+
+The emergency rule is matched as part of the built-in chain.
+
+ >>> from Mailman.configuration import config
+ >>> chain = config.chains['built-in']
+
+The emergency rule matches if the flag is set on the mailing list.
+
+ >>> mlist.emergency = True
+ >>> chain.process(mlist, msg, {})
+
+There are two messages in the virgin queue. The one addressed to the original
+sender will contain a token we can use to grab the held message out of the
+pending requests.
+
+ >>> from Mailman.queue import Switchboard
+ >>> virginq = Switchboard(config.VIRGINQUEUE_DIR)
+
+ >>> def get_held_message():
+ ... import re
+ ... qfiles = []
+ ... for filebase in virginq.files:
+ ... qmsg, qdata = virginq.dequeue(filebase)
+ ... virginq.finish(filebase)
+ ... qfiles.append(qmsg)
+ ... from operator import itemgetter
+ ... qfiles.sort(key=itemgetter('to'))
+ ... cookie = None
+ ... for line in qfiles[1].get_payload().splitlines():
+ ... mo = re.search('confirm/[^/]+/(?P<cookie>.*)$', line)
+ ... if mo:
+ ... cookie = mo.group('cookie')
+ ... break
+ ... assert cookie is not None, 'No confirmation token found'
+ ... data = config.db.pendings.confirm(cookie)
+ ... requestdb = config.db.requests.get_list_requests(mlist)
+ ... rkey, rdata = requestdb.get_request(data['id'])
+ ... return config.db.message_store.get_message_by_id(
+ ... rdata['_mod_message_id'])
+
+ >>> msg = get_held_message()
+ >>> print msg.as_string()
+ From: aperson@example.com
+ To: _xtest@example.com
+ Subject: My first post
+ Message-ID: <first>
+ X-Mailman-Rule-Hits: emergency
+ X-Mailman-Rule-Misses: approved
+ X-Message-ID-Hash: RXJU4JL6N2OUN3OYMXXPPSCR7P7JE2BW
+ <BLANKLINE>
+ An important message.
+ <BLANKLINE>
+
+However, if the message metadata has a 'moderator_approved' key set, then even
+if the mailing list has its emergency flag set, the message still goes through
+to the membership.
+
+ >>> chain.process(mlist, msg, dict(moderator_approved=True))
+ >>> len(virginq.files)
+ 0
diff --git a/Mailman/rules/docs/implicit-dest.txt b/Mailman/rules/docs/implicit-dest.txt
index b6fed2769..5a7f06c0c 100644
--- a/Mailman/rules/docs/implicit-dest.txt
+++ b/Mailman/rules/docs/implicit-dest.txt
@@ -6,8 +6,7 @@ not explicitly mentioned in the set of message recipients.
>>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('implicit-dest')
+ >>> rule = config.rules['implicit-dest']
>>> rule.name
'implicit-dest'
diff --git a/Mailman/rules/docs/loop.txt b/Mailman/rules/docs/loop.txt
index 3174805b9..8fe86cf45 100644
--- a/Mailman/rules/docs/loop.txt
+++ b/Mailman/rules/docs/loop.txt
@@ -6,8 +6,7 @@ X-BeenThere header with the value of the list's posting address.
>>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('loop')
+ >>> rule = config.rules['loop']
>>> rule.name
'loop'
diff --git a/Mailman/rules/docs/max-size.txt b/Mailman/rules/docs/max-size.txt
index b477ecd2b..0d64b0cf7 100644
--- a/Mailman/rules/docs/max-size.txt
+++ b/Mailman/rules/docs/max-size.txt
@@ -8,8 +8,7 @@ bytes).
>>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('max-size')
+ >>> rule = config.rules['max-size']
>>> rule.name
'max-size'
diff --git a/Mailman/rules/docs/moderation.txt b/Mailman/rules/docs/moderation.txt
index 0ce6bee6e..cab8f20d3 100644
--- a/Mailman/rules/docs/moderation.txt
+++ b/Mailman/rules/docs/moderation.txt
@@ -8,8 +8,7 @@ email the list without having those messages be held for approval. The
>>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('moderation')
+ >>> rule = config.rules['moderation']
>>> rule.name
'moderation'
@@ -50,7 +49,7 @@ Non-members
There is another, related rule for matching non-members, which simply matches
if the sender is /not/ a member of the mailing list.
- >>> rule = find_rule('non-member')
+ >>> rule = config.rules['non-member']
>>> rule.name
'non-member'
diff --git a/Mailman/rules/docs/news-moderation.txt b/Mailman/rules/docs/news-moderation.txt
index f69fbb33d..f32919ce5 100644
--- a/Mailman/rules/docs/news-moderation.txt
+++ b/Mailman/rules/docs/news-moderation.txt
@@ -10,8 +10,7 @@ directly to the mailing list.
>>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('news-moderation')
+ >>> rule = config.rules['news-moderation']
>>> rule.name
'news-moderation'
diff --git a/Mailman/rules/docs/no-subject.txt b/Mailman/rules/docs/no-subject.txt
index 3c6dc88bf..3627ac03f 100644
--- a/Mailman/rules/docs/no-subject.txt
+++ b/Mailman/rules/docs/no-subject.txt
@@ -6,8 +6,7 @@ the empty string when stripped.
>>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('no-subject')
+ >>> rule = config.rules['no-subject']
>>> rule.name
'no-subject'
diff --git a/Mailman/rules/docs/recipients.txt b/Mailman/rules/docs/recipients.txt
index 98176c8bb..21d04b8ae 100644
--- a/Mailman/rules/docs/recipients.txt
+++ b/Mailman/rules/docs/recipients.txt
@@ -6,8 +6,7 @@ number of explicit recipients addressed by the message.
>>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('max-recipients')
+ >>> rule = config.rules['max-recipients']
>>> rule.name
'max-recipients'
diff --git a/Mailman/rules/docs/rules.txt b/Mailman/rules/docs/rules.txt
index b9606663c..1f5b147e7 100644
--- a/Mailman/rules/docs/rules.txt
+++ b/Mailman/rules/docs/rules.txt
@@ -1,63 +1,41 @@
Rules
=====
-The rule processor is used to determine the status of a message. Should the
-message be posted to the list, or held for moderator approval? Should the
-message be discarded or rejected (i.e. bounced back to the original sender)?
+Rules are applied to each message as part of a rule chain. Individual rules
+simply return a boolean specifying whether the rule matches or not. Chain
+links determine what happens when a rule matches.
-Actually, these actions are not part of rule processing! Instead, Mailman
-first runs through the set of available and requested rules looking for
-matches. Then later, the matched rules are prioritized and matched to an
-action. Action matching is described elsewhere; this documentation describes
-only the rule processing system.
-
-Rule sets
+All rules
---------
-IRuleSet is the interface that describes a set of rules. Mailman can be
-extended by plugging in additional rule sets, but it also comes with a default
-rule set, called the 'built-in rule set'.
+Rules are maintained in the configuration object as a dictionary mapping rule
+names to rule objects.
>>> from zope.interface.verify import verifyObject
- >>> from Mailman.interfaces import IRuleSet
- >>> from Mailman.rules import BuiltinRules
- >>> rule_set = BuiltinRules()
- >>> verifyObject(IRuleSet, rule_set)
- True
-
-You can iterator over all the rules in a rule set.
-
+ >>> from Mailman.configuration import config
>>> from Mailman.interfaces import IRule
- >>> rule = None
- >>> for rule in rule_set.rules:
- ... if rule.name == 'emergency':
- ... break
- >>> verifyObject(IRule, rule)
- True
- >>> rule.name
- 'emergency'
- >>> print rule.description
- The mailing list is in emergency hold and this message was not pre-approved
- by the list administrator.
+ >>> for rule_name in sorted(config.rules):
+ ... rule = config.rules[rule_name]
+ ... print rule_name, verifyObject(IRule, rule)
+ administrivia True
+ any True
+ approved True
+ emergency True
+ implicit-dest True
+ loop True
+ max-recipients True
+ max-size True
+ moderation True
+ news-moderation True
+ no-subject True
+ non-member True
+ suspicious-header True
-You can ask for a rule by name.
+You can get a rule by name.
- >>> rule_set['emergency'].name
- 'emergency'
- >>> rule_set.get('emergency').name
- 'emergency'
-
-Rule sets act like dictionaries when the rule is missing.
-
- >>> rule_set['no such rule']
- Traceback (most recent call last):
- ...
- KeyError: 'no such rule'
- >>> print rule_set.get('no such rule')
- None
- >>> missing = object()
- >>> rule_set.get('no such rule', missing) is missing
+ >>> rule = config.rules['emergency']
+ >>> verifyObject(IRule, rule)
True
@@ -68,7 +46,6 @@ Individual rules can be checked to see if they match, by running the rule's
`check()` method. This returns a boolean indicating whether the rule was
matched or not.
- >>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
>>> msg = message_from_string("""\
... From: aperson@example.com
@@ -80,7 +57,6 @@ For example, the emergency rule just checks to see if the emergency flag is
set on the mailing list, and the message has not been pre-approved by the list
administrator.
- >>> rule = rule_set['emergency']
>>> rule.name
'emergency'
>>> mlist.emergency = False
@@ -89,23 +65,5 @@ administrator.
>>> mlist.emergency = True
>>> rule.check(mlist, msg, {})
True
- >>> rule.check(mlist, msg, dict(adminapproved=True))
+ >>> rule.check(mlist, msg, dict(moderator_approved=True))
False
-
-
-Rule processing
----------------
-
-Mailman has a global rule processor which will return a set of all the rule
-names that match the current message. You can limit the set of rules the
-processor will check by passing in a set of requested rule names.
-
- >>> emergency_only = set(['emergency'])
- >>> from Mailman.app.rules import process
- >>> process(mlist, msg, {}, emergency_only)
- set(['emergency'])
- >>> process(mlist, msg, dict(adminapproved=True), emergency_only)
- set([])
- >>> mlist.emergency = False
- >>> process(mlist, msg, {}, emergency_only)
- set([])
diff --git a/Mailman/rules/docs/suspicious.txt b/Mailman/rules/docs/suspicious.txt
index 8646e1b81..6b0eeda35 100644
--- a/Mailman/rules/docs/suspicious.txt
+++ b/Mailman/rules/docs/suspicious.txt
@@ -7,8 +7,7 @@ confusing to users, and the list attribute that controls this is misnamed.
>>> from Mailman.configuration import config
>>> mlist = config.db.list_manager.create(u'_xtest@example.com')
- >>> from Mailman.app.rules import find_rule
- >>> rule = find_rule('suspicious-header')
+ >>> rule = config.rules['suspicious-header']
>>> rule.name
'suspicious-header'
diff --git a/Mailman/rules/emergency.py b/Mailman/rules/emergency.py
index e51612940..0e6aa97b4 100644
--- a/Mailman/rules/emergency.py
+++ b/Mailman/rules/emergency.py
@@ -39,4 +39,4 @@ the list administrator.""")
def check(self, mlist, msg, msgdata):
"""See `IRule`."""
- return mlist.emergency and not msgdata.get('adminapproved')
+ return mlist.emergency and not msgdata.get('moderator_approved')