File: migrating.rst

package info (click to toggle)
python-aiosmtpd 1.4.6-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,016 kB
  • sloc: python: 8,064; makefile: 159
file content (59 lines) | stat: -rw-r--r-- 2,129 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 :mod:`smtpd` to aiosmtpd.

Consider the following subclass of :class:`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 :meth:`~smtpd.SMTPServer.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``.
* :meth:`Controller.start` runs the SMTP server in a separate thread and can be
  stopped again by calling :meth:`Controller.stop`