Standards explained · · 18 min read

SPF, DKIM, DMARC: a working setup, explained line by line

Email authentication finally made clear. Why all three exist, how they interact, the 10-lookup SPF trap, how to roll out DMARC without breaking your mail, and what changed with Gmail/Yahoo's 2024 bulk-sender rules.

By The Toolsy team

Email authentication is one of those topics where every developer ends up reading a dozen blog posts and still feels they only half-understand it. Part of the problem is that the three standards — SPF, DKIM, and DMARC — were designed in different decades, layered on top of each other rather than designed as one system, and most explanations treat them in isolation when the whole point is how they work together.

This is a complete walkthrough: what each standard actually does, why all three exist, how to roll them out in production without breaking your mail, the misconfigurations that bite people, and what changed when Gmail and Yahoo made all three mandatory in 2024.

Why email authentication exists at all

SMTP, the protocol underlying email, was designed in 1982 when nobody worried about spoofing. The protocol itself has no built-in authentication: any server can connect to any other server and claim to be sending mail from any address. The receiving server has no way to verify that claim. This is fine in a small, trusted network of universities — it is catastrophic at internet scale.

By the early 2000s, spam, phishing, and email-based fraud were existential threats to email as a medium. SPF, DKIM, and DMARC are layered patches over SMTP that let receiving servers verify the message actually came from where it says it did.

If you're sending mail in 2026 and you haven't configured all three, your mail is increasingly going to spam — or failing entirely. Gmail and Yahoo's 2024 sender requirements made all three mandatory for any domain sending more than 5,000 messages per day to their users. Microsoft is heading the same direction. The era where you could ignore email authentication is over.

SPF: who is allowed to send mail as me?

SPF (Sender Policy Framework, RFC 7208) answers one question: "is this IP address allowed to send mail claiming to be from this domain?" You publish a TXT record at your domain root listing the authorized servers. Receiving servers check the TXT record against the connecting IP.

A typical SPF record looks like:

example.com.  TXT  "v=spf1 include:_spf.google.com include:mailgun.org ip4:198.51.100.0/24 ~all"

Reading left to right: this is an SPF v1 record. Authorized senders are anyone Google's SPF includes (so all of Google Workspace's outbound infrastructure), anyone Mailgun's SPF includes, and anything in the 198.51.100.0/24 IP block. Everything else "softfails" (the ~all at the end) — receivers should treat it as suspicious but not necessarily reject.

The mechanisms you'll see:

The 10-lookup limit: SPF's most common breakage

The single most common SPF problem in production is the 10-DNS-lookup limit. RFC 7208 caps the number of DNS queries an SPF check can require at 10 per evaluation. Each include:, a, mx, ptr, exists, and redirect= counts as one lookup. Recursive includes count too — if you include Salesforce's SPF, and their SPF includes five more domains, all five count.

Large email service providers eat lookups fast. Microsoft 365 takes 4-5 lookups. Salesforce Marketing Cloud takes 6+. Combine Microsoft 365, Salesforce, Mailchimp, and a transactional provider in one record and you're already over the limit.

When you exceed 10, receivers return "permerror" and treat your SPF as if it didn't exist. Mail goes to spam or gets refused. The fix is to "flatten" your SPF: resolve the includes ahead of time into literal IP addresses, and republish the record without the includes. You lose the convenience of automatic updates when your providers change their infrastructure, but you stay under the limit.

SPF's fundamental weakness

SPF checks the envelope sender — the address used in SMTP's MAIL FROM command. This is often different from the display From the user sees in their mail client. Email forwarding routinely changes the envelope sender (mailing lists, vacation auto-forwards, corporate mail gateways) — SPF can pass for the new envelope sender while the display From still claims to be your domain.

This is fixable with DMARC (covered below), which checks "alignment" between SPF's envelope and the display From. Without DMARC, SPF alone doesn't actually stop spoofing of what the recipient sees.

DKIM: was this message actually sent by me, unchanged?

DKIM (DomainKeys Identified Mail, RFC 6376) answers a different question: not "is this IP authorized" but "is this message cryptographically signed by the claimed sender, and has it been tampered with in transit?" Your mail server signs outgoing messages with a private key; the public key is published as a DNS TXT record. Receivers fetch the key, verify the signature, and confirm the message body and key headers haven't been modified.

The signature is added as a DKIM-Signature header:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;
  d=example.com; s=mail; t=1715600000;
  h=From:To:Subject:Date:Message-ID;
  bh=base64-encoded-body-hash;
  b=base64-encoded-signature

Reading the key fields:

Selectors and key rotation

The s= selector lets you publish multiple keys at once and roll them over without interruption. The DNS query for "give me the public key for this DKIM signature" is <selector>._domainkey.<domain>. So a domain can have k1._domainkey.example.com with one key and k2._domainkey.example.com with another, used by different senders or rotated over time.

Common selectors in the wild: Google Workspace uses google; Microsoft 365 uses selector1 and selector2 (auto-rotating pair); Mailchimp uses k1, k2, k3; ProtonMail uses protonmail1/2/3. Custom domains using Gmail SMTP may need to look up the specific selector from their provider's docs.

