1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
.. _migrating:
==================================
Migrating from smtpd to aiosmtpd
==================================
aiosmtpd is designed to make it easy to migrate an existing application based
on `smtpd <https://docs.python.org/3/library/smtpd.html>`__ to aiosmtpd.
Consider the following subclass of ``smtpd.SMTPServer``::
import smtpd
import asyncore
class CustomSMTPServer(smtpd.SMTPServer):
def process_message(self, peer, mail_from, rcpt_tos, data):
# Process message data...
if error_occurred:
return '500 Could not process your message'
if __name__ == '__main__':
server = CustomSMTPServer(('127.0.0.1', 10025), None)
# Run the event loop in the current thread.
asyncore.loop()
To switch this application to using ``aiosmtpd``, implement a handler with
the ``handle_DATA()`` method::
import asyncio
from aiosmtpd.controller import Controller
class CustomHandler:
async def handle_DATA(self, server, session, envelope):
peer = session.peer
mail_from = envelope.mail_from
rcpt_tos = envelope.rcpt_tos
data = envelope.content # type: bytes
# Process message data...
if error_occurred:
return '500 Could not process your message'
return '250 OK'
if __name__ == '__main__':
handler = CustomHandler()
controller = Controller(handler, hostname='127.0.0.1', port=10025)
# Run the event loop in a separate thread.
controller.start()
# Wait for the user to press Return.
input('SMTP server running. Press Return to stop server and exit.')
controller.stop()
Important differences to note:
* Unlike ``process_message()`` in smtpd, ``handle_DATA()`` **must** return
an SMTP response code for the sender such as ``"250 OK"``.
* ``handle_DATA()`` must be a coroutine function, which means it must be
declared with ``async def``.
* ``controller.start()`` runs the SMTP server in a separate thread and can be
stopped again by calling ``controller.stop()``.
|