Administration

Email setup

Configure SMTP for verification, password reset, magic link, one-time code and invitation e-mails.

Auth Service sends e-mail with Nodemailer. E-mail is required whenever a flow that depends on it is active, and in production that is the case by default.

Configuration

SMTP_HOST=smtp.example.com
SMTP_PORT=587                  # defaults to 587
SMTP_USER=user@example.com
SMTP_PASS=your-smtp-password
SMTP_FROM=Auth Service <no-reply@example.com>
MAIL_REPLY_TO=support@example.com   # optional

Port 465 uses implicit TLS; every other port uses STARTTLS negotiation. Authentication is sent only when both SMTP_USER and SMTP_PASS are set; otherwise Nodemailer connects without authentication, which suits a local relay.

When SMTP is mandatory

With NODE_ENV=production (which the Compose stack forces):

  • REQUIRE_EMAIL_VERIFICATION is on by default: a user cannot sign in before following the link sent to their address. The bundled Compose file and .env.example set it to false, so a Compose deployment verifies addresses only after you set REQUIRE_EMAIL_VERIFICATION=true.
  • MAGIC_LINK_ENABLED and EMAIL_OTP_ENABLED add passwordless sign-in by e-mail, for existing accounts only. Both are off by default.
  • If any of these three is on and SMTP_HOST is empty, the process refuses to start.
  • When SMTP_HOST is set, the SMTP connection is checked at startup, and a failure is fatal. Outside production it is only logged as a warning.

To run a production instance without e-mail, set REQUIRE_EMAIL_VERIFICATION=false explicitly. Without SMTP, e-mails are then dropped with a log line, which also means users cannot reset a forgotten password by themselves.

E-mails sent

TriggerTemplate
E-mail verification (sign-up, import, resend by an administrator)verify-email.eml
"Forgot your password?"reset-password.eml
Magic-link sign-inmagic-link.eml
One-time code sign-inemail-otp.eml
Invitation to an organizationorg-invitation.eml
Invitation to register with an applicationregistration-invitation.eml
E-mail address changechange-email.eml

Every template can be overridden globally with a file under <TEMPLATES_DIR>/default/emails/: see Custom templates. A per-application override (<TEMPLATES_DIR>/<appSlug>/emails/) is honoured for the e-mails that have an application context: registration-invitation, and the verification, password reset, change-email and magic-link e-mails when their link was issued for a request carrying that application's client_id.

Sending is rate limited per IP address to 5 requests per minute on the endpoints that send e-mail (MAIL_003, 429), and the credential endpoints (sign-in, sign-up, password reset, two-factor verification) to 10 per minute (RATE_001). Mailing a large user base at once, for example after a migration, should be spread over time.

Testing locally

The Compose file ships a mail catcher behind the mail profile:

docker compose --profile mail up -d
SMTP_HOST=mailpit
SMTP_PORT=1025

Every message sent by the stack then shows up in the Mailpit web interface at http://localhost:8025.

Copyright © 2026