Email¶
FastAuth sends five kinds of email: welcome, verification, password reset, email-change confirmation, and magic-link login. Email is opt-in: if email_transport is None (the default), every send_* is a silent no-op and the email-based flows still function — they just don't deliver anything. This is useful for local development.
Configure a transport¶
from fastauth.email_transports.console import ConsoleTransport # dev
from fastauth.email_transports.smtp import SMTPTransport # prod
from fastauth.email_transports.webhook import WebhookTransport # custom provider
# Console: prints to stdout. No deps.
config = FastAuthConfig(..., email_transport=ConsoleTransport())
# SMTP: requires [email] extra
config = FastAuthConfig(..., email_transport=SMTPTransport(
host="smtp.example.com", port=587,
username="user", password="pass",
from_email="noreply@example.com",
use_tls=True,
))
# Webhook: posts JSON {to, subject, body_html, body_text?} to a URL. Requires [oauth] (httpx).
config = FastAuthConfig(..., email_transport=WebhookTransport(
url="https://your-email-provider.example/send",
headers={"Authorization": "Bearer ..."},
))
Implement EmailTransport.send(to, subject, body_html, body_text=None) for anything else.
Templates¶
Built-in Jinja2 templates ship in fastauth/templates/. Override any of them by pointing email_template_dir at a directory; FastAuth uses a ChoiceLoader, so only the files you place there override the built-ins — everything else falls back automatically.
| File | Sent when | Variables |
|---|---|---|
welcome.jinja2 |
when you call EmailDispatcher.send_welcome_email |
name |
verification.jinja2 |
POST /auth/request-verify-email |
name, url, expires_in_minutes |
password_reset.jinja2 |
POST /auth/forgot-password |
name, url, expires_in_minutes |
email_change.jinja2 |
POST /auth/change-email |
name, new_email, url, expires_in_minutes |
magic_link_login.jinja2 |
POST /auth/magic-links/login |
name, url |
name resolves to user["name"] or user["email"] when the name is missing.
Link URLs¶
FastAuth builds the links using base_url:
| Flow | URL pattern |
|---|---|
| Email verification | {base_url}/auth/verify-email?token=... |
| Password reset | {base_url}/auth/reset-password?token=... |
| Email change | {base_url}/auth/account/confirm-email-change?token=... |
| Magic link | {base_url}/auth/magic-links/callback?token=... |
The token sent in the email is the raw token. The database stores its SHA-256 hash. Tokens are one-time; consumption is atomic on TokenAdapter.consume_token.
Common mistakes¶
- Setting
email_transportwithout theemailextra —SMTPTransportraisesMissingDependencyError: 'aiosmtplib' is required... Install: pip install sreekarnv-fastauth[email]when first used. - Expecting a verification email at registration — it is not sent. The user must call
POST /auth/request-verify-email. See Email verification. base_urlleft ashttp://localhost:8000in production — the link in the email will be unusable (or rejected bySecurecookies when clicked).