Asyncio SMTP Client
aiosmtplib is an asynchronous SMTP client for use with asyncio. It provides an async version of Python's `smtplib` module with similar APIs, enabling non-blocking email sending and interaction with SMTP servers. The current version is 5.1.0, and the project actively maintains compatibility with recent Python versions while introducing new features like XOAUTH2 authentication.
Warnings
- breaking Python 3.9 support was dropped in v5.0.0. Earlier versions (v4.0.0, v3.0.0) also dropped support for Python 3.8 and 3.7 respectively. Ensure your environment meets the `requires_python >=3.10` for v5.x.x.
- breaking In v3.0.0, argument handling for `SMTP` initialization and `connect()` changed significantly. Positional arguments became positional-only, and keyword arguments became keyword-only. Additionally, the `source_address` argument now requires a `(addr, port)` tuple instead of a string, and `local_hostname` should be used for the EHLO/HELO message hostname.
- gotcha When connecting, carefully distinguish between `use_tls=True` (for direct TLS/SSL on ports like 465) and `start_tls=True` (for upgrading a plaintext connection to TLS, typically on port 587 after connecting). Incorrectly combining these, e.g., `use_tls=True` for a STARTTLS-only server, can lead to connection errors.
- gotcha SMTP is a sequential protocol. While `aiosmtplib` is asynchronous, executing multiple `send_message()` calls in parallel with a *single* `SMTP` client instance (e.g., using `asyncio.gather`) will not be more efficient than sequential execution, as the client must wait for one mail to be sent before starting the next. Consider creating multiple `SMTP` instances for parallel sending if high throughput is needed.
Install
-
pip install aiosmtplib
Imports
- SMTP
from aiosmtplib import SMTP
- send
from aiosmtplib import send
Quickstart
import asyncio
import os
from email.message import EmailMessage
from aiosmtplib import send
async def main():
sender_email = os.environ.get('SMTP_SENDER_EMAIL', 'sender@example.com')
recipient_email = os.environ.get('SMTP_RECIPIENT_EMAIL', 'recipient@example.com')
smtp_host = os.environ.get('SMTP_HOST', 'localhost')
smtp_port = int(os.environ.get('SMTP_PORT', 25))
smtp_password = os.environ.get('SMTP_PASSWORD', None)
message = EmailMessage()
message['From'] = sender_email
message['To'] = recipient_email
message['Subject'] = 'Hello from aiosmtplib!'
message.set_content('This is a test email sent using aiosmtplib.')
try:
await send(
message,
hostname=smtp_host,
port=smtp_port,
username=sender_email if smtp_password else None,
password=smtp_password,
start_tls=True if smtp_port == 587 else False, # Use STARTTLS for common submission port
use_tls=True if smtp_port == 465 else False # Use direct TLS for common SMTPS port
)
print(f"Email sent successfully from {sender_email} to {recipient_email}")
except Exception as e:
print(f"Failed to send email: {e}")
if __name__ == '__main__':
asyncio.run(main())