Guides · Email

SPF, DKIM, And DMARC Explained

Three TXT-based standards that tell receivers whether email claiming to be from your domain should be trusted. Each does one job; together they decide whether you reach the inbox.

By Cody · 8 min read · Published

Why authentication exists

SMTP has no native sender check. Anyone can send a message claiming to be from your domain, and historically that was the spammer's playbook. SPF, DKIM, and DMARC are the three TXT records that, together, let receivers decide whether to trust mail claiming your domain on the visible From: line.

Major mailbox providers (Gmail, Yahoo, Microsoft) increasingly require all three for any domain that sends meaningful volume. Without them, even legitimate mail risks the spam folder.

SPF — who is allowed to send

An SPF record lists the IP addresses authorized to send mail using your domain in the envelope-from. A typical record looks like this:

example.com.  IN  TXT  "v=spf1 include:_spf.google.com ~all"

Mechanisms include ip4:, ip6:, a, mx, andinclude:. The trailing qualifier matters: -all says "reject everyone not listed," while ~all means "soft-fail." Use -all in production once you are confident in the list.

SPF has a hard limit of 10 DNS lookups. Each include: chain counts toward that total, and modern marketing stacks blow past it easily. Pitfall: SPF also breaks on forwarding, because the forwarding host is not in your record. DMARC alignment with DKIM is the fix.

DKIM — proving the message wasn't altered

DKIM signs selected headers (and usually the body) of each outbound message with a private key. The corresponding public key is published in DNS under a selector:

google._domainkey.example.com.  IN  TXT  "v=DKIM1; k=rsa; p=MIGfMA0GCSq...AB"

Receivers fetch the key, verify the signature, and on a match they know the message was sent by something holding the private key and was not modified in transit. Use 2048-bit keys; 1024 is no longer considered safe. Most providers manage selectors and key rotation for you.

DMARC — telling receivers what to do

DMARC ties SPF and DKIM together and tells receivers what to do when both fail. It is published at _dmarc.<domain>:

_dmarc.example.com.  IN  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@example.com; pct=100"

The p= tag is the policy: none (just monitor),quarantine (send to spam), or reject (refuse). The rua=tag is the address that receives daily aggregate reports. The pct= tag lets you apply the policy to a fraction of failing mail — useful when ramping fromquarantine to reject.

Alignment in plain English

DMARC does not just check that SPF and DKIM passed — it checks that they passed for the same domain that appears in the visible From: header. That is "alignment."

  • SPF alignment: the SMTP envelope-from domain matches (or is a subdomain of) the visible From: domain.
  • DKIM alignment: at least one valid DKIM signature uses a domain that matches the visible From: domain.

DMARC passes if at least one of these aligns. This is why DKIM tends to survive forwarding while SPF does not — the DKIM signature travels with the message.

Reading DMARC aggregate reports

Aggregate reports (RUA) arrive as gzipped XML files, one per receiver per day. They list every IP that sent as your domain, what passed, what failed alignment, and the volume. Free parsers exist; paid services produce nicer dashboards. The first time you read them, expect surprises: a marketing platform you forgot about, an old support tool, a forwarder.

A staged rollout that won't break your mail

The rollout that consistently works:

  1. Publish SPF and DKIM. Confirm legitimate mail is signing correctly.
  2. Publish DMARC at p=none with rua=. Read reports for 2-4 weeks.
  3. Fix every aligned-failure source until they pass.
  4. Move to p=quarantine; pct=10. Watch reports for a week.
  5. Ramp pct= upward, then move to p=quarantine; pct=100.
  6. Finally, move to p=reject.

Skipping the report-reading step is the only thing that breaks legitimate mail. Take the time.

A clean published trio

Example input
example.com (Google Workspace + Mailchimp)
Example result
# SPF — authorize Google + Mailchimp
example.com.            IN  TXT  "v=spf1 include:_spf.google.com include:servers.mcsv.net -all"

# DKIM — Google's published selector
google._domainkey.example.com.   IN  TXT  "v=DKIM1; k=rsa; p=MIGfMA0G..."

# DMARC — quarantine policy at 100%, reports flow to dmarc@
_dmarc.example.com.     IN  TXT  "v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarc@example.com"

SPF authorizes Google and Mailchimp by include. DKIM publishes Google's selector. DMARC is mid-rollout at p=quarantine — the next step would be p=reject after another reporting window.

Related tools

FAQ

Can I have more than one SPF record?

No. Per RFC 7208 a domain may publish only one SPF (v=spf1) record. Two records cause a permerror and SPF will be ignored. If you need to authorize multiple senders, combine them into one record using `include:` mechanisms.

What selector should I use for DKIM?

Selectors are arbitrary labels that let you publish multiple keys at once. Most providers pick the selector for you (Google uses `google`, Microsoft uses `selector1` and `selector2`). When you rotate keys, publish the new selector first, switch signing to it, then retire the old selector after a grace period.

Will p=reject break my marketing email?

Only if a marketing platform sends as your domain without DKIM signing or SPF authorization aligned to your visible From address. The right rollout order is p=none, read the aggregate reports, fix every legitimate sending source until they pass DMARC, then ramp p=quarantine and finally p=reject. Skipping the report-reading step is what causes outages.

Why does my SPF say permerror?

The two most common causes are a syntax error and exceeding the 10-DNS-lookup limit. Each `include:`, `a`, `mx`, `exists`, and `redirect` mechanism counts as one lookup, and any nested `include:` adds more. Use an SPF flattening tool or remove unused includes to stay under 10.

Does DMARC apply to subdomains automatically?

Yes — a DMARC record at `_dmarc.example.com` applies to subdomains unless you publish a separate `_dmarc.sub.example.com` record. Use the `sp=` tag to set a different policy specifically for subdomains while keeping the parent policy for the apex.

Last reviewed: 2026-05-06.