Send email from Django over SMTP
Django email configuration for SMTP: EMAIL_BACKEND, EMAIL_HOST, EMAIL_PORT, EMAIL_USE_TLS vs EMAIL_USE_SSL, credentials from the environment, send_mail and EmailMultiAlternatives, plus the console backend for development.
Install
# built in — django.core.mail
Complete example
# settings.py
import os
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = os.environ.get("SMTP_HOST", "smtp.queensmtp.com")
EMAIL_PORT = int(os.environ.get("SMTP_PORT", "587"))
EMAIL_USE_TLS = EMAIL_PORT == 587 # STARTTLS
EMAIL_USE_SSL = EMAIL_PORT == 465 # implicit TLS — never set both True
EMAIL_HOST_USER = os.environ["SMTP_USER"]
EMAIL_HOST_PASSWORD = os.environ["SMTP_PASS"]
EMAIL_TIMEOUT = 20
DEFAULT_FROM_EMAIL = "Your App <hello@yourdomain.com>"
SERVER_EMAIL = "alerts@yourdomain.com" # for error mails to ADMINS
# anywhere
from django.core.mail import send_mail, EmailMultiAlternatives
send_mail("Your receipt", "Thanks for your order #1042",
None, ["customer@example.com"]) # None = DEFAULT_FROM_EMAIL
msg = EmailMultiAlternatives("Your receipt", "Thanks for your order #1042",
None, ["customer@example.com"])
msg.attach_alternative("<h1>Thanks for your order</h1><p>#1042 is confirmed.</p>", "text/html")
msg.send()
# development: print instead of sending
# EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"What to know
- EMAIL_USE_TLS and EMAIL_USE_SSL are mutually exclusive; TLS = STARTTLS on 587, SSL = port 465.
- python manage.py sendtestemail you@yourdomain.com is the fastest test.
- Send from a background task (Celery/RQ) in production; SMTP round-trips add 0.5–2 s to a request.
- For a Gmail account use smtp.gmail.com with an App Password; for SES use the region endpoint and SMTP credentials — the settings block is otherwise identical.
Same code, different provider
Only the host, port and credentials change. The rules per provider are on the SMTP settings hub.
| Provider | Host | Port | Username | Password | Note |
|---|---|---|---|---|---|
| QueenSMTP | smtp.queensmtp.com | 587 (STARTTLS) / 465 (SSL) / 2525 | SMTP username from the dashboard | SMTP password | $5/year + $0.10 per 1,000; 100 free/day |
| Gmail | smtp.gmail.com | 587 / 465 | you@gmail.com | App Password | 500/day, From must be the account |
| Amazon SES | email-smtp.<region>.amazonaws.com | 587 / 465 / 2587 | SES SMTP username | SES SMTP password | sandbox 200/day until approved |
| Office 365 | smtp.office365.com | 587 | user@yourdomain.com | mailbox password | SMTP AUTH must be enabled; 30/min |
| SendGrid | smtp.sendgrid.net | 587 / 465 / 2525 | apikey | API key | no free plan since 2025 |
Credentials for the example above
Create a free account, verify your sending domain (SPF + DKIM shown in the dashboard), add an SMTP credential, and paste it into the code. 100 emails a day free; $5/year plus $0.10 per 1,000 after that. Prefer HTTPS? The same account has a REST email API.
Get SMTP credentials Test your settings firstOther languages and frameworks
Django SMTP — questions
Run python manage.py sendtestemail your@address; check EMAIL_HOST/PORT/TLS match the provider; on a cloud VM confirm the port is not blocked (25 usually is). Set EMAIL_BACKEND to the console backend to verify your code path first.
Related Guides
Continue learning with these related articles