This is the very basic code that I am using to create an SMTP server using twisted:
from email.Header import Header
from twisted.internet import protocol, defer, reactor
from twisted.mail import smtp
from zope.interface import implements
class ConsoleMessageDelivery(object):
implements(smtp.IMessageDelivery)
def receivedHeader(self, helo, origin, recipients):
myHostname, clientIP = helo
headerValue = "by %s from %s with ESMTP ; %s" % (myHostname,
clientIP,
smtp.rfc822date())
return "Received: %s" % Header(headerValue)
def validateFrom(self, helo, origin):
# All addresses are accepted
return origin
def validateTo(self, user):
# Only messages directed to the "console@domain" user are accepted.
if user.dest.local == "console":
return lambda: ConsoleMessage()
raise smtp.SMTPBadRcpt(user)
class ConsoleMessage(object):
implements(smtp.IMessage)
def __init__(self):
self.lines = []
def lineReceived(self, line):
self.lines.append(line)
def eomReceived(self):
print "New message received:"
print "\n".join(self.lines)
self.lines = None
return defer.succeed(None)
def connectionLost(self):
# There was an error, throw away the stored lines
self.lines = None
class LocalSMTPFactory(smtp.SMTPFactory):
def buildProtocol(self, addr):
smtpProtocol = smtp.ESMTP()
smtpProtocol.delivery = ConsoleMessageDelivery()
return smtpProtocol
reactor.listenTCP(2025, LocalSMTPFactory())
reactor.run()
I can receive emails but if I would like to reject incoming message with size of 1MB or more, how could I do it?
Notice that ConsoleMessage.lineReceived
is called with each line of the message. Each line has a size (similar to its length, no doubt). You can tally the size of all the lines as they are received and take action based on the result.
Additionally, you could explore the SIZE
ESMTP extension which allows the server to declare the maximum message size which will be accepted. This does not replace checking in the code handling message lines since there's no guarantee a client will respect the declared maximum but in the case of a smart, cooperating client it will save some pointless data transfer.
SIZE
is a simple enough extension that you can probably add it to Twisted's ESMTP server by subclassing twisted.mail.smtp.ESMTP
and overriding the extensions
method to add it.