Документация Python неофициальный перевод
Содержание страницы

21.18. smtpd – SMTP-серверsmtpd – SMTP Server

Исходный код: Lib/smtpd.py


Этот модуль предоставляет несколько классов для реализации SMTP-серверов (электронной почты).

См. также

Пакет aiosmtpd является рекомендуемой заменой этого модуля. Он основан на asyncio и предоставляет более простой API. smtpd следует считать устаревшим.

Предусмотрено несколько реализаций сервера; одна из них – универсальная реализация, которая ничего не делает и может быть переопределена, в то время как две другие предлагают конкретные стратегии отправки почты.

Кроме того, SMTPChannel может быть расширен для реализации очень специфического поведения взаимодействия с SMTP-клиентами.

Код поддерживает RFC 5321, а также расширения RFC 1870 SIZE и RFC 6531 SMTPUTF8.

21.18.1. Объекты SMTPServerSMTPServer Objects

class smtpd.SMTPServer(localaddr, remoteaddr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=True)

Создаёт новый объект SMTPServer, который привязывается к локальному адресу localaddr. Он будет рассматривать remoteaddr как вышестоящий SMTP-ретранслятор. Оба localaddr и remoteaddr должны быть кортежем (host, port) . Объект наследуется от asyncore.dispatcher и поэтому встраивается в цикл событий asyncore при создании.

data_size_limit задаёт максимальное количество байт, которое будет принято в команде DATA. Значение None или 0 означает отсутствие ограничения.

map – это карта сокетов для использования соединениями (в качестве подходящего значения можно использовать изначально пустой словарь). Если не указано, используется глобальная карта сокетов asyncore.

enable_SMTPUTF8 определяет, следует ли включить расширение SMTPUTF8 (как определено в RFC 6531). По умолчанию False. Если установлено True, decode_data должно быть False (иначе возникает ошибка). Если True, SMTPUTF8 принимается как параметр команды MAIL и, если присутствует, передаётся process_message() в списке kwargs['mail_options'].

decode_data определяет, должна ли часть данных SMTP-транзакции декодироваться с помощью UTF-8. По умолчанию True по причинам обратной совместимости, но в Python 3.6 изменится на False; укажите значение ключевого слова явно, чтобы избежать DeprecationWarning. Когда decode_data установлено в False, сервер объявляет расширение 8BITMIME (RFC 6152), принимает параметр BODY=8BITMIME команды MAIL и, если он присутствует, передаёт его process_message() в списке kwargs['mail_options'].

process_message(peer, mailfrom, rcpttos, data, **kwargs)

Вызывает исключение NotImplementedError. Переопределите этот метод в подклассах, чтобы сделать что-то полезное с этим сообщением. То, что было передано в конструктор как remoteaddr, будет доступно как атрибут _remoteaddr. peer – адрес удалённого хоста, mailfrom – отправитель конверта, rcpttos – получатели конверта, а data – строка, содержащая содержимое электронного письма (которое должно быть в формате RFC 5321 ).

Если ключевое слово конструктора decode_data установлено в True, аргумент data будет строкой Unicode. Если установлено в False, он будет объектом bytes.

kwargs – это словарь, содержащий дополнительную информацию. Он пуст, если в качестве параметра инициализации не было указано decode_data=False или enable_SMTPUTF8=True; в противном случае он содержит следующие ключи:

mail_options:
список всех полученных параметров команды MAIL (элементы – строки в верхнем регистре; пример: ['BODY=8BITMIME', 'SMTPUTF8']).
rcpt_options:
то же, что и mail_options, но для команды RCPT. В настоящее время не поддерживается ни один RCPT TO параметр, поэтому пока это всегда будет пустой список.

Реализации process_message должны использовать сигнатуру **kwargs для принятия произвольных именованных аргументов, поскольку будущие улучшения могут добавлять ключи в словарь kwargs.

Верните None для запроса обычного ответа 250 Ok; в противном случае верните нужную строку ответа в формате RFC 5321.

channel_class

Переопределите это в подклассах, чтобы использовать собственный SMTPChannel для управления SMTP-клиентами.

Новое в версии 3.4: Аргумент конструктора map.

Изменено в версии 3.5: localaddr и remoteaddr теперь могут содержать IPv6-адреса.

Новое в версии 3.5: аргументы конструктора decode_data и enable_SMTPUTF8, и аргумент kwargs для process_message(), когда указан хотя бы один из них.

21.18.2. Объекты DebuggingServerDebuggingServer Objects

class smtpd.DebuggingServer(localaddr, remoteaddr)

Создаёт новый отладочный сервер. Аргументы – как в SMTPServer. Сообщения будут отбрасываться и выводиться на stdout.

