[Twisted-Python] SMTP Client Prototype

Moshe Zadka moshez at zadka.site.co.il
Thu May 3 01:53:00 MDT 2001


Hi!
Most of you already know how obsessed I am with e-mail...
Here is the latest thing -- a prototype for an SMTP client.
Later I just want to have an OutgoingQueue domain which can
be used to relay mail. The first stage, which I think is doable
by 0.9, is to have so-called smart host capability -- this would
save us the trouble of going after MX records ourselves, and 
still leave us with something very functional. 

SMTP_CODE = re.compile('(?P<code>\d\d\d)(?P<continuation>[- ])')

DO_HELO, DO_FROM, DO_TO, DO_DATA = range(3) 

class SMTPClientHandler(basic.LineReceiver):

    mode = DO_HELO
    hostname = 'localhost'
    lastCommand = None


    def handleLine(self, line):
        m = SMTP_CODE.match(line)
        if not m:
            raise SMTPError
        if m.groupdict()['continuation'] == ' ':
           self.handleCode(int(m.groupdict()['code']))


    def handleResponse(self, code):
        if self.lastCommand is None:
            if code != 250:
                self.loseConnection()
                return 0
        elif self.lastCommand == 'TO'
            if (code/100) == 2:
                self.successfulTo.append(self.lastTo)
            self.lastTo = None
        elif self.lastCommand == 'DATA':
            if code != 354:
                self.failMessage()
                self.mode = DO_FROM
        elif self.lastCommand == 'DID_DATA':
            if (code/100) == 2:
                self.doneMessage(self.successfulTo)
            else:
                self.failMessage()
            del self.successfulTo
        elif self.lastCommand == 'FROM':
            if (code/100) != 2:
                self.failMessage()
                self.mode = DO_FROM
        elif self.lastCommand == 'HELO':
            self.loseConnection()
            return 0
        return 1


    def handleCode(self, code):
        if not self.handleResponse(code):
            return
        if self.mode is DO_HELO:
            self.handler.write('HELO %s\r\n' % self.hostname)
            self.lastCommand = 'HELO'
        elif self.mode is DO_FROM:
            message = self.getActiveMessage()
            if message is None:
                return self.loseConnection()
            from_ = message.getFrom()
            self.mode = DO_TO
            self.recipients = message.getRecipients()
            self.sucessfulTo = []
            self.handler.write('MAIL FROM:<%s>\r\n' % from_)
            self.lastCommand = 'FROM'
        elif self.mode is DO_TO:
            if not self.recipients:
                self.lastCommand = 'DATA'
                self.handler.write('DATA\r\n')
            else:
                recipient = self.recipients.pop()
                self.lastCommand = 'TO'
                self.lastTo = recipient
                self.handler.write('RCPT TO:<%s>' % recipient)
        elif self.mode is DO_DATA:
             self.lastCommand = 'DID_DATA'
             self.sendMessage()





More information about the Twisted-Python mailing list