Out of the box, Supabase Auth sends confirmation, magic-link and password-reset emails through a shared service meant for testing. It only delivers to members of your Supabase team, and only about 2 messages an hour. The first real user who signs up won't get their email. The fix is custom SMTP, and Resend is a quick, developer-friendly option.
What you need
- A Resend account
- A domain you control, with DNS on Cloudflare (other DNS hosts work the same way)
- Your Supabase project
1. Pick a sending domain
Send from a subdomain, such as mail.example.com or auth.example.com, rather than your root domain. It keeps your sending reputation separate from your main domain's mail, and Supabase's own guidance recommends a separate domain for auth emails.
Watch out: the address you send from must be on the domain you verify. If you verify mail.example.com, send from no-reply@mail.example.com. Sending from no-reply@example.com fails with a "domain is not verified" error.
2. Add the domain in Resend
In Resend, go to Domains → Add domain and enter your sending domain. Resend shows the DNS records to add.
On Cloudflare, Resend's Sign in to Cloudflare button can add them for you. To add them by hand, open your zone's DNS → Records and create:
| Type | Name | Content | Notes |
|---|---|---|---|
| MX |
send (or send.mail for a subdomain) |
the feedback-smtp...amazonses.com value Resend shows |
Priority 10 |
| TXT |
send (or send.mail) |
v=spf1 include:amazonses.com ~all |
SPF |
| TXT |
resend._domainkey (or resend._domainkey.mail) |
the long p=... value Resend shows |
DKIM, DNS only |
Copy the exact names Resend gives you: for a subdomain they include it. In the Name field, enter only the part before your zone's domain; Cloudflare adds the rest.
Then click Verify in Resend. Records usually propagate in minutes.
Recommended: add a DMARC record too, for example a TXT record named _dmarc with v=DMARC1; p=none; to start, then tighten it once mail flows cleanly.
3. Create an API key
In Resend, go to API Keys → Create API key. For SMTP, a key with Sending access is enough. Copy it now; it's shown once.
4. Turn on custom SMTP in Supabase
In the Supabase dashboard, open Authentication → Emails → SMTP Settings and enable custom SMTP:
| Field | Value |
|---|---|
| Sender email |
no-reply@mail.example.com (on your verified domain) |
| Sender name | Your product name |
| Host | smtp.resend.com |
| Port |
587 (STARTTLS) or 465 (SSL) |
| Username | resend |
| Password | your Resend API key (re_...) |
Save. Supabase now sends to any address, starting with a limit of 30 emails an hour; raise it under Authentication → Rate Limits once you're sure the setup is right.
5. Send a test
Sign up with an address outside your team, or trigger a password reset. The email should arrive within seconds, and it shows up in Resend's Emails list with its delivery status. If it doesn't:
- "Domain is not verified": the sender address isn't on the verified domain (see step 1).
- Nothing in Resend's list: the SMTP details in Supabase are wrong; re-enter the password.
- Lands in spam: check SPF and DKIM pass in the message headers, and add DMARC.
6. Send your app's own emails
Invitations and notifications from your API can use the same SMTP details. In FastAPI with the standard library:
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["From"] = "no-reply@mail.example.com"
msg["To"] = "user@example.com"
msg["Subject"] = "You're invited"
msg.set_content("Join the team: https://example.com/invite/abc")
with smtplib.SMTP("smtp.resend.com", 587) as smtp:
smtp.starttls()
smtp.login("resend", RESEND_API_KEY)
smtp.send_message(msg)
Run it in a thread (run_in_threadpool) or a background task so a slow mail server doesn't block requests.
Using it with FastAPI Supabase Starter
Steps 1 to 5 are the same. For the app's own emails (organization invitations and templates from Admin › Messaging ), put the same values in .env:
SMTP_HOST=smtp.resend.com
SMTP_PORT=587
SMTP_USER=resend
SMTP_PASSWORD=re_xxx
EMAILS_FROM_EMAIL=no-reply@mail.example.com
Every message is recorded with its status in the delivery log under Admin › Messaging. More in Email, SMS and WhatsApp.
Top comments (0)