Добавить поддержку SMTP AUTH в библиотеку Python smtpd ... не можете переопределить метод? - PullRequest
2 голосов
/ 16 июля 2009

Итак, я хотел расширить класс SMTPServer Python smtpd, чтобы он мог обрабатывать подключения SMTP AUTH. Казалось, достаточно просто ...

Итак, выглядело так, как будто я мог начать вот так:

def smtp_EHLO(self, arg):
    print 'got in arg: ', arg
    # do stuff here...

Но по какой-то причине это никогда не вызывается. Библиотека Python smtpd вызывает другие подобные методы:

        method = None
        i = line.find(' ')
        if i < 0:
            command = line.upper()
            arg = None
        else:
            command = line[:i].upper()
            arg = line[i+1:].strip()
        method = getattr(self, 'smtp_' + command, None)

Почему он не вызывает мой метод?

После этого я подумал, что мог бы просто переопределить весь метод found_terminator (self):, но, похоже, это тоже не сработало.

 def found_terminator(self):
     # I add this to my child class and it never gets called... 

Я что-то делаю глупо или ...? Может быть, я еще не совсем проснулся сегодня ...

import smtpd
import asyncore

class CustomSMTPServer(smtpd.SMTPServer):

    def smtp_EHLO(self, arg):

        print 'got in arg: ', arg

    def process_message(self, peer, mailfrom, rcpttos, data):
        print 'Receiving message from:', peer
        print 'Message addressed from:', mailfrom
        print 'Message addressed to  :', rcpttos
        print 'Message length        :', len(data)
        print 'HERE WE ARE MAN!'
        return

    # Implementation of base class abstract method
    def found_terminator(self):
        print 'THIS GOT CALLED RIGHT HERE!'

        line = EMPTYSTRING.join(self.__line)
        print >> DEBUGSTREAM, 'Data:', repr(line)
        self.__line = []
        if self.__state == self.COMMAND:
            if not line:
                self.push('500 Error: bad syntax')
                return
            method = None
            i = line.find(' ')
            if i < 0:
                command = line.upper()
                arg = None
            else:
                command = line[:i].upper()
                arg = line[i+1:].strip()
            method = getattr(self, 'smtp_' + command, None)

            print 'looking for: ', command
            print 'method is: ', method

            if not method:
                self.push('502 Error: command "%s" not implemented' % command)
                return
            method(arg)
            return
        else:
            if self.__state != self.DATA:
                self.push('451 Internal confusion')
                return
            # Remove extraneous carriage returns and de-transparency according
            # to RFC 821, Section 4.5.2.
            data = []
            for text in line.split('\r\n'):
                if text and text[0] == '.':
                    data.append(text[1:])
                else:
                    data.append(text)
            self.__data = NEWLINE.join(data)
            status = self.__server.process_message(self.__peer,
                                                   self.__mailfrom,
                                                   self.__rcpttos,
                                                   self.__data)
            self.__rcpttos = []
            self.__mailfrom = None
            self.__state = self.COMMAND
            self.set_terminator('\r\n')
            if not status:
                self.push('250 Ok')
            else:
                self.push(status)

server = CustomSMTPServer(('127.0.0.1', 1025), None)

asyncore.loop()

Ответы [ 2 ]

3 голосов
/ 16 июля 2009

Вам нужно расширить SMTPChannel - вот где реализованы методы глагола smtp_; ваше расширение SMTPServer просто должно вернуть ваш собственный подкласс канала.

0 голосов
/ 17 марта 2019

TL & DR: Чтобы добавить дополнительные функции в SMTPChannel, вам просто нужно объявить функцию, а затем добавить ее непосредственно в smtpd.SMTPChannel

Объяснение:

Класс SMTPChannel предназначен для ответа на команды, которые вводит пользователь на открытом порту (обычно это порт 25). То, как он ищет команды, на которые он может ответить, основано на «Самоанализе», где он проверяет все доступные атрибуты функции.

Обратите внимание, что функциям в SMTPChannel необходимо , чтобы начать с "smtp_". Например, если вы хотите ответить на HELP, вы должны создать smtpd.SMTPChannel.smtp_HELP.

Функция ниже взята из исходного кода, который детализирует самоанализ

class SMTPChannel(asynchat.async_chat):
  method = getattr(self, 'smtp_' + command, None)

CodeThatWorks

Шаг 1: Объявите ФУНКЦИЮ, которая будет называться

def smtp_HELP(self,arg):
  self.push("[8675309] GPT Answers to HELP")

Шаг 2. Добавьте следующую функцию в smtpd.SMTPChannel

class FakeSMTPServer(smtpd.SMTPServer):

"""A Fake smtp server"""
        smtpd.SMTPChannel.smtp_HELP = smtp_HELP

Шаг 3: Telnet к localhost 25 и тестирование

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 vics-imac.fios-router.home ESMTP Sendmail 6.7.4 Sunday 17 March 2019
HELP
[8675309] GPT Answers to HELP
...