[Twisted-Python] Help with SMTP Proxy

Eugene Coetzee projects at reedflute.com
Sat Apr 23 03:46:11 EDT 2005


Jan Van Uytven wrote:

> 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)
>
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 at reedflute.com
Project information -> projects at reedflute.com
Web                 -> www.reedflute.com
=============================================== 





More information about the Twisted-Python mailing list