
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. thanks, Jan class messageHandler(object): implements(smtp.IMessage) def __init__(self, addressee): self.lines = [] self.noisy = False self.emailMessage = None self.emailAddress = str(addressee) #__init__ def lineReceived(self, line): self.lines.append(line) #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 processEmail(self.emailAddress, emailMessage) #eomReceived def connectionLost(self): log(1, 'Connection lost unexpectedly!') # unexpected loss of connection; don't save del(self.lines) del(self.emailMessage) #connectionLost #messageHandler class localDelivery(object): implements(smtp.IMessageDelivery) def __init__(self): pass #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 #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 #buildProtocol #SMTPFactory