4
Mailman can do pattern based header matching during its normal rule
5
processing. There is a set of site-wide default header matchines specified in
6
the configuaration file under the HEADER_MATCHES variable.
8
>>> from Mailman.app.lifecycle import create_list
9
>>> mlist = create_list(u'_xtest@example.com')
11
Because the default HEADER_MATCHES variable is empty when the configuration
12
file is read, we'll just extend the current header matching chain with a
13
pattern that matches 4 or more stars, discarding the message if it hits.
15
>>> from Mailman.configuration import config
16
>>> chain = config.chains['header-match']
17
>>> chain.extend('x-spam-score', '[*]{4,}', 'discard')
19
First, if the message has no X-Spam-Score header, the message passes through
20
the chain untouched (i.e. no disposition).
22
>>> msg = message_from_string("""\
23
... From: aperson@example.com
24
... To: _xtest@example.com
28
... This is a message.
31
>>> from Mailman.app.chains import process
33
Pass through is seen as nothing being in the log file after processing.
35
# XXX This checks the vette log file because there is no other evidence
36
# that this chain has done anything.
38
>>> fp = open(os.path.join(config.LOG_DIR, 'vette'))
40
>>> file_pos = fp.tell()
41
>>> process(mlist, msg, {}, 'header-match')
43
>>> print 'LOG:', fp.read()
47
Now, if the header exists but does not match, then it also passes through
50
>>> msg['X-Spam-Score'] = '***'
51
>>> del msg['subject']
52
>>> msg['Subject'] = 'This is almost spam'
53
>>> del msg['message-id']
54
>>> msg['Message-ID'] = '<two>'
55
>>> file_pos = fp.tell()
56
>>> process(mlist, msg, {}, 'header-match')
58
>>> print 'LOG:', fp.read()
62
But now if the header matches, then the message gets discarded.
64
>>> del msg['x-spam-score']
65
>>> msg['X-Spam-Score'] = '****'
66
>>> del msg['subject']
67
>>> msg['Subject'] = 'This is spam, but barely'
68
>>> del msg['message-id']
69
>>> msg['Message-ID'] = '<three>'
70
>>> file_pos = fp.tell()
71
>>> process(mlist, msg, {}, 'header-match')
73
>>> print 'LOG:', fp.read()
74
LOG: ... DISCARD: <three>
77
For kicks, let's show a message that's really spammy.
79
>>> del msg['x-spam-score']
80
>>> msg['X-Spam-Score'] = '**********'
81
>>> del msg['subject']
82
>>> msg['Subject'] = 'This is really spammy'
83
>>> del msg['message-id']
84
>>> msg['Message-ID'] = '<four>'
85
>>> file_pos = fp.tell()
86
>>> process(mlist, msg, {}, 'header-match')
88
>>> print 'LOG:', fp.read()
89
LOG: ... DISCARD: <four>
92
Flush out the extended header matching rules.
97
List-specific header matching
98
-----------------------------
100
Each mailing list can also be configured with a set of header matching regular
101
expression rules. These are used to impose list-specific header filtering
102
with the same semantics as the global `HEADER_MATCHES` variable.
104
The list administrator wants to match not on four stars, but on three plus
105
signs, but only for the current mailing list.
107
>>> mlist.header_matches = [('x-spam-score', '[+]{3,}', 'discard')]
109
A message with a spam score of two pluses does not match.
111
>>> del msg['x-spam-score']
112
>>> msg['X-Spam-Score'] = '++'
113
>>> del msg['message-id']
114
>>> msg['Message-ID'] = '<five>'
115
>>> file_pos = fp.tell()
116
>>> process(mlist, msg, {}, 'header-match')
117
>>> fp.seek(file_pos)
118
>>> print 'LOG:', fp.read()
121
A message with a spam score of three pluses does match.
123
>>> del msg['x-spam-score']
124
>>> msg['X-Spam-Score'] = '+++'
125
>>> del msg['message-id']
126
>>> msg['Message-ID'] = '<six>'
127
>>> file_pos = fp.tell()
128
>>> process(mlist, msg, {}, 'header-match')
129
>>> fp.seek(file_pos)
130
>>> print 'LOG:', fp.read()
131
LOG: ... DISCARD: <six>
134
As does a message with a spam score of four pluses.
136
>>> del msg['x-spam-score']
137
>>> msg['X-Spam-Score'] = '+++'
138
>>> del msg['message-id']
139
>>> msg['Message-ID'] = '<seven>'
140
>>> file_pos = fp.tell()
141
>>> process(mlist, msg, {}, 'header-match')
142
>>> fp.seek(file_pos)
143
>>> print 'LOG:', fp.read()
144
LOG: ... DISCARD: <seven>