[Twisted-Python] How to use defer.fail better...

Jan Bakuwel jan.bakuwel at omiha.com
Mon Mar 30 05:42:01 EDT 2009

Hoi all,

I'm writing a twisted/python SMTP server that accepts emails from a MTA
using twisted. All works well, except that when I return a
defer.fail(None) from processEmail to messageHandler.eomReceived (see
below), twisted dumps the trace back of the last exception on stdout. Is
there a way to avoid this? I would like to handle the exception
gracefully (with an exception handler) and would not like to see any
trace back from it in my logs. I've read that using None as the
parameter to defer.fail does exactly that... what should I use instead?

The other thing I would like to do better is to have a way to return
smtp code 421 (service temporarily unavailable) rather than 550 (fatal)
in those cases where I would like to indicate a (temporary) failure to
receive the email. I've patched smtp.py (replace 550 -> 421) for this
but would gladly hear about a way to do this without patching a standard
component on my system.


class messageHandler(object):
    def __init__(self, addressee):
        self.lines = []
        self.noisy = False
        self.emailMessage = None
        self.emailAddress = str(addressee)
    def lineReceived(self, line):

    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 processEmail(self.emailAddress, emailMessage)

    def connectionLost(self):
        log(1, 'Connection lost unexpectedly!')
        # unexpected loss of connection; don't save

class localDelivery(object):
    def __init__(self):
    #end __init__
    def validateFrom(self, helo, originAddress):
        log (1, 'Incoming email from %s', str(originAddress))
        # accept mail from anywhere. To reject an address, raise
        # smtp.SMTPBadSender here.
        return originAddress
    #end validateFrom
    def receivedHeader(self, helo, origin, recipients):
        myHostname, clientIP = helo
        headerValue = "by %s from %s with ESMTP ; %s" % (myHostname,
clientIP, smtp.rfc822date())
        log(1, '...received: %s', headerValue)
        # email.Header.Header used for automatic wrapping of long lines
        return "Received: %s" % Header(headerValue)
    #end receivedHeader

    def validateTo(self, user):
        #if not user.dest.domain in valid_domains:
        #       print "Not accepting mail for %s" % user.dest
        #       raise smtp.SMTPBadRcpt(user)
        log(1, 'Accepting email for %s', user.dest)
        return lambda: messageHandler(user.dest)
    #end validateTo


class SMTPFactory(protocol.ServerFactory):
    def __init__(self):
    #end __init__
    def buildProtocol(self, addr):
        delivery = localDelivery()
        smtpProtocol = smtp.SMTP(delivery)
        smtpProtocol.factory = self
        return smtpProtocol

More information about the Twisted-Python mailing list