Mercurial > hg > pyspamc
comparison spamc-milter.py @ 0:7f4443127958 default tip
Import
author | Daniele Nicolodi <daniele@grinta.net> |
---|---|
date | Wed, 02 Nov 2011 12:03:09 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7f4443127958 |
---|---|
1 # Simple milter deamon that handles email messages off to spamd for | |
2 # classification. Messages classified as spam are rejected. Other | |
3 # are augmented with Spamassassin additional headers. | |
4 | |
5 import email.parser | |
6 from cStringIO import StringIO | |
7 | |
8 import Milter as milter | |
9 import spamc | |
10 | |
11 | |
12 # headers to add to scanned messages | |
13 HEADERS = ('X-Spam-Checker-Version', 'X-Spam-Level', 'X-Spam-Status', ) | |
14 | |
15 | |
16 class Milter(milter.Base): | |
17 | |
18 def __init__(self): | |
19 # integer incremented with each call | |
20 self.id = milter.uniqueID() | |
21 self.fd = StringIO() | |
22 | |
23 @milter.noreply | |
24 def connect(self, hostname, family, hostaddr): | |
25 self.hostname = hostname | |
26 self.hostaddr = hostaddr | |
27 return milter.CONTINUE | |
28 | |
29 def hello(self, heloname): | |
30 self.helo = heloname | |
31 return milter.CONTINUE | |
32 | |
33 def envfrom(self, mailfrom, *str): | |
34 self.mailfrom = mailfrom | |
35 return milter.CONTINUE | |
36 | |
37 @milter.noreply | |
38 def envrcpt(self, recipient, *str): | |
39 self.recipient = recipient | |
40 return milter.CONTINUE | |
41 | |
42 @milter.noreply | |
43 def header(self, name, val): | |
44 # add header to buffer | |
45 self.fd.write('%s: %s\n' % (name, val)) | |
46 return milter.CONTINUE | |
47 | |
48 @milter.noreply | |
49 def eoh(self): | |
50 # terminate headers | |
51 self.fd.write('\n') | |
52 return milter.CONTINUE | |
53 | |
54 @milter.noreply | |
55 def body(self, chunk): | |
56 # add body to buffer | |
57 self.fd.write(chunk) | |
58 return milter.CONTINUE | |
59 | |
60 def eom(self): | |
61 # ask spamd about the received message | |
62 self.conn = spamc.Client('localhost') | |
63 resp = self.conn.request('HEADERS', self.fd.getvalue()) | |
64 # reject spam messages | |
65 if resp.result: | |
66 return milter.REJECT | |
67 # parse returned message headers | |
68 data = resp.read() | |
69 print data | |
70 headers = email.parser.Parser().parsestr(data) | |
71 # add headers | |
72 for name in HEADERS: | |
73 # transform multiple line headers to single line ones | |
74 value = ' '.join(headers.get(name, '').split()) | |
75 self.addheader(name, value) | |
76 # accept message | |
77 return milter.ACCEPT | |
78 | |
79 def close(self): | |
80 # clean up | |
81 self.fd.close() | |
82 self.conn.close() | |
83 return milter.CONTINUE | |
84 | |
85 def abort(self): | |
86 # client disconnected prematurely | |
87 return milter.CONTINUE | |
88 | |
89 | |
90 def main(): | |
91 socketname = "/var/spool/postfix/private/spamc" | |
92 timeout = 600 | |
93 | |
94 # register the milter factory | |
95 milter.factory = Milter | |
96 # ask milter features we use | |
97 milter.set_flags(milter.CHGHDRS + milter.ADDHDRS) | |
98 # run | |
99 milter.runmilter("spamc-milter", socketname, timeout) | |
100 | |
101 | |
102 if __name__ == "__main__": | |
103 main() |