Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top