21.18.3. Объекты PureProxyPureProxy Objects

class smtpd.PureProxy(localaddr, remoteaddr)

Создаёт новый сервер-чистый прокси. Аргументы – как в SMTPServer. Всё будет пересылаться на remoteaddr. Имейте в виду, что его запуск с большой вероятностью сделает вас открытым ретранслятором, поэтому будьте осторожны.

21.18.4. Объекты MailmanProxyMailmanProxy Objects

class smtpd.MailmanProxy(localaddr, remoteaddr)

Создаёт новый чистый прокси-сервер. Аргументы те же, что и в SMTPServer. Всё будет перенаправляться на remoteaddr, если только локальные настройки mailman не знают об адресе – в этом случае обработка пойдёт через mailman. Учтите, что запуск этого сервера с большой вероятностью превратит вас в открытый релей, так что будьте осторожны.

21.18.5. Объекты SMTPChannelSMTPChannel Objects

class smtpd.SMTPChannel(server, conn, addr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=True)

Создаёт новый объект SMTPChannel, управляющий взаимодействием между сервером и одним SMTP-клиентом.

conn и addr описаны ниже в переменных экземпляра.

data_size_limit задаёт максимальное количество байт, которое будет принято в команде DATA. Значение None или 0 означает отсутствие ограничения.

enable_SMTPUTF8 определяет, следует ли включить расширение SMTPUTF8 (как определено в RFC 6531). По умолчанию False. Исключение ValueError возникает, если enable_SMTPUTF8 и decode_data одновременно установлены в True.

Словарь можно указать в map, чтобы избежать использования глобальной карты сокетов.

decode_data определяет, должна ли часть данных SMTP-транзакции декодироваться с помощью UTF-8. По умолчанию True по причинам обратной совместимости, но в Python 3.6 изменится на False. Укажите значение ключевого слова явно, чтобы избежать DeprecationWarning.

Чтобы использовать собственную реализацию SMTPChannel, нужно переопределить SMTPServer.channel_class вашего SMTPServer.

Изменено в версии 3.5: добавлены аргументы decode_data и enable_SMTPUTF8.

SMTPChannel имеет следующие переменные экземпляра:

smtp_server

Содержит объект SMTPServer, создавший этот канал.

conn

Содержит объект сокета, подключённого к клиенту.

addr

Содержит адрес клиента – второе значение, возвращаемое socket.accept

received_lines

Содержит список строк (декодированных в UTF-8), полученных от клиента. Строки имеют окончание "\r\n", преобразованное в "\n".

smtp_state

Содержит текущее состояние канала. Изначально это COMMAND, а затем DATA после того, как клиент отправит строку «DATA».

seen_greeting

Содержит строку с приветствием, отправленным клиентом в его «HELO».

mailfrom

Содержит строку с адресом, указанным в строке «MAIL FROM:» от клиента.

rcpttos

Содержит список строк с адресами, указанными в строках «RCPT TO:» от клиента.

received_data

Содержит строку со всеми данными, отправленными клиентом в состоянии DATA, включая всё до завершающего "\r\n.\r\n", но не включая его.

fqdn

Содержит полное доменное имя сервера, возвращаемое socket.getfqdn().

peer

Содержит имя клиента, возвращаемое conn.getpeername(), где conn – это conn.

SMTPChannel работает, вызывая методы с именем smtp_<command> при получении командной строки от клиента. В базовый класс SMTPChannel встроены методы для обработки следующих команд (и соответствующих ответов на них):

Команда Выполняемое действие
HELO Принимает приветствие от клиента и сохраняет его в seen_greeting. Переводит сервер в режим базовых команд.
EHLO Принимает приветствие от клиента и сохраняет его в seen_greeting. Переводит сервер в расширенный режим команд.
NOOP Не выполняет никаких действий.
QUIT Корректно закрывает соединение.
MAIL Принимает синтаксис «MAIL FROM:» и сохраняет указанный адрес как mailfrom. В расширенном режиме команд принимает атрибут SIZE RFC 1870 и отвечает соответствующим образом в зависимости от значения data_size_limit.
RCPT Принимает синтаксис «RCPT TO:» и сохраняет указанные адреса в списке rcpttos.
RSET Сбрасывает mailfrom, rcpttos и received_data, но не приветствие.
DATA Устанавливает внутреннее состояние в DATA и сохраняет остальные строки от клиента в received_data до получения терминатора "\r\n.\r\n".
HELP Возвращает минимальную информацию о синтаксисе команд
VRFY Возвращает код 252 (сервер не знает, действителен ли адрес)
EXPN Сообщает, что команда не реализована.