Before you start
Tick off what you already have. New to tinyRelay? See how onboarding works.
[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
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.
python manage.py shell
>>> from django.core.mail import send_mail
>>> send_mail("tinyRelay SMTP test", "It works.", None, ["you@example.com"])
1Send 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.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
tinyRelay posts signed webhook events (SEND, DELIVERED, BOUNCED, OPEN, CLICK, UNSUBSCRIBE and SPAM) with your metadata on each one.
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
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.
Check [SMTP host] and [port]. Some hosting providers block outbound SMTP ports; ask yours if a correct host and port still time out.
The encryption mode does not match the port. STARTTLS and implicit TLS are different settings; use the [encryption] you were given.
Send from an address on a domain that was set up with tinyRelay during onboarding.
Check the DKIM CNAME on your sender domain, then the recipient address. The email bounce codes reference explains each bounce category.
FAQ
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
- SMTP relay service
- Send email with Python over the REST API
- Verification code emails
- SMTP vs API
- tinyRelay docs: setup