Appearance
SMTP providers
Sulu uses standard SMTP for all transactional email — verification, password reset, project invitations, workspace invitations, and the billing notification series. Any standards-compliant SMTP relay works; the table below documents the credentials and host/port for the providers we've verified.
For multi-line MIME and HTML email, Sulu uses SimpleMailMessage (plain text) — providers that require API access for HTML are out of scope.
Configuration
Set these env vars in your .env:
bash
SMTP_HOST=<provider host>
SMTP_PORT=<provider port>
SMTP_USER=<see provider section>
SMTP_PASS=<see provider section>
MAIL_FROM=[email protected]Sulu sets 10-second timeouts for connect / read / write — slow providers will fail fast rather than holding request threads.
Resend
bash
SMTP_HOST=smtp.resend.com
SMTP_PORT=465
SMTP_USER=resend
SMTP_PASS=re_xxxxxxxx... # your Resend API keyResend uses port 465 (SSL implicit). Username is the literal string resend; password is your API key.
Mailgun
bash
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587 # STARTTLS
SMTP_USER=[email protected]
SMTP_PASS=... # SMTP password from the Mailgun domain settings pageFor the EU region, use smtp.eu.mailgun.org instead.
AWS SES
bash
SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=587 # STARTTLS
SMTP_USER=AKIAxxxxxxxx # SMTP credentials (NOT the IAM access key)
SMTP_PASS=...SES requires an out-of-band "SMTP credentials" creation flow in the AWS console — these are NOT the same as your IAM access key. Replace us-east-1 with your actual region.
Postmark
Postmark's SMTP service was deprecated; new deployments need the HTTP API, which Sulu does not currently support out of the box. Use one of the SMTP-compatible providers above, or contribute an HTTP-API integration.
Self-hosted Postfix
bash
SMTP_HOST=localhost # if Postfix runs on the same host
SMTP_PORT=25 # or 587 if you've configured submission
SMTP_USER= # empty — no auth on local relay
SMTP_PASS=Note: empty username/password may require a Spring-side config tweak. If the relay doesn't accept anonymous connections, point at a remote authenticating relay instead.
Verifying delivery
After configuring, the simplest smoke test is to trigger the verification email flow:
bash
# Hit the registration endpoint with a real address you control
curl -X POST https://yourcompany.example/api/auth/register \
-H 'Content-Type: application/json' \
-d '{"fullName":"Test User","email":"[email protected]"}'Within seconds you should receive a Sulu verification email. Check your backend logs for Mail sent: verification — that's the success signal.
If the email never arrives, check provider deliverability dashboards (spam folder, suppression list, DMARC alignment) before assuming a Sulu problem.
Operational protections
- Per-recipient rate limit: out of the box, Sulu caps outbound email at 5 messages per recipient per hour (
SULU_MAIL_RATE_PER_RECIPIENT). Excess sends are dropped silently with a WARN log. This prevents bot-triggered loops on/forgot-passwordfrom flooding any single address. - Circuit breaker: if outbound SMTP fails at 50%+ over a rolling window of 10 calls, Sulu opens its circuit breaker for 60 seconds. During that window, further send attempts return immediately without hitting the provider. After 60s, three trial calls determine whether to close again.
Both are tunable via the SULU_MAIL_* env vars — see .env.example.