aiosmtpd - Asyncio-based SMTP Server
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.
Warnings
- breaking 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.
- gotcha 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.
- deprecated 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.
- deprecated The `authentication_handler` parameter for the `SMTP` class constructor was deprecated in favor of `authenticator` and is scheduled for removal in version 2.0.
- gotcha 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.
- breaking 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.
Install
-
pip install aiosmtpd
Imports
- Controller
from aiosmtpd.controller import Controller
- SMTP
from aiosmtpd.smtp import SMTP
- handlers.Sink
from aiosmtpd.handlers import Sink
- handlers.Debugging
from aiosmtpd.handlers import Debugging
Quickstart
import asyncio
from aiosmtpd.controller import Controller
from aiosmtpd.handlers import Debugging
import os
async def amain():
# Use Debugging handler to print incoming emails to console
handler = Debugging()
# The Controller runs the SMTP server in a separate thread.
# For testing/quickstart, localhost:8025 is common.
controller = Controller(handler, hostname=os.environ.get('SMTP_HOST', '127.0.0.1'), port=int(os.environ.get('SMTP_PORT', 8025)))
print(f"Starting SMTP server on {controller.hostname}:{controller.port}...")
controller.start()
print("SMTP server started. Press Ctrl+C to stop.")
try:
# Keep the main loop running while the controller's thread handles the SMTP server
await asyncio.Event().wait()
except asyncio.CancelledError:
pass
finally:
controller.stop()
print("SMTP server stopped.")
if __name__ == '__main__':
# Run the asyncio event loop
try:
asyncio.run(amain())
except KeyboardInterrupt:
print("Server interrupted by user.")