SMTP Backend¶
The SMTP backend (SMTPBackend) sends emails via any SMTP server — Gmail, Mailgun, your own Postfix, etc.
Installation¶
pip install amsdal_mail[smtp]
The [smtp] extra installs aiosmtplib for async support.
Configuration¶
Environment Variables¶
| Variable | Default | Description |
|---|---|---|
AMSDAL_EMAIL_HOST |
localhost |
SMTP server hostname |
AMSDAL_EMAIL_PORT |
25 |
SMTP server port |
AMSDAL_EMAIL_USER |
— | Authentication username |
AMSDAL_EMAIL_PASSWORD |
— | Authentication password |
AMSDAL_EMAIL_USE_TLS |
false |
Use STARTTLS (upgrade to TLS after connecting) |
AMSDAL_EMAIL_USE_SSL |
false |
Use SSL/TLS from the start |
AMSDAL_EMAIL_TIMEOUT |
30 |
Connection timeout in seconds |
Constructor Parameters¶
All constructor parameters mirror the env vars above and take precedence over them:
from amsdal_mail import get_connection
conn = get_connection(
'smtp',
host='smtp.gmail.com',
port=587,
username='you@gmail.com',
password='your-app-password',
use_tls=True,
)
Gmail Setup¶
Gmail requires an App Password (not your regular password). Enable 2-Step Verification first, then generate an App Password.
export AMSDAL_EMAIL_BACKEND=smtp
export AMSDAL_EMAIL_HOST=smtp.gmail.com
export AMSDAL_EMAIL_PORT=587
export AMSDAL_EMAIL_USER=you@gmail.com
export AMSDAL_EMAIL_PASSWORD=your-app-password
export AMSDAL_EMAIL_USE_TLS=true
from amsdal_mail import send_mail
status = send_mail(
subject='Hello from AMSDAL',
message='This email was sent via Gmail SMTP.',
from_email='you@gmail.com',
recipient_list=['recipient@example.com'],
)
TLS vs SSL¶
| Mode | Port | How It Works |
|---|---|---|
STARTTLS (use_tls=True) |
587 | Connects in plain text, then upgrades to TLS |
SSL/TLS (use_ssl=True) |
465 | Encrypted from the start |
| Neither | 25 | No encryption (not recommended) |
Warning
Do not set both use_tls and use_ssl to True — they are mutually exclusive.
Connection Pooling¶
Use the context manager to send multiple messages over a single SMTP connection:
from amsdal_mail import get_connection, EmailMessage
with get_connection('smtp') as conn:
for user in users:
msg = EmailMessage(
subject='Notification',
body=f'Hello {user.name}!',
from_email='noreply@example.com',
to=[user.email],
)
conn.send_messages([msg])
The connection is opened on __enter__ and closed on __exit__.
HTML Email with Attachments¶
from amsdal_mail import EmailMessage, Attachment, get_connection
msg = EmailMessage(
subject='Invoice #1234',
body='Please find your invoice attached.',
html_body='<h1>Invoice #1234</h1><p>See attachment.</p>',
from_email='billing@example.com',
to=['customer@example.com'],
attachments=[
Attachment(
filename='invoice-1234.pdf',
content=pdf_bytes,
mimetype='application/pdf',
),
],
)
conn = get_connection('smtp')
status = conn.send_messages([msg])
Inline Images¶
from amsdal_mail import EmailMessage, Attachment, get_connection
msg = EmailMessage(
subject='Newsletter',
body='See HTML version.',
html_body='<img src="cid:header"><h1>Weekly Update</h1>',
from_email='news@example.com',
to=['subscriber@example.com'],
attachments=[
Attachment(
filename='header.png',
content=header_bytes,
mimetype='image/png',
content_id='header',
),
],
)
conn = get_connection('smtp')
status = conn.send_messages([msg])
Async¶
The async version uses aiosmtplib:
from amsdal_mail import asend_mail
status = await asend_mail(
subject='Hello',
message='Sent asynchronously via SMTP.',
from_email='noreply@example.com',
recipient_list=['user@example.com'],
)
Or with EmailMessage directly:
from amsdal_mail import EmailMessage, get_connection
conn = get_connection('smtp')
status = await conn.asend_messages([msg])
Per-Recipient Status¶
SMTP returns per-recipient accept/reject results. The backend maps these to SendStatus:
- Accepted recipients get status
'sent' - Rejected with SMTP code >= 500 get
'rejected' - Rejected with SMTP code < 500 get
'failed'
Note
SMTP does not return message IDs, so RecipientStatus.message_id is always None for the SMTP backend.