Добавить поддержку SMTP AUTH в библиотеку Python smtpd... не можете переопределить метод?
Итак, я хотел расширить класс 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()
1 ответ
Вы должны продлить SMTPChannel
- вот где smtp_
реализованы методы глагола; ваше расширение SMTPServer
просто нужно вернуть свой собственный подкласс канала.
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