DEV Community

Qasim Muhammad
Qasim Muhammad

Posted on • Originally published at developer.nylas.com

Send Auth0 Authentication Emails From an Agent Account

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"
    }
  }'
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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.com keeps 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_password on 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"
Enter fullscreen mode Exit fullscreen mode

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)