1. Courses
  2. AI Engineering
  3. Run and Grow Your Site
  4. Stop 2

25 minBeginner

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

  • : a TXT record that lists which servers may send mail for your domain.
  • : a signature on every message. The public key sits in a TXT record, so the inbox can check nobody changed the mail.
  • : a TXT record at _dmarc that 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.

Resend mail Gmail checks looks up Cloudflare DNS SPF allowed senders DKIM public key for the seal DMARC what to do on failure pass Inbox fail Spam or reject
The inbox reads three records from your DNS. When SPF or DKIM passes and lines up with the From domain, DMARC passes and the mail goes to the inbox. When they fail, your DMARC policy decides what happens.

Quick check

Which record lets an inbox confirm that nobody changed the message on the way?

Verifying your domain in 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=spf1 on the same name make SPF fail. Merge them into one.
  • Start DMARC gently. Begin with p=none and a report address. After a few weeks of clean reports, move to p=quarantine.

Quick check

Resend says "verified", but you haven't added a _dmarc record yet. What does that mean?

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 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:

Output
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 it

Resend only sends. To receive mail at hello@, use : 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.

Supabase Auth Your site Resend SMTP API Member inbox reply to hello@ Cloudflare Email Routing Owner's inbox
Outgoing mail always leaves through Resend, by SMTP from Supabase or by API from the site. Incoming mail to hello@ arrives through Cloudflare Email Routing, which forwards it to an inbox the owner already reads.

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?

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.

  1. 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.

  2. 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.

    Output
    Type  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.example

    Back in Resend, click Verify. It can take a few minutes.

  3. 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.

  4. 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", host smtp.resend.com, port 465, username resend, password a second Resend API key. Supabase then applies its own e-mail rate limit, which you can raise in its rate limit settings.

  5. 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.

  6. Ask the agent to use the right senders

    Markdown
    Add 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.
  7. Check a real message

    Sign in with a Gmail address, open the sign-in mail, choose Show original and look for three passes:

    Output
    SPF:   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
Output
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 lines

Check 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?

After four weeks of DMARC reports showing only your own Resend mail passing, what is a sensible next step?

A member replies to the weekly offers e-mail, and the reply bounces. Sending works fine. What is missing?

Flashcards

Open my review

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

