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 mailman.app.lifecycle import create_list
>>> mlist = create_list('_xtest@example.com')
Headers such as Approved
, Approve
, (as well as their X-
variants)
and Urgent
are used to grant special permissions 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.
>>> from mailman.testing.helpers import (specialized_message_from_string
... as message_from_string)
>>> msg = message_from_string("""\
... From: aperson@example.com
... Approved: foobar
... Approve: barfoo
... X-Approved: bazbar
... X-Approve: barbaz
... Urgent: notreally
... Subject: A message of great import
...
... Blah blah blah
... """)
>>> from mailman.config import config
>>> handler = config.handlers['cleanse']
>>> handler.process(mlist, msg, {})
>>> print(msg.as_string())
From: aperson@example.com
Subject: A message of great import
Blah blah blah
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?
... """)
>>> handler.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
How are you doing?
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. Message-ID
can reveal the poster’s domain, so it is replaced.
Hotmail apparently sets X-Originating-Email
.
>>> mlist.anonymous_list = True
>>> mlist.description = 'A Test Mailing List'
>>> mlist.preferred_language = 'en'
>>> msg = message_from_string("""\
... From: bperson@example.com
... Reply-To: bperson@example.org
... Sender: asystem@example.net
... X-Originating-Email: cperson@example.com
... Message-ID: <99999@example.com>
... Subject: a message to you
...
... How are you doing?
... """)
>>> handler.process(mlist, msg, {})
>>> print(msg.as_string())
Subject: a message to you
Message-ID: ...
From: A Test Mailing List <_xtest@example.com>
Reply-To: _xtest@example.com
How are you doing?
In addition to removing all the headers that we know might reveal the poster’s
address or domain, we also then remove any of the remaining headers whose names
don’t match a pattern in the anonymous_list_keep_headers setting
in the
[mailman]
section of mailman.cfg
. This is how that setting is
described:
# This is a space separated list of regexps which match headers to be kept
# in messages to anonymous lists. Many headers are removed from posts to
# anonymous lists before this is consulted, but of the remaining headers,
# any that don't match one of these patterns are also removed. The headers
# kept by default are non X- headers, those X- headers added by Mailman
# and any X-Spam- headers. The match is case-insensitive.
anonymous_list_keep_headers: ^(?!x-) ^x-mailman- ^x-content-filtered-by:
^x-topics: ^x-ack: ^x-beenthere: ^x-list-administrivia: ^x-spam-
So we see for a message with unknown X-
headers that those headers are
also removed, but the known X-Mailman-Version
header is not.
>>> mlist.anonymous_list = True
>>> mlist.description = 'A Test Mailing List'
>>> mlist.preferred_language = 'en'
>>> msg = message_from_string("""\
... From: bperson@example.com
... Reply-To: bperson@example.org
... Sender: asystem@example.net
... X-Originating-Email: cperson@example.com
... X-Maybe-From: bperson@example.com
... X-Some-Other-Unknown: What's this
... X-Mailman-Version: 3.3.4
... Message-ID: <99999@example.com>
... Subject: a message to you
...
... How are you doing?
... """)
>>> handler.process(mlist, msg, {})
>>> print(msg.as_string())
X-Mailman-Version: 3.3.4
Subject: a message to you
Message-ID: ...
From: A Test Mailing List <_xtest@example.com>
Reply-To: _xtest@example.com
How are you doing?