E-mail that arrives: Resend, SPF, DKIM and DMARC
Sign-in links, the weekly offers e-mail and your own reports are only useful if they reach the inbox. This lesson sends Mangrove Kitchen's mail from its own domain through Resend, with the three DNS checks that keep it out of spam.
By the end you can
- Explain SPF, DKIM and DMARC in plain words
- Verify your domain in Resend by copying its records into Cloudflare
- Send Supabase sign-in mails through Resend with custom SMTP
- Choose sender addresses per purpose and receive replies at hello@
- Check a real message's headers for three passes
The everyday picture
Anyone can write your shop's name on an envelope as the return address. So a careful post office checks three things. Did this letter come from a post office you listed as yours? Does it carry your wax seal, unbroken? And what did you ask them to do with letters that fail, plus send you a report?
Those are SPF, DKIM and DMARC. Inbox providers such as Gmail and Outlook run all three checks on every message.
Three checks every inbox runs
- SPF: a TXT record that lists which servers may send mail for your domain.
- DKIM: a signature on every message. The public key sits in a TXT record, so the inbox can check nobody changed the mail.
- DMARC: a TXT record at
_dmarcthat says what to do with mail that fails (nothing, spam folder, or reject) and where to send reports.
Since 2024, Gmail and Yahoo require large senders to pass all three, offer a one-click unsubscribe on marketing mail and keep spam complaints low. Small senders need at least SPF or DKIM. Set up all three from day one and you won't have to think about it again.
Quick check
Which record lets an inbox confirm that nobody changed the message on the way?
DKIM signs each message, and the public key in DNS proves the signature. SPF only checks which server sent it, and DMARC sets the policy built on the other two.
Verifying your domain in Resend
Resend sends mail for your site. When you add your domain, it shows the records to copy: an MX and an SPF TXT on a send subdomain (used for bounces), and a DKIM TXT at resend._domainkey. Because they sit on subdomains, your main domain's records stay untouched. Kolom sends its mail the same way.
Two rules save hours:
- Only one SPF record per name. Two TXT records starting
v=spf1on the same name make SPF fail. Merge them into one. - Start DMARC gently. Begin with
p=noneand a report address. After a few weeks of clean reports, move top=quarantine.
Quick check
Resend says "verified", but you haven't added a _dmarc record yet. What does that mean?
Resend checks its own SPF and DKIM records. DMARC is your policy, published by you, and large inboxes expect it. A p=none record costs nothing and starts the reports.
Sign-in mails, senders and replies
Supabase's built-in mailer allows only a few e-mails an hour, meant for testing. For real visitors, turn on custom SMTP in Supabase and point it at Resend: host smtp.resend.com, port 465, username resend, and a Resend API key as the password.
Give each purpose its own sender, so people know what to expect and a problem with one kind of mail doesn't hurt the others:
Purpose From Sent by
Sign-in links no-reply@mangrovekitchen.example Supabase (SMTP)
Weekly offers e-mail offers@mangrovekitchen.example the site (API)
Owner reports reports@mangrovekitchen.example the site (API)
Reply-to on all hello@mangrovekitchen.example a person reads itResend only sends. To receive mail at hello@, use Cloudflare Email Routing: it forwards hello@ to the owner's existing inbox for free. It adds MX and SPF records on the main domain, separate from Resend's.
Quick check
On launch evening, 40 people sign up within an hour and most never get their sign-in link. Custom SMTP is off. What is the likely cause?
The built-in mailer is meant for testing and allows only a few mails an hour. Custom SMTP through Resend removes that bottleneck. Email Routing only handles incoming mail.
Do it
Send your site's mail from your own domain. Menus move, so look for the named setting if a button has a new place.
Add the domain in Resend
Sign up with the owner address and turn on two-factor sign-in. Open Domains, add your domain and choose a region close to your visitors.
Copy the records into Cloudflare
In Cloudflare, open DNS, then Records, and add each record exactly as Resend shows it (type, name, value, MX priority). Then add DMARC. Mail records have no proxy setting.
OutputType Name Content (copy yours from Resend) MX send feedback-smtp.....amazonses.com (priority 10) TXT send v=spf1 include:amazonses.com ~all TXT resend._domainkey p=MIGfMA0GCSqGSIb3...(long key) TXT _dmarc v=DMARC1; p=none; rua=mailto:dmarc@mangrovekitchen.exampleBack in Resend, click Verify. It can take a few minutes.
Make a sending key and store it in Vercel
In Resend, create an API key with sending access only. Copy it straight into Vercel as
RESEND_API_KEY(Production and Preview) and redeploy. Never paste it into the agent's chat or a file in the repository.Turn on custom SMTP in Supabase
In Supabase, open Authentication and find the SMTP settings. Turn on custom SMTP and fill in: sender
no-reply@your domain, sender name "Mangrove Kitchen", hostsmtp.resend.com, port465, usernameresend, password a second Resend API key. Supabase then applies its own e-mail rate limit, which you can raise in its rate limit settings.Forward hello@ to your inbox
In Cloudflare, open Email, then Email Routing. Add the owner's inbox as a destination (it gets a confirmation mail), create
hello@and let Cloudflare add its records.Ask the agent to use the right senders
MarkdownAdd a small module for sending e-mail with Resend, used only on the server. Read the key from RESEND_API_KEY; never expose it to the browser. Senders: offers@ for the weekly e-mail, reports@ for owner reports, both with reply-to hello@mangrovekitchen.example. Every weekly e-mail needs an unsubscribe link. Show me the changed files before you commit.Check a real message
Sign in with a Gmail address, open the sign-in mail, choose Show original and look for three passes:
OutputSPF: PASS with IP 54.240.x.x DKIM: 'PASS' with domain mangrovekitchen.example DMARC: 'PASS'
Bring it to your team
Ask these before the first weekly e-mail goes out.
- Does a test message show SPF, DKIM and DMARC as pass?
- Is there exactly one SPF record on each name?
- Where do the Resend keys live, and do they have sending access only?
- Who reads hello@, and has someone sent it a test reply?
- Does every weekly e-mail have a working unsubscribe link?
Red flags
- Sign-in mails still go through the built-in mailer after launch.
- A Resend key with full access sits in a chat, a screenshot or the repository.
- DMARC reports go to an address nobody can open.
Practice
Plan your mail setup
For your own site (or Mangrove Kitchen), write a one-screen mail plan: the records Resend asks for, your DMARC record, the sender address for each kind of mail, where replies go, and where each key is stored.
- It lists the MX, SPF and DKIM records on the right names and a DMARC record at _dmarc starting with p=none
- It keeps one SPF record per name
- Each kind of mail has its own sender, with a reply-to a person reads
- Keys live in Vercel and Supabase settings only, with sending access
- It says how you will check the headers of a real message
Show a model answer
Records (from Resend): MX send, TXT send (SPF), TXT resend._domainkey
DMARC: TXT _dmarc v=DMARC1; p=none; rua=mailto:dmarc@my-domain
review reports after 4 weeks, then p=quarantine
SPF: main domain has one record (from Email Routing); send has one
Senders: no-reply@ sign-in (Supabase SMTP), offers@ weekly,
reports@ owner report; reply-to hello@ on all
hello@ forwards to the owner inbox (Cloudflare Email Routing)
Keys: RESEND_API_KEY in Vercel (sending access); a second key as the
SMTP password in Supabase; neither in chat or the repository
Check: Gmail "Show original" shows three PASS linesCheck yourself
Your main domain already has an SPF record from Cloudflare Email Routing. The agent suggests adding a second v=spf1 TXT record on the same name for another tool. What should you do?
A name may have only one SPF record; two cause a permanent error. Merge the includes into one line. Deleting Email Routing's would break incoming mail, and _dmarc is for DMARC only.
After four weeks of DMARC reports showing only your own Resend mail passing, what is a sensible next step?
Clean reports show that your real senders pass, so a stricter policy now only affects fakes. Going straight to reject before reading reports risks blocking your own mail.
A member replies to the weekly offers e-mail, and the reply bounces. Sending works fine. What is missing?
Resend only sends. Replies need an inbox, which Email Routing provides by forwarding hello@. The other settings only affect sending.
Flashcards
Key takeaways
- Inboxes check SPF (who may send), DKIM (the signature) and DMARC (the policy); set up all three.
- Verify your domain in Resend by copying its records into Cloudflare exactly; keep one SPF record per name and start DMARC at p=none.
- Send Supabase sign-in mail through Resend with custom SMTP; the built-in mailer is for testing.
- Use a sender per purpose, a reply-to a person reads, and Cloudflare Email Routing to receive mail.
Sources and further reading
- Managing domains, Resend docs
- Send emails with Supabase SMTP, Resend docs
- Send emails with custom SMTP, Supabase docs
- Email sender guidelines, Google
- Email Routing, Cloudflare docs