Seven distinct email types flow through Auth0's email provider: verification, welcome, password change, blocked account, breached password, MFA verification, and user invitation. Every one of them ships through a default test provider that's rate-limited and explicitly meant for development — Auth0's own docs tell you to replace it before production.
The usual replacement is a one-way transactional service. But there's a more interesting option: point Auth0's SMTP settings at a mailbox your app fully owns, so the address that sends your password-reset emails can also receive what comes back. A Nylas Agent Account — a hosted, API-controlled mailbox, currently in beta — fits that slot. Here's the wiring.
Create the mailbox with an app password
Auth0's SMTP client authenticates with an app_password set on the grant — not your API key. Set it at creation:
curl --request POST \
--url "https://api.us.nylas.com/v3/connect/custom" \
--header "Authorization: Bearer $NYLAS_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"provider": "nylas",
"settings": {
"email": "noreply@notifications.yourcompany.com",
"app_password": "MySecureP4ssword!2024"
}
}'
If you live in the terminal, the Nylas CLI does the same thing in one line:
nylas agent account create noreply@notifications.yourcompany.com \
--app-password "MySecureP4ssword!2024"
Save both the returned grant_id and the password. The password is stored as a bcrypt hash, so it can be reset later but never read back. Rules: 18–40 characters, mixed case, a digit, printable ASCII — full details in mail client access.
You'll need a domain registered first. A *.nylas.email trial subdomain works with zero DNS setup for prototyping; production wants your own domain with MX and TXT records, per the provisioning guide.
Fill in five fields on the Auth0 side
In the Auth0 Dashboard: Branding → Email Provider, toggle Use my own email provider on, pick SMTP (the generic option, not a named integration). Then:
| Auth0 field | Value |
|---|---|
| From | noreply@notifications.yourcompany.com |
| Host |
mail.us.nylas.email (or mail.eu.nylas.email for EU) |
| Port | 587 |
| Username | Same as From |
| Password | The app_password from step 1 |
Two constraints hide in that table. The From must match the Username — SMTP submissions where MAIL FROM doesn't match the authenticated account get rejected, and Auth0 surfaces that as a verification failure on save. And port 587 with STARTTLS is Auth0's recommended default, but 465 (implicit TLS) works on the same host if your environment blocks 587. Avoid port 25 entirely; Auth0 warns against it and many networks drop it.
Scripting it instead? PATCH /api/v2/emails/provider on the Management API — but note Auth0 requires host, port, username, and password together on every update. Rotating just the password still means sending all four.
Verify with a real send
Click Send Test Email, or sign up a throwaway user to fire a verification email. The message should arrive from your address, and a copy lands in the account's Sent folder — confirm via GET /v3/grants/{grant_id}/messages?in=sent.
If it fails, skip the guessing: Auth0's Monitoring → Logs records SMTP errors with the exact server response. A credentials typo and a DNS misconfiguration look identical from the outside but completely different in that log.
What you get that SES doesn't give you
Here's the part that makes this more than an SMTP swap. When a confused user hits "reply" on a verification email — and some always do — that reply doesn't evaporate. It lands in the mailbox's inbox and fires a message.created webhook your app can act on, whether that means routing to support or letting an agent answer. The reply-handling recipe covers the loop.
A few operational notes from the field:
- Customize templates first. All seven email types route through this provider the moment you flip the switch. Edit them under Branding → Email Templates before going live, or users get Auth0's defaults from your shiny new sender.
-
Use a dedicated subdomain.
notifications.yourcompany.comkeeps auth-mail reputation isolated from your team's primary domain. A deliverability dip on reset emails shouldn't touch everyone's regular mail. - Mind the send cap: 200 messages per account per day on the free plan. Fine for a low-volume B2B tenant; a B2C app with steady signups should move to a paid plan or split traffic across multiple accounts.
-
Password rotation is two steps. Update
settings.app_passwordon the grant, then re-paste it into Auth0 (with the other three unchanged fields, per the all-or-nothing rule above). Active SMTP sessions disconnect on the next authenticated command.
When it breaks: a short troubleshooting map
| Symptom | Likely cause | Where to look |
|---|---|---|
| Verification fails when you save the provider | From doesn't match Username — the SMTP submission is rejected when MAIL FROM differs from the authenticated account |
The five-field table above; make both the same address |
| Test email never sends | Connection blocked on port 587 | Switch to port 465 (implicit TLS, same host) |
| Test email fails with an opaque error | Credentials typo or DNS misconfiguration | Auth0 Monitoring → Logs — the SMTP server response is recorded verbatim |
| Password rotation "didn't take" | Partial Management API update |
PATCH /api/v2/emails/provider requires host, port, username, and password together — send all four |
The Monitoring → Logs entry is the one to remember. From the outside, a wrong password and a missing MX record produce the same user-visible failure; the logged server response tells them apart in seconds.
And one verification trick that beats any dashboard indicator: after a successful test send, list the mailbox's sent folder via the API. If the message is in Sent, the whole chain — Auth0, SMTP auth, outbound pipeline — worked.
curl --request GET \
--url "https://api.us.nylas.com/v3/grants/$GRANT_ID/messages?in=sent" \
--header "Authorization: Bearer $NYLAS_API_KEY"
Try the round trip
The full guide lives at send Auth0 emails with an Agent Account, with sibling recipes for Supabase and Clerk if your stack differs.
Concrete next step: provision a trial-subdomain mailbox, point a dev tenant's SMTP at it, trigger a password reset, and then — the fun part — reply to that email and watch it show up in the inbox via the API. That reply path is the whole reason to do this instead of another no-reply pipe.
Top comments (0)