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

J

Jan Bakuwel

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()
 
B

Bjoern Schliessmann

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

Without having looked at your code at this late hour -- perhaps a
short explanation of what a Deferred is will help.

If a function wants to returns something that will not be available
at an instant (e.g. some data fetched over network) it doesn't
return the "wanted" value directly, but a Deferred instance (as an
abstract reference to this value)

The calling function may now, after getting this Deferred,
attach "Callbacks" and "Errbacks" to this Deferred. Callbacks and
Errbacks are just functions that are executed when the Deferred's
task is finished successfully or unsuccessfully (which will mostly
happen in the future). When the result the Deferred stands for is
available, some other function outside "fires" the Deferred so the
Callback or Errback is executed.

So the typical workflow is:

- Call a function and get a Deferred
- Attach Callbacks to the Deferred which will process the data the
Deferred stands for /when/ it's finally available
- Wait, and eventually in some part of the program the Deferred is
fired and your Callback gets executed.

Regards&HTH,


Björn
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top