从 smtpd 迁移到 aiosmtpd

aiosmtpd is designed to make it easy to migrate an existing application based on smtpd 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() 方法:

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:

  • 不像 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()