#!/usr/bin/python
"""Example of a interfacing to Courier's mail filter interface"""
LOGFILE = '/tmp/filter.log'
# Setup log file
from twisted.python import log
log.startLogging(open(LOGFILE, 'a'))
import sys
sys.stderr = log.logfile
# Twisted imports
from twisted.internet import reactor,stdio
from twisted.internet.protocol import Protocol,Factory
from twisted.protocols import basic
FILTERS='/var/lib/courier/filters'
ALLFILTERS='/var/lib/courier/allfilters'
FILTERNAME='twistedfilter'
import os, os.path
from syslog import syslog,openlog,LOG_MAIL
from rfc822 import Message
def trace_dump():
t,v,tb = sys.exc_info()
openlog(FILTERNAME, 0, LOG_MAIL)
syslog('Unhandled exception: %s - %s' % (v, t))
while tb:
syslog('Trace: %s:%s %s' % (tb.tb_frame.f_code.co_filename,tb.tb_frame.f_code.co_name,tb.tb_lineno))
tb = tb.tb_next
# just to be safe
del tb
def safe_del(file):
try:
if os.path.isdir(file):
os.removedirs(file)
else:
os.remove(file)
except OSError:
pass
class DieWhenLost(Protocol):
def connectionLost(self, reason=None):
reactor.stop()
class MailProcessor(basic.LineReceiver):
"""I process a mail message.
Override filterMessage to do any filtering you want."""
messageFilename = None
delimiter = '\n'
def connectionMade(self):
log.msg('Connection from %r' % self.transport)
self.state = 'connected'
self.metaInfo = []
def lineReceived(self, line):
if self.state == 'connected':
self.messageFilename = line
self.state = 'gotMessageFilename'
if self.state == 'gotMessageFilename':
if line:
self.metaInfo.append(line)
else:
if not self.metaInfo:
self.transport.loseConnection()
return
self.filterMessage()
def filterMessage(self):
"""Override this.
A trivial example is included.
"""
try:
m = Message(open(self.messageFilename))
self.sendLine('200 Ok')
except:
trace_dump()
self.sendLine('435 %s processing error' % FILTERNAME)
def main():
# Listen on the UNIX socket
f = Factory()
f.protocol = MailProcessor
safe_del('%s/%s' % (ALLFILTERS, FILTERNAME))
reactor.listenUNIX('%s/%s' % (ALLFILTERS, FILTERNAME), f, 10)
# Once started, close fd 3 to let Courier know we're ready
reactor.callLater(0, os.close, 3)
# When stdin is closed, it's time to exit.
reactor.addReader(stdio.StandardIO(DieWhenLost()))
# Go!
reactor.run()
if __name__ == '__main__':
main()
|