Guide · SMTP · Django

Django email SMTP settings

To send Django email through tinyRelay, keep the default SMTP backend and set EMAIL_HOST, EMAIL_PORT, the credentials and exactly one of EMAIL_USE_TLS or EMAIL_USE_SSL in settings.py. send_mail then goes through the relay.

1EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
2EMAIL_HOST = "[SMTP host]"
3EMAIL_PORT = [port]
4EMAIL_HOST_USER = "[SMTP username]"
5EMAIL_HOST_PASSWORD = "[SMTP password]"
6EMAIL_USE_TLS = True # STARTTLSEMAIL_USE_SSL = True # implicit TLS
7DEFAULT_FROM_EMAIL = "Acme <no-reply@acme.com>"
>>> send_mail("tinyRelay SMTP test", "It works.", None, ["you@example.com"])
1
THIS LINEDjango's default SMTP backend. Nothing to install.

Hover a line to pin it.Bracketed values come from onboarding.

Before you start

Tick off what you already have. New to tinyRelay? See how onboarding works.

SMTP host, port and encryption are issued at onboarding. This guide shows them as [SMTP host], [port] and [encryption]. Whether SMTP sends receive the same webhooks and metadata as API sends is being confirmed.

Configure Django email SMTP settings

Django's SMTP backend reads its connection from settings. Load the secrets from the environment so they stay out of your repository.

1. Put the credentials in the environment

EnvironmentCopy
export TINYRELAY_SMTP_HOST="[SMTP host]"
export TINYRELAY_SMTP_PORT="[port]"
export TINYRELAY_SMTP_USER="[SMTP username]"
export TINYRELAY_SMTP_PASSWORD="[SMTP password]"

2. Set the EMAIL_* settings

Choose the tab that matches the [encryption] you were given. Set only one of EMAIL_USE_TLS and EMAIL_USE_SSL.

# settings.py
import os

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = os.environ["TINYRELAY_SMTP_HOST"]        # [SMTP host]
EMAIL_PORT = int(os.environ["TINYRELAY_SMTP_PORT"])   # [port]
EMAIL_HOST_USER = os.environ["TINYRELAY_SMTP_USER"]
EMAIL_HOST_PASSWORD = os.environ["TINYRELAY_SMTP_PASSWORD"]
EMAIL_USE_TLS = True        # [encryption] is STARTTLS
EMAIL_TIMEOUT = 10
DEFAULT_FROM_EMAIL = "Acme <no-reply@acme.com>"
# settings.py
import os

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = os.environ["TINYRELAY_SMTP_HOST"]        # [SMTP host]
EMAIL_PORT = int(os.environ["TINYRELAY_SMTP_PORT"])   # [port]
EMAIL_HOST_USER = os.environ["TINYRELAY_SMTP_USER"]
EMAIL_HOST_PASSWORD = os.environ["TINYRELAY_SMTP_PASSWORD"]
EMAIL_USE_SSL = True        # [encryption] is implicit TLS; never set both
EMAIL_TIMEOUT = 10
DEFAULT_FROM_EMAIL = "Acme <no-reply@acme.com>"

3. Send a test from the shell

With from_email set to None, Django uses DEFAULT_FROM_EMAIL.

TerminalCopy
python manage.py shell

>>> from django.core.mail import send_mail
>>> send_mail("tinyRelay SMTP test", "It works.", None, ["you@example.com"])
1

Send Django email from your app

Use send_mail with html_message for a plain-text and HTML version together. Password reset emails from django.contrib.auth use the same settings.

accounts/emails.pyCopy
# accounts/emails.py
from django.core.mail import send_mail
from django.template.loader import render_to_string


def send_confirmation(user, confirm_url):
    send_mail(
        subject="Confirm your Acme email address",
        message=f"Hi {user.first_name}, confirm your address: {confirm_url}",
        from_email=None,  # uses DEFAULT_FROM_EMAIL
        recipient_list=[user.email],
        html_message=render_to_string(
            "emails/confirm.html", {"user": user, "confirm_url": confirm_url}
        ),
    )

Need per-recipient metadata?

SMTP sends one message per recipient. If you want one request for many recipients, each with their own IDs echoed on webhooks, call the REST API instead: see send email with Python.

Delivery events and the REST API

Documented
REST API sends

tinyRelay posts signed webhook events (SEND, DELIVERED, BOUNCED, OPEN, CLICK, UNSUBSCRIBE and SPAM) with your metadata on each one.

Being confirmed
SMTP sends

Whether SMTP sends receive the same webhooks and metadata is being confirmed, and this guide will be updated when it is.

If you need your own IDs echoed on every event today, send those messages through the API instead: see the transactional email API and email webhooks.

Troubleshooting

What do you see?5 common symptoms
Authentication failedWhat to check

The username or password does not match what was issued at onboarding. Copy them again and check for stray quotes or spaces in your environment file.

Connection timed out or refusedWhat to check

Check [SMTP host] and [port]. Some hosting providers block outbound SMTP ports; ask yours if a correct host and port still time out.

TLS or SSL handshake errorWhat to check

The encryption mode does not match the port. STARTTLS and implicit TLS are different settings; use the [encryption] you were given.

Sender address rejectedWhat to check

Send from an address on a domain that was set up with tinyRelay during onboarding.

Accepted but never arrivesWhat to check

Check the DKIM CNAME on your sender domain, then the recipient address. The email bounce codes reference explains each bounce category.

FAQ

What SMTP host and port does tinyRelay use with Django?

They are issued at onboarding with your SMTP username and password, so this guide shows them as placeholders. Set EMAIL_HOST and EMAIL_PORT to the values you were given.

Use EMAIL_USE_TLS for STARTTLS and EMAIL_USE_SSL for implicit TLS, matching the encryption issued at onboarding. Django treats them as mutually exclusive, so set only one to True.

The from_email you pass. If you pass None, Django uses DEFAULT_FROM_EMAIL. Use an address on a domain set up with tinyRelay.

This is being confirmed. Email sent through the REST API gets signed webhook events with your metadata; this guide will be updated for SMTP.

Next steps

Sources

Get started

Send transactional email with a service that reports back.

SMTP relay or REST API, standalone or alongside tinyEmail. Tell us what you send and our team sets you up.