3 # Copyright (c) Twisted Matrix Laboratories.
4 # See LICENSE for details.
7 Example of a interfacing to Courier's mail filter interface.
10 LOGFILE = '/tmp/filter.log'
13 from twisted.python import log
14 log.startLogging(open(LOGFILE, 'a'))
16 sys.stderr = log.logfile
19 from twisted.internet import reactor, stdio
20 from twisted.internet.protocol import Protocol, Factory
21 from twisted.protocols import basic
23 FILTERS='/var/lib/courier/filters'
24 ALLFILTERS='/var/lib/courier/allfilters'
25 FILTERNAME='twistedfilter'
28 from syslog import syslog, openlog, LOG_MAIL
29 from rfc822 import Message
32 t,v,tb = sys.exc_info()
33 openlog(FILTERNAME, 0, LOG_MAIL)
34 syslog('Unhandled exception: %s - %s' % (v, t))
36 syslog('Trace: %s:%s %s' % (tb.tb_frame.f_code.co_filename,tb.tb_frame.f_code.co_name,tb.tb_lineno))
43 if os.path.isdir(file):
51 class DieWhenLost(Protocol):
52 def connectionLost(self, reason=None):
56 class MailProcessor(basic.LineReceiver):
57 """I process a mail message.
59 Override filterMessage to do any filtering you want."""
60 messageFilename = None
63 def connectionMade(self):
64 log.msg('Connection from %r' % self.transport)
65 self.state = 'connected'
68 def lineReceived(self, line):
69 if self.state == 'connected':
70 self.messageFilename = line
71 self.state = 'gotMessageFilename'
72 if self.state == 'gotMessageFilename':
74 self.metaInfo.append(line)
77 self.transport.loseConnection()
81 def filterMessage(self):
84 A trivial example is included.
87 m = Message(open(self.messageFilename))
88 self.sendLine('200 Ok')
91 self.sendLine('435 %s processing error' % FILTERNAME)
95 # Listen on the UNIX socket
97 f.protocol = MailProcessor
98 safe_del('%s/%s' % (ALLFILTERS, FILTERNAME))
99 reactor.listenUNIX('%s/%s' % (ALLFILTERS, FILTERNAME), f, 10)
101 # Once started, close fd 3 to let Courier know we're ready
102 reactor.callLater(0, os.close, 3)
104 # When stdin is closed, it's time to exit.
105 s = stdio.StandardIO(DieWhenLost())
110 if __name__ == '__main__':