{"id":4872,"library":"aiosmtpd","title":"aiosmtpd - Asyncio-based SMTP Server","description":"aiosmtpd is an asyncio-based SMTP and LMTP server, providing an asynchronous, RFC 5321 compliant server that supports customizable extensions. It serves as a modern replacement for the deprecated `smtpd` module in the Python standard library. The current version is 1.4.6, and it's actively maintained under the aio-libs umbrella project.","status":"active","version":"1.4.6","language":"en","source_language":"en","source_url":"https://github.com/aio-libs/aiosmtpd","tags":["asyncio","smtp","email","server","mail","lmtp"],"install":[{"cmd":"pip install aiosmtpd","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Officially tested on CPython>=3.9 and PyPy>=3.9, though PyPI metadata states >=3.8. Future versions will drop Python 3.8 support.","package":"Python","optional":false}],"imports":[{"note":"The Controller class is in the 'controller' submodule.","wrong":"from aiosmtpd import Controller","symbol":"Controller","correct":"from aiosmtpd.controller import Controller"},{"note":"Directly using SMTP is possible but Controller is often preferred for managing the server in a separate thread.","symbol":"SMTP","correct":"from aiosmtpd.smtp import SMTP"},{"note":"Commonly used handler for testing, discards all incoming mail.","symbol":"handlers.Sink","correct":"from aiosmtpd.handlers import Sink"},{"note":"Default handler for the command-line script; prints incoming mail to stdout.","symbol":"handlers.Debugging","correct":"from aiosmtpd.handlers import Debugging"}],"quickstart":{"code":"import asyncio\nfrom aiosmtpd.controller import Controller\nfrom aiosmtpd.handlers import Debugging\nimport os\n\nasync def amain():\n    # Use Debugging handler to print incoming emails to console\n    handler = Debugging()\n    \n    # The Controller runs the SMTP server in a separate thread.\n    # For testing/quickstart, localhost:8025 is common.\n    controller = Controller(handler, hostname=os.environ.get('SMTP_HOST', '127.0.0.1'), port=int(os.environ.get('SMTP_PORT', 8025)))\n    \n    print(f\"Starting SMTP server on {controller.hostname}:{controller.port}...\")\n    controller.start()\n    print(\"SMTP server started. Press Ctrl+C to stop.\")\n    \n    try:\n        # Keep the main loop running while the controller's thread handles the SMTP server\n        await asyncio.Event().wait()\n    except asyncio.CancelledError:\n        pass\n    finally:\n        controller.stop()\n        print(\"SMTP server stopped.\")\n\nif __name__ == '__main__':\n    # Run the asyncio event loop\n    try:\n        asyncio.run(amain())\n    except KeyboardInterrupt:\n        print(\"Server interrupted by user.\")\n","lang":"python","description":"This quickstart sets up a basic SMTP server on `127.0.0.1:8025` using the `Debugging` handler, which prints all received emails to the console. It leverages `Controller` to run the server in a separate thread, allowing the main program to continue running or wait for interruption. You can connect to this server with any SMTP client (e.g., `smtplib` or `telnet`)."},"warnings":[{"fix":"Update `handle_NOOP(self, server)` to accept the `server` argument: `async def handle_NOOP(self, server): ...`","message":"The signature of the `handle_NOOP()` method in custom handlers changed from taking zero arguments to requiring a single argument in version 1.4.x. Custom handlers implementing this method must be updated.","severity":"breaking","affected_versions":">=1.4.0"},{"fix":"If clients connect without STARTTLS and require AUTH, initialize `Controller` or `SMTP` with `auth_require_tls=False`: `Controller(handler, ..., auth_require_tls=False)`.","message":"By default, the SMTP AUTH extension might not be advertised or supported by the server unless a STARTTLS command is issued first, or `auth_require_tls=False` is explicitly passed to the `Controller` or `SMTP` constructor. This can cause authentication failures with clients expecting immediate AUTH support.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Migrate `process_message()` logic to `async def handle_DATA(self, server, session, envelope): ...` ensuring it returns an SMTP response string (e.g., `'250 OK'`).","message":"The `process_message()` method in handler classes was deprecated. Implementations should now use the asynchronous `handle_DATA(self, server, session, envelope)` method for processing incoming mail data.","severity":"deprecated","affected_versions":"<1.0a5"},{"fix":"Replace `authentication_handler=my_func` with `authenticator=Authenticator(my_func)` (where `Authenticator` is imported from `aiosmtpd.smtp`).","message":"The `authentication_handler` parameter for the `SMTP` class constructor was deprecated in favor of `authenticator` and is scheduled for removal in version 2.0.","severity":"deprecated","affected_versions":">=1.3.0"},{"fix":"Adjust tests or application logic that rely on a specific short startup timeout, or explicitly set `ready_timeout` in the `Controller` constructor: `Controller(handler, ..., ready_timeout=1.0)`.","message":"The default `ready_timeout` for `Controller.start()` to wait for the SMTP server thread to become ready changed from 1 second to 5 seconds. This could impact testing setups or deployments sensitive to startup times.","severity":"gotcha","affected_versions":">=1.4.2"},{"fix":"Ensure your environment uses Python 3.9 or newer to guarantee compatibility with current and future `aiosmtpd` releases.","message":"While PyPI states `requires_python >=3.8`, the official documentation recommends CPython>=3.9 and PyPy>=3.9. The upcoming version 1.4.7 explicitly drops support for Python 3.8, requiring an upgrade if using newer `aiosmtpd` versions.","severity":"breaking","affected_versions":">=1.4.7 (future)"}],"env_vars":null,"last_verified":"2026-04-12T00:00:00.000Z","next_check":"2026-07-11T00:00:00.000Z"}