mitgliederverwaltung/docs/smtp-configuration-concept.md
Simon a4f3aa5d6f
All checks were successful
continuous-integration/drone/push Build is passing
feat: add smtp settings
2026-03-12 13:39:48 +01:00

5.8 KiB
Raw Blame History

SMTP Configuration Concept

Status: Implemented
Last updated: 2026-03-12


1. Goal

Enable configurable SMTP for sending transactional emails (join confirmation, user confirmation, password reset). Configuration via environment variables and Admin Settings (database), with the same precedence pattern as OIDC and Vereinfacht: ENV overrides Settings. Include a test email action in Settings (button + recipient field) with clear success/error feedback.


2. Scope

  • In scope: SMTP server configuration (host, port, credentials, TLS/SSL), sender identity (from-name, from-email), test email from Settings UI, warning when SMTP is not configured in production, specific error messages per failure category, graceful delivery errors in AshAuthentication senders.
  • Out of scope: Separate adapters per email type; retry queues.

3. Configuration Sources

Source Priority Use case
ENV 1 Production, Docker, 12-factor
Settings 2 Admin UI, dev without ENV

When an ENV variable is set, the corresponding Settings field is read-only in the UI (with hint "Set by environment").


4. SMTP Parameters

Parameter ENV Settings attribute Notes
Host SMTP_HOST smtp_host e.g. smtp.example.com
Port SMTP_PORT smtp_port Default 587 (TLS), 465 (SSL), 25 (plain)
Username SMTP_USERNAME smtp_username Optional if no auth
Password SMTP_PASSWORD smtp_password Sensitive, not shown when set
Password file SMTP_PASSWORD_FILE Docker/Secrets: path to file with password
TLS/SSL SMTP_SSL smtp_ssl tls / ssl / none (default: tls)
Sender name MAIL_FROM_NAME smtp_from_name Display name in "From" header (default: Mila)
Sender email MAIL_FROM_EMAIL smtp_from_email Address in "From" header; must match SMTP user on most servers

Important: On most SMTP servers (e.g. Postfix with strict relay policies) the sender email (smtp_from_email) must be the same address as smtp_username or an alias that is owned by that account.


5. Password from File

Support SMTP_PASSWORD_FILE (path to file containing the password), same pattern as OIDC_CLIENT_SECRET_FILE in runtime.exs. Read once at runtime; SMTP_PASSWORD ENV overrides file if both are set.


6. Behaviour When SMTP Is Not Configured

  • Dev/Test: Keep current adapters (Swoosh.Adapters.Local, Swoosh.Adapters.Test). No change.
  • Production: If neither ENV nor Settings provide SMTP (no host):
    • Show a warning in the Settings UI.
    • Delivery attempts silently fall back to the Local adapter (no crash).

7. Test Email (Settings UI)

  • Location: SMTP / E-Mail section in Global Settings.
  • Elements: Input for recipient, submit button inside a phx-submit form.
  • Behaviour: Sends one email using current SMTP config and mail_from/0. Returns {:ok, _} or {:error, classified_reason}.
  • Error categories: :sender_rejected, :auth_failed, :recipient_rejected, :tls_failed, :connection_failed, {:smtp_error, message} — each shows a specific human-readable message in the UI.
  • Permission: Reuses existing Settings page authorization (admin).

8. Sender Identity (mail_from)

Mv.Mailer.mail_from/0 returns {name, email}. Priority:

  1. MAIL_FROM_NAME / MAIL_FROM_EMAIL ENV variables
  2. smtp_from_name / smtp_from_email in Settings (DB)
  3. Hardcoded defaults: {"Mila", "noreply@example.com"}

Provided by Mv.Config.mail_from_name/0 and Mv.Config.mail_from_email/0.


9. AshAuthentication Senders

Both SendPasswordResetEmail and SendNewUserConfirmationEmail use Mv.Mailer.deliver/1 (not deliver!/1). Delivery failures are logged (Logger.error) and not re-raised, so they never crash the caller process. AshAuthentication ignores the return value of send/3.


10. TLS / SSL in OTP 27

OTP 26+ enforces verify_peer by default, which fails for self-signed or internal SMTP server certificates.

Both tls_options: [verify: :verify_none] (for STARTTLS, port 587) and sockopts: [verify: :verify_none] (for direct SSL, port 465) are set in Mv.Mailer.smtp_config/0 to allow such certificates.

For ENV-based boot config, the same options are set in config/runtime.exs.


11. Summary Checklist

  • ENV: SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, SMTP_PASSWORD_FILE, SMTP_SSL.
  • ENV: MAIL_FROM_NAME, MAIL_FROM_EMAIL for sender identity.
  • Settings: attributes and UI for host, port, username, password, TLS/SSL, from-name, from-email.
  • Password from file: SMTP_PASSWORD_FILE supported in runtime.exs.
  • Mailer: Swoosh SMTP adapter configured from merged ENV + Settings when SMTP is configured.
  • Per-request SMTP config via Mv.Mailer.smtp_config/0 for Settings-only scenarios.
  • TLS certificate validation relaxed for OTP 27 (tls_options + sockopts).
  • Prod warning: clear message in Settings when SMTP is not configured.
  • Test email: form with recipient field, translatable content, classified success/error messages.
  • AshAuthentication senders: graceful error handling (no crash on delivery failure).
  • Gettext for all new UI strings, translated to German.
  • Docs and code guidelines updated.