summaryrefslogtreecommitdiff
path: root/src/mailman/rules/docs
diff options
context:
space:
mode:
authorBarry Warsaw2012-04-04 23:43:40 -0600
committerBarry Warsaw2012-04-04 23:43:40 -0600
commit180d4968c277b533507db04bb9d363c6a65a2af5 (patch)
tree4dc689635e93688a2f9a5e8e2eb3566167193006 /src/mailman/rules/docs
parent53633149a247243efe830d7175906dc204423f41 (diff)
downloadmailman-180d4968c277b533507db04bb9d363c6a65a2af5.tar.gz
mailman-180d4968c277b533507db04bb9d363c6a65a2af5.tar.zst
mailman-180d4968c277b533507db04bb9d363c6a65a2af5.zip
Diffstat (limited to 'src/mailman/rules/docs')
-rw-r--r--src/mailman/rules/docs/approved.rst297
1 files changed, 83 insertions, 214 deletions
diff --git a/src/mailman/rules/docs/approved.rst b/src/mailman/rules/docs/approved.rst
index 3e1206563..9c61a7419 100644
--- a/src/mailman/rules/docs/approved.rst
+++ b/src/mailman/rules/docs/approved.rst
@@ -2,20 +2,27 @@
Pre-approved postings
=====================
-Messages can contain a pre-approval, which is used to bypass the message
-approval queue. This has several use cases:
+Messages can contain a pre-approval, which is used to bypass the normal
+message approval queue. This has several use cases:
-- A list administrator can send an emergency message to the mailing list from
- an unregistered address, say if they are away from their normal email.
+ - A list administrator can send an emergency message to the mailing list
+ from an unregistered address, for example if they are away from their
+ normal email.
-- An automated script can be programmed to send a message to an otherwise
- moderated list.
+ - An automated script can be programmed to send a message to an otherwise
+ moderated list.
In order to support this, a mailing list can be given a *moderator password*
which is shared among all the administrators.
- >>> mlist = create_list('_xtest@example.com')
- >>> mlist.moderator_password = 'abcxyz'
+ >>> mlist = create_list('test@example.com')
+
+This password will not be stored in clear text, so it must be hashed using the
+configured hash protocol.
+
+ >>> from flufl.password import lookup, make_secret
+ >>> scheme = lookup(config.passwords.password_scheme.upper())
+ >>> mlist.moderator_password = make_secret('super secret', scheme)
The ``approved`` rule determines whether the message contains the proper
approval or not.
@@ -28,8 +35,8 @@ approval or not.
No approval
===========
-If the message has no ``Approve:`` or ``Approved:`` header (or their ``X-``
-equivalents), then the rule does not match.
+The preferred header to check for approval is ``Approved:``. If the message
+does not have this header, the rule will not match.
>>> msg = message_from_string("""\
... From: aperson@example.com
@@ -39,123 +46,95 @@ equivalents), then the rule does not match.
>>> rule.check(mlist, msg, {})
False
-If the message has an ``Approve:``, ``Approved:``, ``X-Approve:``, or
-``X-Approved:`` header with a value that does not match the moderator
-password, then the rule does not match. However, the header is still removed.
-::
+If the rule has an ``Approved`` header, but the value of this header does not
+match the moderator password, the rule will not match. Note that the header
+must contain the clear text version of the password.
- >>> msg['Approve'] = '12345'
+ >>> msg['Approved'] = 'not the password'
>>> rule.check(mlist, msg, {})
False
- >>> print msg['approve']
- None
- >>> del msg['approve']
- >>> msg['Approved'] = '12345'
- >>> rule.check(mlist, msg, {})
- False
- >>> print msg['approved']
- None
- >>> del msg['approved']
- >>> msg['X-Approve'] = '12345'
- >>> rule.check(mlist, msg, {})
- False
- >>> print msg['x-approve']
- None
+The message is approved
+=======================
- >>> del msg['x-approve']
- >>> msg['X-Approved'] = '12345'
- >>> rule.check(mlist, msg, {})
- False
- >>> print msg['x-approved']
- None
+By adding an ``Approved`` header with a matching password, the rule will
+match.
- >>> del msg['x-approved']
+ >>> del msg['approved']
+ >>> msg['Approved'] = 'super secret'
+ >>> rule.check(mlist, msg, {})
+ True
-Using an approval header
-========================
+Alternative headers
+===================
-If the moderator password is given in an ``Approve:`` header, then the rule
-matches, and the ``Approve:`` header is stripped.
+Other headers can be used to stash the moderator password. This rule also
+checks the ``Approve`` header.
- >>> msg['Approve'] = 'abcxyz'
+ >>> del msg['approved']
+ >>> msg['Approve'] = 'super secret'
>>> rule.check(mlist, msg, {})
True
- >>> print msg['approve']
- None
-Similarly, for the ``Approved:`` header.
+Similarly, an ``X-Approved`` header can be used.
>>> del msg['approve']
- >>> msg['Approved'] = 'abcxyz'
+ >>> msg['X-Approved'] = 'super secret'
>>> rule.check(mlist, msg, {})
True
- >>> print msg['approved']
- None
-The headers ``X-Approve:`` and ``X-Approved:`` are treated the same way.
-::
+And finally, an ``X-Approve`` header can be used.
- >>> del msg['approved']
- >>> msg['X-Approve'] = 'abcxyz'
+ >>> del msg['x-approved']
+ >>> msg['X-Approve'] = 'super secret'
>>> rule.check(mlist, msg, {})
True
- >>> print msg['x-approve']
- None
- >>> del msg['x-approve']
- >>> msg['X-Approved'] = 'abcxyz'
+
+Removal of header
+=================
+
+Technically, rules should not have side-effects, however this rule does remove
+the ``Approved`` header (LP: #973790) when it matches.
+
+ >>> del msg['x-approved']
+ >>> msg['Approved'] = 'super secret'
>>> rule.check(mlist, msg, {})
True
- >>> print msg['x-approved']
+ >>> print msg['approved']
None
- >>> del msg['x-approved']
+It also removes the header when it doesn't match. If the rule didn't do this,
+then the mailing list could be probed for its moderator password.
+
+ >>> msg['Approved'] = 'not the password'
+ >>> rule.check(mlist, msg, {})
+ False
+ >>> print msg['approved']
+ None
Using a pseudo-header
=====================
-Different mail user agents have varying degrees to which they support custom
-headers like ``Approve:`` and ``Approved:``. For this reason, Mailman also
-supports using a *pseudo-header*, which is really just the first
-non-whitespace line in the payload of the message. If this pseudo-header
-looks like a matching ``Approve:`` or ``Approved:`` header, the message is
-similarly allowed to pass.
+Mail programs have varying degrees to which they support custom headers like
+``Approved:``. For this reason, Mailman also supports using a
+*pseudo-header*, which is really just the first non-whitespace line in the
+payload of the message. If this pseudo-header looks like a matching
+``Approved:`` header, the message is similarly allowed to pass.
>>> msg = message_from_string("""\
... From: aperson@example.com
...
- ... Approve: abcxyz
+ ... Approved: super secret
... An important message.
... """)
>>> rule.check(mlist, msg, {})
True
-The pseudo-header is removed.
-
- >>> print msg.as_string()
- From: aperson@example.com
- Content-Transfer-Encoding: 7bit
- MIME-Version: 1.0
- Content-Type: text/plain; charset="us-ascii"
- <BLANKLINE>
- An important message.
- <BLANKLINE>
-
-Similarly for the ``Approved:`` header.
-::
-
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ...
- ... Approved: abcxyz
- ... An important message.
- ... """)
- >>> rule.check(mlist, msg, {})
- True
+The pseudo-header is always removed from the body of plain text messages.
>>> print msg.as_string()
From: aperson@example.com
@@ -173,28 +152,7 @@ the pseudo-header line is still removed.
>>> msg = message_from_string("""\
... From: aperson@example.com
...
- ... Approve: 123456
- ... An important message.
- ... """)
- >>> rule.check(mlist, msg, {})
- False
-
- >>> print msg.as_string()
- From: aperson@example.com
- Content-Transfer-Encoding: 7bit
- MIME-Version: 1.0
- Content-Type: text/plain; charset="us-ascii"
- <BLANKLINE>
- An important message.
- <BLANKLINE>
-
-Similarly for the ``Approved:`` header.
-::
-
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ...
- ... Approved: 123456
+ ... Approved: not the password
... An important message.
... """)
>>> rule.check(mlist, msg, {})
@@ -225,13 +183,13 @@ be used with MIME documents.
... --AAA
... Content-Type: application/x-ignore
...
- ... Approve: 123456
+ ... Approved: not the password
... The above line will be ignored.
...
... --AAA
... Content-Type: text/plain
...
- ... Approve: abcxyz
+ ... Approved: super secret
... An important message.
... --AAA--
... """)
@@ -248,52 +206,7 @@ Like before, the pseudo-header is removed, but only from the text parts.
--AAA
Content-Type: application/x-ignore
<BLANKLINE>
- Approve: 123456
- The above line will be ignored.
- <BLANKLINE>
- --AAA
- Content-Transfer-Encoding: 7bit
- MIME-Version: 1.0
- Content-Type: text/plain; charset="us-ascii"
- <BLANKLINE>
- An important message.
- --AAA--
- <BLANKLINE>
-
-The same goes for the ``Approved:`` message.
-
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ... MIME-Version: 1.0
- ... Content-Type: multipart/mixed; boundary="AAA"
- ...
- ... --AAA
- ... Content-Type: application/x-ignore
- ...
- ... Approved: 123456
- ... The above line will be ignored.
- ...
- ... --AAA
- ... Content-Type: text/plain
- ...
- ... Approved: abcxyz
- ... An important message.
- ... --AAA--
- ... """)
- >>> rule.check(mlist, msg, {})
- True
-
-And the header is removed.
-
- >>> print msg.as_string()
- From: aperson@example.com
- MIME-Version: 1.0
- Content-Type: multipart/mixed; boundary="AAA"
- <BLANKLINE>
- --AAA
- Content-Type: application/x-ignore
- <BLANKLINE>
- Approved: 123456
+ Approved: not the password
The above line will be ignored.
<BLANKLINE>
--AAA
@@ -305,51 +218,7 @@ And the header is removed.
--AAA--
<BLANKLINE>
-Here, the correct password is in the non-``text/plain`` part, so it is ignored.
-
- >>> msg = message_from_string("""\
- ... From: aperson@example.com
- ... MIME-Version: 1.0
- ... Content-Type: multipart/mixed; boundary="AAA"
- ...
- ... --AAA
- ... Content-Type: application/x-ignore
- ...
- ... Approve: abcxyz
- ... The above line will be ignored.
- ...
- ... --AAA
- ... Content-Type: text/plain
- ...
- ... Approve: 123456
- ... An important message.
- ... --AAA--
- ... """)
- >>> rule.check(mlist, msg, {})
- False
-
-And yet the pseudo-header is still stripped.
-
- >>> print msg.as_string()
- From: aperson@example.com
- MIME-Version: 1.0
- Content-Type: multipart/mixed; boundary="AAA"
- <BLANKLINE>
- --AAA
- Content-Type: application/x-ignore
- <BLANKLINE>
- Approve: abcxyz
- The above line will be ignored.
- <BLANKLINE>
- --AAA
- Content-Transfer-Encoding: 7bit
- MIME-Version: 1.0
- Content-Type: text/plain; charset="us-ascii"
- <BLANKLINE>
- An important message.
- --AAA--
-
-As before, the same goes for the ``Approved:`` header.
+If the correct password is in the non-``text/plain`` part, it is ignored.
>>> msg = message_from_string("""\
... From: aperson@example.com
@@ -359,20 +228,20 @@ As before, the same goes for the ``Approved:`` header.
... --AAA
... Content-Type: application/x-ignore
...
- ... Approved: abcxyz
+ ... Approved: super secret
... The above line will be ignored.
...
... --AAA
... Content-Type: text/plain
...
- ... Approved: 123456
+ ... Approved: not the password
... An important message.
... --AAA--
... """)
>>> rule.check(mlist, msg, {})
False
-And the pseudo-header is removed.
+Pseudo-header is still stripped, but only from the ``text/plain`` part.
>>> print msg.as_string()
From: aperson@example.com
@@ -382,7 +251,7 @@ And the pseudo-header is removed.
--AAA
Content-Type: application/x-ignore
<BLANKLINE>
- Approved: abcxyz
+ Approved: super secret
The above line will be ignored.
<BLANKLINE>
--AAA
@@ -397,10 +266,9 @@ And the pseudo-header is removed.
Stripping text/html parts
=========================
-Because some mail readers will include both a ``text/plain`` part and a
-``text/html`` alternative, the ``approved`` rule has to search the
-alternatives and strip anything that looks like an ``Approve:`` or
-``Approved:`` headers.
+Because some mail programs will include both a ``text/plain`` part and a
+``text/html`` alternative, the rule must search the alternatives and strip
+anything that looks like an ``Approved:`` header.
>>> msg = message_from_string("""\
... From: aperson@example.com
@@ -413,7 +281,7 @@ alternatives and strip anything that looks like an ``Approve:`` or
... <html>
... <head></head>
... <body>
- ... <b>Approved: abcxyz</b>
+ ... <b>Approved: super secret</b>
... <p>The above line will be ignored.
... </body>
... </html>
@@ -421,7 +289,7 @@ alternatives and strip anything that looks like an ``Approve:`` or
... --AAA
... Content-Type: text/plain
...
- ... Approved: abcxyz
+ ... Approved: super secret
... An important message.
... --AAA--
... """)
@@ -457,7 +325,8 @@ And the header-like text in the ``text/html`` part was stripped.
--AAA--
<BLANKLINE>
-This is true even if the rule does not match.
+This is true even if the rule does not match (i.e. the incorrect password was
+given).
::
>>> msg = message_from_string("""\
@@ -471,7 +340,7 @@ This is true even if the rule does not match.
... <html>
... <head></head>
... <body>
- ... <b>Approve: 123456</b>
+ ... <b>Approved: not the password</b>
... <p>The above line will be ignored.
... </body>
... </html>
@@ -479,7 +348,7 @@ This is true even if the rule does not match.
... --AAA
... Content-Type: text/plain
...
- ... Approve: 123456
+ ... Approved: not the password
... An important message.
... --AAA--
... """)