[Twisted-Python] Help with SMTP Proxy
Jan Van Uytven
wyvern at crm3.com
Fri Apr 22 18:19:03 MDT 2005
Hi,
I'm a new user of Twisted, I came to it because I need to write an SMTP
proxy and want to use Python to do it. The proxy would copy the incoming
e-mail (including the envelope headers) and then forward it to Postfix.
Googling around I came across an example of an SMTP server (written by
the author of twisted.mail I think) and after playing around with it a
bit I can get it to receive and copy the e-mail, but I'm not quite sure
how to forward it on after that. Right now I have the proxy sitting on
port 2025 and the final smtp server on port 2030. Here's the code I have
so far:
import os, StringIO
from zope.interface import implements
from twisted.application import service
application = service.Application("Postfix SMTP Proxy for CopyUser")
from twisted.application import internet
from twisted.internet import protocol, defer
smtpServerFactory = protocol.ServerFactory()
from twisted.mail import smtp
class FileMessage(object):
implements(smtp.IMessage)
def __init__(self, fileObj):
self.fileObj = fileObj
self.msg = []
def lineReceived(self, line):
self.fileObj.write(line + '\n')
self.msg.append(line)
def eomReceived(self):
self.fileObj.close()
print "\n".join(self.msg)
return defer.succeed(None)
def connectionLost(self):
self.fileObj.close()
os.remove(self.fileObj.name)
class Delivery(object):
implements(smtp.IMessageDelivery)
counter = 0
def validateTo(self, user):
fileName = 'smtplog.' + str(self.counter)
self.counter += 1
return lambda: FileMessage(file(fileName, 'w'))
def validateFrom(self, helo, origin):
return origin
def receivedHeader(self, helo, origin, recipients):
recpts = []
for i in recipients:
recpts.append(str(i))
recptstr = "Recipients: " + ",".join(recpts)
origin = "Origin: " + str(origin)
return recptstr+"\r\n"+origin+"\r\n\r\n"
class ESMTPFactory(protocol.ServerFactory):
protocol = smtp.ESMTP
def buildProtocol(self, addr):
p = self.protocol()
p.delivery = Delivery()
p.factory = self
return p
class ForwardSMTPClient(smtp.ESMTPClient):
def getMailFrom(self):
return ["smtp_proxy at localhost"]
def getMailTo(self):
return "tester at localhost"
def getMailData(self):
data = """
Subject: Test!
Test!
"""
return StringIO.StringIO(data)
def sentMail(self, code, resp, numOk, addresses, log):
print 'Sent', numOk, 'messages'
class SMTPClientFactory(protocol.ClientFactory):
protocol = ForwardSMTPClient
def buildProtocol(self, addr):
return self.protocol(secret=None, identity='localhost')
smtpServerFactory = ESMTPFactory()
smtpClientFactory = SMTPClientFactory()
smtpServerService = internet.TCPServer(2025, smtpServerFactory)
smtpServerService.setServiceParent(application)
I've left out actually forwarding the message for now, I just want to
forward a test e-mail upon receipt of the message. The whole structure
of this program doesn't seem right to me. I thought initially of trying
something like adding this to the eomReceived method:
smtpForwardService = internet.TCPClient('localhost', 2030,
smtpClientFactory)
smtpForwardService.setServiceParent(application)
but it started an endless loop of sending the test e-mail. Most clients
use reactor.stop() to finish after processing, but I need the reactor to
keep on going.
Documentation on twisted.mail is almost non-existent. Is there a better
way of doing this?
Thanks,
Still Struggling
More information about the Twisted-Python
mailing list