[Twisted-Python] Help with SMTP Proxy

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@localhost"] def getMailTo(self): return "tester@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

Jan Van Uytven wrote:
This is how I'm doing it. http://twistedmatrix.com/pipermail/twisted-python/2005-March/009888.html Conductor instance registers a reference to both smtpServerService instance and smtpForwardService instance. I would call something like conductor.write(destination) from within the smtpServerService instance which would in turn call a method on the reference to smtpForwardService from within conductor. regards, Eugene Coetzee -- -- =============================================== Reedflute Software Solutions Telephone -> +27 18 293 3236 General information -> info@reedflute.com Project information -> projects@reedflute.com Web -> www.reedflute.com ===============================================

Eugene Coetzee wrote:
<snip> Conductor instance registers a reference to both smtpServerService instance and smtpForwardService instance. I would call something like conductor.write(destination) from within the smtpServerService instance which would in turn call a method on the reference to smtpForwardService from within conductor. </snip> should in fact read ... Conductor instance registers a reference to both smtpServerFactory instance and smtpClientFactory instance. I would call something like conductor.write(destination) from within the smtpServer instance which would in turn call a method on the reference to smtpClientFactory from within conductor. Sorry about that. -- -- =============================================== Reedflute Software Solutions Telephone -> +27 18 293 3236 General information -> info@reedflute.com Project information -> projects@reedflute.com Web -> www.reedflute.com ===============================================

Jan Van Uytven wrote:
This is how I'm doing it. http://twistedmatrix.com/pipermail/twisted-python/2005-March/009888.html Conductor instance registers a reference to both smtpServerService instance and smtpForwardService instance. I would call something like conductor.write(destination) from within the smtpServerService instance which would in turn call a method on the reference to smtpForwardService from within conductor. regards, Eugene Coetzee -- -- =============================================== Reedflute Software Solutions Telephone -> +27 18 293 3236 General information -> info@reedflute.com Project information -> projects@reedflute.com Web -> www.reedflute.com ===============================================

Eugene Coetzee wrote:
<snip> Conductor instance registers a reference to both smtpServerService instance and smtpForwardService instance. I would call something like conductor.write(destination) from within the smtpServerService instance which would in turn call a method on the reference to smtpForwardService from within conductor. </snip> should in fact read ... Conductor instance registers a reference to both smtpServerFactory instance and smtpClientFactory instance. I would call something like conductor.write(destination) from within the smtpServer instance which would in turn call a method on the reference to smtpClientFactory from within conductor. Sorry about that. -- -- =============================================== Reedflute Software Solutions Telephone -> +27 18 293 3236 General information -> info@reedflute.com Project information -> projects@reedflute.com Web -> www.reedflute.com ===============================================
participants (2)
-
Eugene Coetzee
-
Jan Van Uytven