File: migrating.rst

package info (click to toggle)
python-aiosmtpd 1.2.2-1%2Bdeb11u1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,704 kB
  • sloc: python: 3,838; makefile: 39
file content (59 lines) | stat: -rw-r--r-- 2,145 bytes parent folder | download | duplicates (2)
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()``.