Newbie: trying to twist my head around twisted (and python)

Jan Bakuwel jan.bakuwel at int.greenpeace.org
Wed Oct 11 17:15:09 CEST 2006


Hoi all,

Please see below a small piece of python code that resembles a
smtpserver using the twisted framework. The code is based on the example
smtp server discussed in Twisted Network Programming Essentials.
The unmodified example code can be found on the O'Reilly website:
(http://examples.oreilly.com/twistedadn/, in ch08 subdir).

I've removed all the code I don't (the original example write an email
received with SMTP to a Maildir; I'll do something else with it). For
the sake of the example, the only thing I'll do in eomReceived is print
whether the message had any attachments or not, then return a "failed"
if a message had any attachments and a "success" if not.

According to the book, I need to return a "Deferred result" from the
function eomReceived (see ???????? below).

In eomReceived, I intend to process the email then either return success
 or failure. I've been looking at the twisted way of using twisted :-).
According to the book "its a little confusing for a start" and I have to
agree :-)

Does anyone know how I need to complete the code below so it returns
this mysterious "Deferred result" and runs?

Many thanks in advance,
Jan


#!/usr/bin/python

from twisted.mail import smtp, maildir
from zope.interface import implements
from twisted.internet import protocol, reactor, defer
import os
from email.Header import Header
from email import message_from_string


class MessageHandler(object):
    implements(smtp.IMessage)

    def __init__(self, userDir):
        self.lines = []
    #end __init__

    def lineReceived(self, line):
        self.lines.append(line)
    #end lineReceived

    def eomReceived(self):
        # message is complete, store it
        self.lines.append('') # add a trailing newline
        messageData = '\n'.join(self.lines)
	emailMessage = message_from_string (messageData)

        # return a Deferred result so the client knows whether the
	# message has been successfully processed
	if emailMessage.is_multipart():
	    print "email has attachments"
            return ?????? failed ???????
        else:
            print "email has no attachments"
            return ?????? success ???????

    #end eomReceived

    def connectionLost(self):
        print "Connection lost unexpectedly!"
        # unexpected loss of connection; don't save
        del(self.lines)
        del(self.email)
    #end connectionLost

#end MessageHandler


class LocalDelivery(object):
    implements(smtp.IMessageDelivery)

    def __init__(self):
	pass
    #end __init__

    def receivedHeader(self, helo, origin, recipients):
        myHostname, clientIP = helo
        headerValue = "by %s from %s with ESMTP ; %s" % (myHostname,
clientIP, smtp.rfc822date())
        # email.Header.Header used for automatic wrapping of long lines
        return "Received: %s" % Header(headerValue)
    #end receivedHeader

    def validateFrom(self, helo, originAddress):
        # accept mail from anywhere. To reject an address, raise
        # smtp.SMTPBadSender here.
        return originAddress
    #end validateFrom

    def validateTo(self, user):
        print "Accepting mail for %s" % user.dest
        return lambda: MessageHandler()
    #end validateTo

#end LocalDelivery


class SMTPFactory(protocol.ServerFactory):
    def __init__(self):
        pass
    #end __init__

    def buildProtocol(self, addr):
        delivery = LocalDelivery()
        smtpProtocol = smtp.SMTP(delivery)
        smtpProtocol.factory = self
        return smtpProtocol
    #end buildProtocol

#end SMTPFactory


if __name__ == "__main__":
    import sys
    reactor.listenTCP(10025, SMTPFactory())
    from twisted.internet import ssl
    # SSL stuff here... and certificates...
    reactor.run()



More information about the Python-list mailing list