- Dev —
StderrEmailSenderprints mail bodies (including the magic link) to stderr. No keys needed. - Production —
ResendEmailSender, used automatically when bothRESEND_API_KEYandHEXGATE_EMAIL_FROMare set.
Production config
HEXGATE_DASHBOARD_URL
controls the host inside the link the user clicks; misconfiguring it
sends users to localhost.
What gets sent
Both link routes are pre-mounted on the dashboard and consume the token
via the FastAPI-Users
/v1/auth/verify and /v1/auth/reset-password
endpoints, respectively.
Failure handling
Provider failures (network, 5xx, invalid from-address) are logged at ERROR level but never 5xx the calling endpoint — the user gets a successful submit, the operator sees the log line, and the user can click “Resend email” on the verification banner. Same shape for password reset. Partial config (onlyRESEND_API_KEY set, no HEXGATE_EMAIL_FROM or
vice versa) is treated as dev mode and keeps StderrEmailSender —
better to surface “stderr sender active” at startup than to silently
have every send rejected by Resend at delivery time.
Testing
platform/api/tests/test_mailer.py covers the Resend sender in
isolation by patching resend.Emails.send. The auth-flow tests in
test_auth.py use a list-capturing sender via the outbox fixture so
they read the would-have-been-mailed token directly — no Resend in the
test loop.