diff options
| author | Barry Warsaw | 2007-06-19 18:42:27 -0400 |
|---|---|---|
| committer | Barry Warsaw | 2007-06-19 18:42:27 -0400 |
| commit | 3a86b40fe4e3b28c2d9f4e3bbd2cc0eeefe31453 (patch) | |
| tree | e7bb34c284974cb38fce21cc5ad0d28fc50a3a98 | |
| parent | 0514aa46113f1f44dcf86f2d8ae6f86b71e88a3d (diff) | |
| download | mailman-3a86b40fe4e3b28c2d9f4e3bbd2cc0eeefe31453.tar.gz mailman-3a86b40fe4e3b28c2d9f4e3bbd2cc0eeefe31453.tar.zst mailman-3a86b40fe4e3b28c2d9f4e3bbd2cc0eeefe31453.zip | |
| -rw-r--r-- | Mailman/Handlers/Cleanse.py | 6 | ||||
| -rw-r--r-- | Mailman/docs/cleanse.txt | 110 | ||||
| -rw-r--r-- | Mailman/testing/test_cleanse.py | 32 | ||||
| -rw-r--r-- | Mailman/testing/test_handlers.py | 65 |
4 files changed, 145 insertions, 68 deletions
diff --git a/Mailman/Handlers/Cleanse.py b/Mailman/Handlers/Cleanse.py index cb148c8c0..d84f988e3 100644 --- a/Mailman/Handlers/Cleanse.py +++ b/Mailman/Handlers/Cleanse.py @@ -39,15 +39,15 @@ def process(mlist, msg, msgdata): # We remove other headers from anonymous lists if mlist.anonymous_list: log.info('post to %s from %s anonymized', - mlist.internal_name(), msg.get('from')) + mlist.fqdn_listname, msg.get('from')) del msg['from'] del msg['reply-to'] del msg['sender'] # Hotmail sets this one del msg['x-originating-email'] i18ndesc = str(uheader(mlist, mlist.description, 'From')) - msg['From'] = formataddr((i18ndesc, mlist.GetListEmail())) - msg['Reply-To'] = mlist.GetListEmail() + msg['From'] = formataddr((i18ndesc, mlist.posting_address)) + msg['Reply-To'] = mlist.posting_address # Some headers can be used to fish for membership del msg['return-receipt-to'] del msg['disposition-notification-to'] diff --git a/Mailman/docs/cleanse.txt b/Mailman/docs/cleanse.txt new file mode 100644 index 000000000..85b636737 --- /dev/null +++ b/Mailman/docs/cleanse.txt @@ -0,0 +1,110 @@ +Cleansing headers +================= + +All messages posted to a list get their headers cleansed. Some headers are +related to additional permissions that can be granted to the message and other +headers can be used to fish for membership. + + >>> from email import message_from_string + >>> from Mailman.Message import Message + >>> from Mailman.Handlers.Cleanse import process + >>> from Mailman.configuration import config + >>> from Mailman.database import flush + >>> mlist = config.list_manager.create('_xtest@example.com') + >>> flush() + +Headers such as Approved, Approve, and Urgent are used to grant special +pemissions to individual messages. All may contain a password; the first two +headers are used by list administrators to pre-approve a message normal held +for approval. The latter header is used to send a regular message to all +members, regardless of whether they get digests or not. Because all three +headers contain passwords, they must be removed from any posted message. + + >>> msg = message_from_string("""\ + ... From: aperson@example.com + ... Approved: foobar + ... Approve: barfoo + ... Urgent: notreally + ... Subject: A message of great import + ... + ... Blah blah blah + ... """, Message) + >>> process(mlist, msg, {}) + >>> print msg.as_string() + From: aperson@example.com + Subject: A message of great import + <BLANKLINE> + Blah blah blah + <BLANKLINE> + +Other headers can be used by list members to fish the list for membership, so +we don't let them go through. These are a mix of standard headers and custom +headers supported by some mail readers. For example, X-PMRC is supported by +Pegasus mail. I don't remember what program uses X-Confirm-Reading-To though +(Some Microsoft product perhaps?). + + >>> msg = message_from_string("""\ + ... From: bperson@example.com + ... Reply-To: bperson@example.org + ... Sender: asystem@example.net + ... Return-Receipt-To: another@example.com + ... Disposition-Notification-To: athird@example.com + ... X-Confirm-Reading-To: afourth@example.com + ... X-PMRQC: afifth@example.com + ... Subject: a message to you + ... + ... How are you doing? + ... """, Message) + >>> process(mlist, msg, {}) + >>> print msg.as_string() + From: bperson@example.com + Reply-To: bperson@example.org + Sender: asystem@example.net + Subject: a message to you + <BLANKLINE> + How are you doing? + <BLANKLINE> + + +Anonymous lists +--------------- + +Anonymous mailing lists also try to cleanse certain identifying headers from +the original posting, so that it is at least a bit more difficult to determine +who sent the message. This isn't perfect though, for example, the body of the +messages are never scrubbed (though that might not be a bad idea). The From +and Reply-To headers in the posted message are taken from list attributes. + +Hotmail apparently sets X-Originating-Email. + + >>> mlist.anonymous_list = True + >>> mlist.description = u'A Test Mailing List' + >>> mlist.preferred_language = u'en' + >>> flush() + >>> msg = message_from_string("""\ + ... From: bperson@example.com + ... Reply-To: bperson@example.org + ... Sender: asystem@example.net + ... X-Originating-Email: cperson@example.com + ... Subject: a message to you + ... + ... How are you doing? + ... """, Message) + >>> process(mlist, msg, {}) + >>> print msg.as_string() + Subject: a message to you + From: A Test Mailing List <_xtest@example.com> + Reply-To: _xtest@example.com + <BLANKLINE> + How are you doing? + <BLANKLINE> + + +Clean up +-------- + + >>> for mlist in config.list_manager.mailing_lists: + ... config.list_manager.delete(mlist) + >>> flush() + >>> list(config.list_manager.mailing_lists) + [] diff --git a/Mailman/testing/test_cleanse.py b/Mailman/testing/test_cleanse.py new file mode 100644 index 000000000..97ad9c46c --- /dev/null +++ b/Mailman/testing/test_cleanse.py @@ -0,0 +1,32 @@ +# Copyright (C) 2007 by the Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. + +"""Doctest harness for the Cleanse handler.""" + +import doctest +import unittest + +options = (doctest.ELLIPSIS + | doctest.NORMALIZE_WHITESPACE + | doctest.REPORT_NDIFF) + + +def test_suite(): + suite = unittest.TestSuite() + suite.addTest(doctest.DocFileSuite('../docs/cleanse.txt', + optionflags=options)) + return suite diff --git a/Mailman/testing/test_handlers.py b/Mailman/testing/test_handlers.py index bbc7f5ba8..e6a846412 100644 --- a/Mailman/testing/test_handlers.py +++ b/Mailman/testing/test_handlers.py @@ -39,7 +39,6 @@ from Mailman.testing.base import TestBase from Mailman.Handlers import Acknowledge from Mailman.Handlers import AfterDelivery from Mailman.Handlers import Approve -from Mailman.Handlers import Cleanse from Mailman.Handlers import CookHeaders from Mailman.Handlers import FileRecips from Mailman.Handlers import Hold @@ -137,69 +136,6 @@ X-BeenThere: %s -class TestCleanse(TestBase): - def setUp(self): - TestBase.setUp(self) - - def test_simple_cleanse(self): - eq = self.assertEqual - msg = email.message_from_string("""\ -From: aperson@example.org -Approved: yes -Urgent: indeed -Reply-To: bperson@example.com -Sender: asystem@example.com -Return-Receipt-To: another@example.com -Disposition-Notification-To: athird@example.com -X-Confirm-Reading-To: afourth@example.com -X-PMRQC: afifth@example.com -Subject: a message to you - -""", Message.Message) - Cleanse.process(self._mlist, msg, {}) - eq(msg['approved'], None) - eq(msg['urgent'], None) - eq(msg['return-receipt-to'], None) - eq(msg['disposition-notification-to'], None) - eq(msg['x-confirm-reading-to'], None) - eq(msg['x-pmrqc'], None) - eq(msg['from'], 'aperson@example.org') - eq(msg['reply-to'], 'bperson@example.com') - eq(msg['sender'], 'asystem@example.com') - eq(msg['subject'], 'a message to you') - - def test_anon_cleanse(self): - eq = self.assertEqual - msg = email.message_from_string("""\ -From: aperson@example.org -Approved: yes -Urgent: indeed -Reply-To: bperson@example.com -Sender: asystem@example.com -Return-Receipt-To: another@example.com -Disposition-Notification-To: athird@example.com -X-Confirm-Reading-To: afourth@example.com -X-PMRQC: afifth@example.com -Subject: a message to you - -""", Message.Message) - self._mlist.anonymous_list = 1 - Cleanse.process(self._mlist, msg, {}) - eq(msg['approved'], None) - eq(msg['urgent'], None) - eq(msg['return-receipt-to'], None) - eq(msg['disposition-notification-to'], None) - eq(msg['x-confirm-reading-to'], None) - eq(msg['x-pmrqc'], None) - eq(len(msg.get_all('from')), 1) - eq(len(msg.get_all('reply-to')), 1) - eq(msg['from'], '_xtest@example.com') - eq(msg['reply-to'], '_xtest@example.com') - eq(msg['sender'], None) - eq(msg['subject'], 'a message to you') - - - class TestCookHeaders(TestBase): def test_transform_noack_to_xack(self): eq = self.assertEqual @@ -1463,7 +1399,6 @@ Mailman rocks! def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestApprove)) - suite.addTest(unittest.makeSuite(TestCleanse)) suite.addTest(unittest.makeSuite(TestCookHeaders)) suite.addTest(unittest.makeSuite(TestFileRecips)) suite.addTest(unittest.makeSuite(TestHold)) |