The reason selectors exist: rotate your DKIM keys periodically. Publish a new key under a new selector, switch your mail server to sign with it, wait for receivers to catch up, then retire the old selector. Annual rotation is reasonable. If a private key is compromised, you can revoke a selector immediately by publishing an empty p= for it (more on this below).

DKIM key revocation

To revoke a DKIM selector without deleting the TXT record entirely, set the p= field to an empty string:

oldkey._domainkey.example.com.  TXT  "v=DKIM1; k=rsa; p="

Receivers interpret this as "this selector is explicitly revoked" — signatures using this selector are rejected. This is different from the record being absent (which is treated as "we don't know" and may pass anyway depending on configuration).

What DKIM doesn't protect

The signature covers what's in the h= list and the body. Headers not in h= can be added or modified — including, importantly, additional From headers (some receivers accept the first one, some the last, creating header-injection opportunities). The signing list should always include at least: From, To, Subject, Date, Message-ID, MIME-Version, Content-Type.

DKIM also doesn't say anything about which servers are authorized to send. A spammer with their own infrastructure can DKIM-sign messages from spam-domain.com perfectly validly — they own that domain. The question DKIM answers is "is this domain's signature on the message", not "is this domain reputable".

DMARC: what should receivers do when SPF/DKIM fail?

DMARC (Domain-based Message Authentication, Reporting, and Conformance, RFC 7489) is the layer on top of SPF and DKIM that adds two things: a policy declaration ("if SPF and DKIM both fail, here's what receivers should do") and a reporting system ("send me aggregate reports about who's sending mail claiming to be from my domain").

The record lives at _dmarc.<your-domain> and looks like:

_dmarc.example.com.  TXT  "v=DMARC1; p=reject; rua=mailto:dmarc@example.com; ruf=mailto:forensic@example.com; pct=100; adkim=s; aspf=s"

The tags you'll use:

Alignment: the concept that ties everything together

The piece that's confusing in DMARC explanations is "alignment". DMARC doesn't just ask "did SPF pass" — it asks "did SPF pass and is the SPF domain aligned with the From header domain?"

Example: an email shows From: alice@example.com in the user's mail client. SPF was checked against the envelope sender bounce@mail.example.com and passed. Alignment means: does mail.example.com match example.com closely enough?

DKIM alignment works the same way: the d= in the DKIM signature compared to the From domain.

DMARC passes if EITHER SPF passes with alignment OR DKIM passes with alignment. Both don't need to succeed. This is intentional: forwarding routinely breaks SPF alignment (the envelope sender becomes the forwarder's address) while leaving DKIM alignment intact, and you want forwarded mail to still authenticate.

The DMARC rollout playbook

Going from no DMARC to p=reject in one step is how you accidentally block your own legitimate mail. The conventional rollout takes 2-3 months for an active domain:

  1. Week 1-2: Publish p=none with rua=. Don't change anything else. Receive aggregate reports. Read them. You will discover legitimate sending sources you didn't know about — the marketing team's tool, an old contract sender, a developer's test SMTP.
  2. Week 3-6: Fix sources that fail alignment. Either get them under SPF, get them signing with DKIM under your domain, or stop them from sending as you.
  3. Week 7-8: Move to p=quarantine; pct=10. Watch the rua reports for spike in failures. If everything looks clean, ramp pct to 25, 50, 75, 100 over a couple of weeks.
  4. Week 9-12: Move to p=reject; pct=10, ramp the same way. Final destination: p=reject; pct=100.

If you skip the monitoring period (p=none) and go straight to enforcement, you will block legitimate mail. The reports are the whole point.

Reading aggregate (rua) reports

Receivers send XML reports daily, one per receiving domain. The raw XML is unreadable; use a tool like Dmarcian or Postmark's DMARC tool to parse them visually. The free tiers cover most small-to-medium senders.

What you're looking for in the reports:

What changed in 2024

Gmail and Yahoo's bulk-sender rules, effective February 2024, made all three mandatory for senders shipping more than 5,000 messages per day to their users. The specifics:

"Bulk senders" effectively means any company doing transactional or marketing email at scale. If you're a small product without a marketing list, you might be under the 5,000/day threshold — but you should still configure all three, because you'll cross the threshold someday and reputation built on a properly-authenticated domain compounds.

How to test your setup

Tools that help, in order of usefulness:

If all three pass, you're set up correctly. If any fail, the headers will tell you which check failed and usually why.

Closing thought

Email authentication has more moving parts than its component pieces suggest, but the actual work of setting up SPF, DKIM, and DMARC for a domain is a few hours, including the rollout monitoring period. Most "I tried to set this up and it broke things" stories trace back to skipping the p=none phase, exceeding the SPF 10-lookup limit, or missing one of the senders that was using your domain.

Get all three configured. Read the aggregate reports for two weeks. Ramp to p=reject. Your deliverability will improve significantly, your spam folder ratio will drop, and you'll be ready for whatever the next round of sender requirements brings.

Found this useful? Share it with a developer who'd want to read it. Have a topic to suggest? Email hello@toolsy.website.

← More posts