Автор оригинала: Doug Hellmann.
Цель:
Включает классы для реализации SMTP-серверов.
Модуль smtpd
включает классы для создания серверов простого почтового транспортного протокола.
Базовый класс почтового сервера
Базовым классом для всех предоставленных примеров серверов является SMTPServer
. Он обрабатывает общение с клиентом, получение входящих данных и обеспечивает удобный
Аргументы конструктора – это локальный адрес для прослушивания подключений и удаленный адрес, по которому должны доставляться прокси-сообщения. Метод process_message ()
предоставляется как перехватчик, который должен быть переопределен производным классом. Он вызывается, когда сообщение полностью получено, и с учетом следующих аргументов:
равноправный
Адрес клиента, кортеж, содержащий IP-адрес и входящий порт.
mailfrom
Информация “от” из конверта сообщения, передаваемая сервер клиентом, когда сообщение доставлено. Это не обязательно соответствовать
Из
заголовок во всех случаях.
rcpttos
Список получателей из конверта сообщения. Опять же, это не всегда
К
заголовок, особенно если получатель слепая копировальная копия.
данные
Полное тело сообщения RFC 5322.
Реализация по умолчанию process_message ()
вызывает NotImplementedError
. В следующем примере определяется
smtpd_custom.py
import smtpd import asyncore class CustomSMTPServer(smtpd.SMTPServer): 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)) server CustomSMTPServer(('127.0.0.1', 1025), None) asyncore.loop()
SMTPServer
использует asyncore
, поэтому для запуска сервера вызовите asyncore.loop ()
.
Для демонстрации сервера нужен клиент. Один из примеров из раздела о smtplib можно адаптировать для создания клиента на
smtpd_senddata.py
import smtplib import email.utils from email.mime.text import MIMEText # Create the message msg MIMEText('This is the body of the message.') msg['To'] email.utils.formataddr(('Recipient', 'recipient@example.com')) msg['From'] email.utils.formataddr(('Author', 'author@example.com')) msg['Subject'] 'Simple test message' server smtplib.SMTP('127.0.0.1', 1025) server.set_debuglevel(True) # show communication with the server try: server.sendmail('author@example.com', ['recipient@example.com'], msg.as_string()) finally: server.quit()
Чтобы протестировать программы, запустите smtpd_custom.py
в одном терминале и smtpd_senddata.py
в другом.
$ python3 smtpd_custom.py Receiving message from: ('127.0.0.1', 58541) Message addressed from: author@example.com Message addressed to : ['recipient@example.com'] Message length : 229
Отладочные данные из smtpd_senddata.py
показывают всю связь с сервером.
$ python3 smtpd_senddata.py send: 'ehlo 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0. 0.0.0.0.0.0.ip6.arpa\r\n' reply: b'250-1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 .0.0.0.0.0.0.ip6.arpa\r\n' reply: b'250-SIZE 33554432\r\n' reply: b'250 HELP\r\n' reply: retcode (250); Msg: b'1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 .0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa\nSIZE 33554432\nHELP' send: 'mail FROM:reply: b'250 OK\r\n' reply: retcode (250); Msg: b'OK' send: 'rcpt TO: \r\n' reply: b'250 OK\r\n' reply: retcode (250); Msg: b'OK' send: 'data\r\n' reply: b'354 End data with . \r\n' reply: retcode (354); Msg: b'End data with . ' data: (354, b'End data with . ') send: b'Content-Type: text/plain;\r\nMIME-Ver sion: 1.0\r\nContent-Transfer-Encoding: 7bit\r\nTo: Recipient \r\nFrom: Author \r\nSu bject: Simple test message\r\n\r\nThis is the body of the messag e.\r\n.\r\n' reply: b'250 OK\r\n' reply: retcode (250); Msg: b'OK' data: (250, b'OK') send: 'quit\r\n' reply: b'221 Bye\r\n' reply: retcode (221); Msg: b'Bye'
Чтобы остановить сервер, нажмите Ctrl-C
.
Сервер отладки
В предыдущем примере показаны аргументы для process_message ()
, но smtpd
также включает сервер, специально разработанный для более полной отладки, который называется DebuggingServer
. Он выводит все входящее сообщение на консоль, а затем останавливает обработку (он не передает сообщение на настоящий почтовый сервер).
smtpd_debug.py
import smtpd import asyncore server smtpd.DebuggingServer(('127.0.0.1', 1025), None) asyncore.loop()
При использовании клиентской программы smtpd_senddata.py
из более ранней версии DebuggingServer
выводится следующим образом:
---------- MESSAGE FOLLOWS ---------- Content-Type: text/plain; MIME-Version: 1.0 Content-Transfer-Encoding: 7bit To: RecipientFrom: Author Subject: Simple test message X-Peer: 127.0.0.1 This is the body of the message. ------------ END MESSAGE ------------
Прокси сервер
Класс PureProxy
реализует простой прокси-сервер. Входящие сообщения пересылаются
Предупреждение
В стандартной библиотечной документации для smtpd
сказано: «Запуск этого может сделать вас открытым ретранслятором, поэтому будьте осторожны».
Шаги по настройке прокси-сервера аналогичны отладке.
smtpd_proxy.py
import smtpd import asyncore server smtpd.PureProxy(('127.0.0.1', 1025), ('mail', 25)) asyncore.loop()
Однако он не выводит никаких результатов, поэтому, чтобы убедиться, что он работает, посмотрите журналы почтового сервера.
Aug 20 19:16:34 homer sendmail[6785]: m9JNGXJb006785: fromauthor@example.com>, size248, class0, nrcpts1, msgid200810192316.m9JNGXJb006785@homer.example.com>, protoESMTP, daemonMTA, relay[192.168.1.17]
Смотрите также
- стандартная библиотечная документация для smtpd
- smtplib – предоставляет клиентский интерфейс.
электронная почта
– анализирует сообщения электронной почты.asyncore
– базовый модуль для написания асинхронных серверов.- RFC 2822 – Интернет