INTEGRATIONS · Published 2026-10-06 · Updated 2026-10-06 · SecureSMTP
Django
Settings for Django’s SMTP email backend, so send_mail() goes through SecureSMTP.
Django’s built-in SMTP email backend works with SecureSMTP. Change the settings and send_mail(), the password-reset emails and error emails to ADMINS all go through SecureSMTP. No package to install.
Setup
Every request needs your site’s API key. Get it when you add the site under Sites (/app/forms/sites) in the dashboard — see Sites and API keys. Keep it in an environment variable on the server:
export SECURESSMTP_API_KEY="qcs_live_..."Settings
# settings.py
import os
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.securessmtp.com"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = "securessmtp"
EMAIL_HOST_PASSWORD = os.environ["SECURESSMTP_API_KEY"]
EMAIL_TIMEOUT = 30
DEFAULT_FROM_EMAIL = "Acme Store <[email protected]>"
SERVER_EMAIL = DEFAULT_FROM_EMAIL # used for error emails to ADMINSTo use port 465 instead of 587:
EMAIL_PORT = 465
EMAIL_USE_SSL = True # instead of EMAIL_USE_TLS; do not set both[email protected] with your From name, and the From address you set becomes the Reply-To. Verify your domain and the email goes out from your own address. See Domains and DNS.Send an email
from django.core.mail import send_mail
send_mail(
subject="Your order has shipped",
message="Your order is on its way.",
from_email=None, # uses DEFAULT_FROM_EMAIL
recipient_list=["[email protected]"],
html_message="<p>Your order is on its way.</p>",
fail_silently=False,
)With HTML and an attachment (up to 15 MB in total):
from django.core.mail import EmailMultiAlternatives
email = EmailMultiAlternatives(
subject="Invoice 1042",
body="Your invoice is attached.",
to=["[email protected]"],
)
email.attach_alternative("<p>Your invoice is attached.</p>", "text/html")
email.attach_file("invoices/invoice-1042.pdf")
email.send()Handle errors
With fail_silently=False (the default), a refused email raises an smtplib exception that carries the SMTP reply code:
import logging
import smtplib
from django.core.mail import send_mail
logger = logging.getLogger(__name__)
try:
send_mail("Hello", "Hi there.", None, ["[email protected]"])
except smtplib.SMTPResponseException as err:
# err.smtp_code is the SMTP reply, e.g. 450 rate limit, 550 rejected
logger.error("Email rejected: %s %s", err.smtp_code, err.smtp_error)
except (smtplib.SMTPException, OSError) as err:
logger.error("Email failed: %s", err)| SMTP reply | Meaning |
|---|---|
250 | Accepted. |
535 | Login failed: the password is not a valid API key. |
450 4.7.0 | Rate limit: more than 120 sends from this site in 60 seconds. Retry later. |
550 5.7.0 | Monthly email limit reached. |
550 5.7.1 | Rejected as spam, the site is disabled, or every recipient has unsubscribed. |
550 5.1.1 | Every recipient is on the suppression list. |
552 5.3.4 | Attachments are over 15 MB in total. |
4xx 4.3.0 | Temporary failure. Retry later. |
Or call the API
To get the message_id back or use API-only fields such as template, copy securessmtp.py from the Python guide into your app and call it from a view or a task:
# views.py: call the API instead of SMTP
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from .securessmtp import SecureSMTPError, send_email
@require_POST
def notify(request):
try:
result = send_email({
"to": "[email protected]",
"subject": "Your order has shipped",
"text": "Your order is on its way.",
"from": {"name": "Acme Store"},
})
except SecureSMTPError as err:
return JsonResponse({"ok": False, "reason": err.reason}, status=502)
return JsonResponse({"ok": True, "message_id": result["message_id"]})- Check
okin the body, not only the HTTP status. Rate limit, monthly limit and send failures come back with HTTP 200. - There is no idempotency key. If a request times out, the email may already have been sent, and sending it again can deliver it twice.
- Every reason is listed in the error catalogue.
Next
- SMTP details and limits: SMTP.
- Send from your own address: Domains and DNS.
- Find an email and see what happened to it: Email log.