diff options
| author | Barry Warsaw | 2012-04-04 23:43:40 -0600 |
|---|---|---|
| committer | Barry Warsaw | 2012-04-04 23:43:40 -0600 |
| commit | 180d4968c277b533507db04bb9d363c6a65a2af5 (patch) | |
| tree | 4dc689635e93688a2f9a5e8e2eb3566167193006 /src/mailman/rules/docs | |
| parent | 53633149a247243efe830d7175906dc204423f41 (diff) | |
| download | mailman-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.rst | 297 |
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-- ... """) |
