DEV Community

Cover image for SPF, DKIM, DMARC: the 15-minute setup that actually passes
DevOps Daily
DevOps Daily

Posted on

SPF, DKIM, DMARC: the 15-minute setup that actually passes

Every guide to email authentication starts with a history lesson. Skip it. You are here because your emails land in spam, or a client asked "is DMARC set up?", or you saw dmarc=fail in a bounced message. Here is the 15-minute version: the exact records, why each one exists in one sentence, and how to verify you got it right.

The one-sentence versions

  • SPF lists which servers may send mail claiming to be from your domain.
  • DKIM cryptographically signs each message so receivers can verify it was not altered and really came from you.
  • DMARC tells receivers what to do when SPF or DKIM fail, and sends you reports about it.

SPF and DKIM are the mechanisms. DMARC is the policy on top. You need all three.

SPF: one TXT record

At your domain root (or the subdomain you send from), add a TXT record:

v=spf1 include:_spf.yourprovider.com ~all
Enter fullscreen mode Exit fullscreen mode

Replace the include with whatever your email provider documents. Sending through Amazon SES it is include:amazonses.com; Google Workspace is include:_spf.google.com. If you send through several providers, chain the includes in a single record:

v=spf1 include:amazonses.com include:_spf.google.com ~all
Enter fullscreen mode Exit fullscreen mode

Mistake #1: two SPF records. SPF allows exactly one TXT record starting with v=spf1 per domain. Two records means SPF returns a permanent error, which is worse than no record at all. Merge them.

Also know the 10-DNS-lookup limit: every include costs lookups, and past 10 the check fails. If you have collected includes from years of tools, prune them.

Verify it with dig:

dig +short TXT yourdomain.com | grep spf1
Enter fullscreen mode Exit fullscreen mode

or use a checker that also counts your lookups, like this free SPF checker.

DKIM: the CNAMEs your provider gives you

You do not write DKIM records by hand. Your provider generates a key pair, keeps the private key, and gives you DNS records (usually 1 to 3 CNAMEs) that publish the public key. They look like:

abc123._domainkey.yourdomain.com  CNAME  abc123.dkim.provider.com
Enter fullscreen mode Exit fullscreen mode

Add them exactly as given and wait for verification. That is it.

Mistake #2: proxying the DKIM CNAMEs. If your DNS is behind Cloudflare, those records must be DNS only (grey cloud). Proxied CNAMEs resolve to Cloudflare IPs and DKIM verification never completes. This one costs people days.

Verify with the selector your provider used:

dig +short TXT abc123._domainkey.yourdomain.com
Enter fullscreen mode Exit fullscreen mode

You should see a v=DKIM1; k=rsa; p=... blob. A DKIM checker does the same with the parsing done for you.

DMARC: start monitoring, then enforce

Add a TXT record at _dmarc.yourdomain.com:

v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com
Enter fullscreen mode Exit fullscreen mode

p=none means "change nothing, just send me aggregate reports about who is sending as my domain." Run in this mode for a couple of weeks and read the reports; you will usually discover a forgotten tool sending as your domain.

Then enforce:

v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@yourdomain.com; pct=100
Enter fullscreen mode Exit fullscreen mode

and eventually p=reject. Enforcement is what actually stops spoofing, and since 2024 Gmail and Yahoo require a DMARC record for bulk senders at all.

Mistake #3: jumping straight to p=reject. If some legitimate system sends unaligned mail (a CRM, a billing tool, an old cron job), p=reject silently kills those messages. Monitor first, enforce second.

Verify:

dig +short TXT _dmarc.yourdomain.com
Enter fullscreen mode Exit fullscreen mode

or decode the policy in plain English with a DMARC analyzer.

The 15-minute checklist

  1. One SPF record, correct include, ~all at the end. Check the lookup count.
  2. Add the provider's DKIM CNAMEs, unproxied. Confirm the selector resolves.
  3. _dmarc record at p=none with a rua address. Calendar reminder for two weeks: read reports, move to quarantine, then reject.
  4. Send a test email to a Gmail account, open "Show original", and confirm all three lines say PASS.

Step 4 is the ground truth. Gmail's "Show original" view shows spf=pass dkim=pass dmarc=pass right at the top, and it is checking the real thing rather than just the DNS.

Once these pass, deliverability problems stop being an authentication problem and start being a reputation problem. That is a different article, but you cannot get there without this one.

While speaking of emails, if you want to learn how SMTP works under the hood, watch a message move from application code to an SMTP relay, through TLS and AUTH, across DNS and recipient MX checks, and finally into a mailbox check out this simulator: SMTP Flow Simulator

Top comments (0)