Episode transcriptWax seals for your sign-in links · about 8 minutes · tap any line to play from there
  1. NadiaImran, remember launch evening for Mangrove Kitchen?
  2. ImranI remember Leila messaging me that she'd tapped sign in three times and no e-mail ever came. And two members found their links in spam.
  3. NadiaTwo separate problems, and both fixed in about half an hour. Today is e-mail that actually arrives. Sending from your own domain through a service called Resend, with three DNS records that keep you out of spam.
  4. ImranThe three acronyms. SPF, DKIM and DMARC. I always mix them up.
  5. NadiaThen let's use a picture. Anyone can write your shop's name as the return address on an envelope. So a careful post office checks three things.
  6. NadiaFirst, did this letter come from a post office you listed as yours? Second, does it carry your wax seal, unbroken? Third, what did you ask them to do with letters that fail, and should they send you a report?
  7. ImranSo the list of post offices is SPF.
  8. NadiaYes. SPF is a TXT record listing the servers allowed to send mail for your domain. DKIM is the wax seal: a signature on every message, checked with a public key you publish in DNS, so the inbox knows nobody changed it on the way.
  9. ImranAnd DMARC is the instruction about failures.
  10. NadiaRight. It's one more TXT record, on a special DMARC name. It says do nothing, send to spam, or reject, and where to send the reports.
  11. NadiaIf you can see the first diagram, Resend sends the mail at the top, Gmail receives it and looks up three records in your Cloudflare DNS. When the checks pass, it goes to the inbox. When they fail, your DMARC policy decides.
  12. ImranDo small sites really need all three? We're sending a few hundred e-mails, not millions.
  13. NadiaSince twenty twenty-four, Gmail and Yahoo require large senders to pass all three, offer one-click unsubscribe on marketing mail, and keep spam complaints low. Small senders need at least SPF or DKIM. Setting up all three on day one costs ten minutes, and then you never think about it again.
  14. ImranFine. How do I get them?
  15. NadiaYou add your domain in Resend, and it shows you the records. An MX record and an SPF record on a send subdomain, which Resend uses for bounces. And a DKIM record at a name starting with resend. Because they sit on subdomains, your main domain's records aren't touched.
  16. ImranSo I copy them into Cloudflare like last lesson.
  17. NadiaExactly like last lesson, and mail records have no proxy setting, so no cloud to worry about. Two rules, though. Only one SPF record per name. Two SPF records on the same name make SPF fail, so merge them into one.
  18. ImranAnd the second rule?
  19. NadiaStart DMARC gently. Begin with the policy none and a report address. After a few weeks of clean reports, move to quarantine, which sends failing mail to spam.
  20. ImranWhy not go straight to reject? Stop the fakes on day one.
  21. NadiaBecause you might have a sender you forgot about, and reject would block your own mail. The reports tell you who sends as you. Read them first, then tighten.
  22. ImranNow Leila's missing link. That wasn't spam.
  23. NadiaNo. Supabase's built-in mailer allows only a few e-mails an hour. It's meant for testing. On launch evening it hit its limit. The fix is custom SMTP: Supabase hands each sign-in mail to Resend instead.
  24. ImranSMTP is the old mail protocol?
  25. NadiaThe standard way one mail server hands a message to another. In Supabase's authentication settings, you turn on custom SMTP and fill in four things. Host smtp dot resend dot com. Port four six five. Username, the word resend. And the password is a Resend API key.
  26. ImranAn API key as a password. So that goes into Supabase's settings box directly, never into a chat with the agent.
  27. NadiaYes. And the other key, the one the site uses to send the weekly offers e-mail, goes into Vercel as an environment variable. Give both keys sending access only.
  28. NadiaThe second diagram shows all the mail paths. Supabase sends sign-in mail by SMTP, and your site sends offers and reports by API. Both go out through Resend to the member's inbox.
  29. ImranAnd replies? If a member answers the offers e-mail?
  30. NadiaGood catch. Resend only sends. To receive mail at hello at your domain, use Cloudflare Email Routing. It's free and forwards hello to an inbox you already read. That's the bottom of the diagram.
  31. ImranYou said hello. What about the other addresses?
  32. NadiaGive each purpose its own sender. No-reply for sign-in links, offers for the weekly e-mail, reports for the owner's report. All with a reply-to of hello, which a person reads. People know what to expect, and a problem with one kind of mail doesn't drag down the others. Kolom sends its own mail exactly this way.
  33. ImranSo in our story, what did the fix look like?
  34. NadiaWe added the domain in Resend, copied three records into Cloudflare, and added the DMARC record with policy none. Resend verified it in about fifteen minutes. Then custom SMTP in Supabase, with the no-reply sender. Leila's next link arrived in seconds.
  35. ImranAnd how did we know it was really fixed, not just lucky?
  36. NadiaWe opened the mail in Gmail, chose Show original, and read three lines. SPF pass, DKIM pass, DMARC pass. That's your proof.
  37. ImranGive me the Do it steps in order.
  38. NadiaSign up for Resend with the owner address and turn on two-factor. Add your domain. Copy each record into Cloudflare exactly, then add DMARC, and click Verify. Create a sending-only key and paste it into Vercel, then redeploy.
  39. NadiaTurn on custom SMTP in Supabase with a second key. Set up Email Routing for hello. Ask the agent to add a small server-only module for sending, with the right senders and an unsubscribe link in every weekly e-mail. Then check a real message's headers.
  40. ImranMy questions before the first weekly e-mail goes out. Does a test message show three passes? Is there exactly one SPF record per name? Where do the keys live, and do they have sending access only? Who reads hello, and has someone tested a reply?
  41. NadiaAnd does every weekly e-mail have a working unsubscribe link? Without it, people press the spam button instead, and that hurts every mail you send.
  42. NadiaOne to think about. Resend says your domain is verified, but you never added a DMARC record. Is that fine? Take a second.
  43. ImranMail will send, but inboxes won't know my policy, and I get no reports.
  44. NadiaExactly. Resend checks its own records. DMARC is yours to publish, and a policy of none costs nothing.
  45. ImranMy summary. One, inboxes check SPF for who may send, DKIM for the seal, and DMARC for the policy. Two, copy Resend's records into Cloudflare exactly, keep one SPF per name, and start DMARC at none. Three, send sign-in mail through Resend with custom SMTP, because the built-in mailer is for testing.
  46. NadiaAnd receiving is separate. Email Routing forwards hello to a real inbox.
  47. ImranNext time, numbers. Who visits, how Google finds us, and why the first week of search looks like zero.
  48. NadiaAnalytics, Search Console and a sitemap. See you there.
Finished reading?Mark it complete to fill in its stop on your course line.

Use it at work

Runbook

Symptoms, first checks with commands, fixes and when to escalate, for one alert.

Open in the DevOps & TechOps Lab
Next stopAnalytics, Search Console and your sitemap
Was this lesson helpful?
Questions and discussion

Loading the discussion…