[Twisted-Python] Help with SMTP Proxy
Eugene Coetzee
projects at reedflute.com
Sat Apr 23 01:46:11 MDT 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