Skip to main content

How to Set Up SPF, DKIM and DMARC So Mail Actually Lands

7 min read
Fix my mail deliverability

We align all three records with your From domain and step DMARC up to p=reject safely.

Three DNS records decide whether your invoices reach the inbox or the spam folder, and most setups have all three and still fail. The reason is alignment: DMARC does not ask whether SPF passed, it asks whether the domain SPF authenticated matches the domain in the From header. This is the working order to set them up, why SPF alone breaks the moment a message is forwarded, the ten lookup limit that silently voids your record, and how to move from p=none to p=reject without losing a week of mail.

Most deliverability problems are not spam filters being unfair. They are three DNS records that exist, look right, and do not do what their owner thinks.

The three answer different questions. SPF says which servers may send for your domain. DKIM signs the message so a receiver can prove it was not altered. DMARC ties both back to the address your recipient actually sees, and tells receivers what to do when neither ties.

That last part is where working setups fail, so it is worth taking first.

Alignment is the whole game

DMARC does not ask "did SPF pass". It asks whether the domain that passed is the same domain as the one in the From: header, the only address the recipient ever sees.

A message passes DMARC when either of these holds:

  • SPF passed, and the domain it authenticated aligns with the From domain.
  • DKIM passed, and the d= domain in the signature aligns with the From domain.

The SPF check authenticates the envelope sender, the Return-Path, not the From header. Send through a marketing platform that uses its own bounce domain and SPF passes for that platform and aligns with nothing. The mail is authenticated and still fails DMARC.

This is why DKIM matters more than it looks. It is also why the fix for a failing platform is usually to sign with your own domain, not to add another include: to SPF.

SPF, and the limit that voids it

One TXT record at the apex, listing who may send.

v=spf1 include:_spf.example-provider.com ip4:203.0.113.10 -all

Two things to get right.

The ten lookup limit. SPF allows at most ten DNS-querying mechanisms while evaluating a record. Every include, a, mx, ptr, exists and redirect counts, and every include drags in whatever that provider's record expands to. Cross the limit and the result is a permanent error, which most receivers treat as no SPF at all. Four or five providers is enough to cross it without a single obvious mistake in your record.

Check the expansion, do not count the words in your own record.

-all or ~all. Hard fail says anything else is forged. Soft fail says treat it as suspicious. Start on ~all while you are still discovering who sends on your behalf, and move to -all once the reports are quiet. Leaving it on ~all forever is the common half-measure.

SPF also breaks on forwarding. A message forwarded by a mailing list arrives from the list's server, which is not in your record, and SPF fails through no fault of anyone. DKIM survives that trip, which is the second reason to sign.

DKIM

Your mail server signs outgoing messages with a private key. The public half goes in DNS under a selector you choose.

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

Use 2048-bit keys. Publish a second selector before you rotate, switch signing to it, and remove the old one a few days later, so no message is ever signed with a key that is not published.

Sign with your own domain wherever a provider allows it. Every platform that sends on your behalf, invoicing, marketing, ticketing, should sign as d=example.com. That single change fixes more alignment failures than any SPF edit.

DMARC, starting at none

_dmarc.example.com  TXT  "v=DMARC1; p=none; rua=mailto:dmarc@example.com; fo=1"

p=none changes nothing about delivery. It asks receivers to send you aggregate reports about what they saw. That is the point: you cannot safely enforce a policy over senders you have not enumerated, and almost nobody can list them correctly from memory. Invoicing, the CRM, a monitoring tool, a form on the website, an old server somebody set up in 2019.

Run it for two to four weeks and read the reports. They will show you sources you forgot.

Then tighten in two steps: p=quarantine, watch, then p=reject. Use pct= to ramp a percentage of mail into the new policy if the volume makes you nervous.

By default both alignment modes are relaxed, which means a subdomain aligns with its parent. aspf=s and adkim=s demand an exact match. Relaxed is the right default; strict is for people who know why they want it.

The order that works

  1. Publish SPF with ~all and check the expansion stays under ten lookups.
  2. Turn on DKIM signing everywhere, with your own domain in d=.
  3. Publish DMARC at p=none with rua.
  4. Read reports until nothing surprising appears.
  5. Move SPF to -all, DMARC to quarantine, then reject.

Skipping step 3 and going straight to p=reject is how a company discovers, on a Monday, that its invoices have been rejected since Friday.

If mail is currently landing in spam and you would rather have it diagnosed than described, that is part of our security and compliance work, and our free mail tools will check the three records for you first.

Frequently asked questions

Why does an email fail DMARC even though SPF passes?

SPF authenticates the envelope sender, the Return-Path, and DMARC asks whether that domain aligns with the domain in the From header. A marketing platform that uses its own bounce domain passes SPF for the platform and aligns with nothing, so the message is authenticated and still fails DMARC. The usual fix is to have the platform sign with DKIM using the sender's own domain in d=, instead of adding another include to SPF.

Does DMARC require both SPF and DKIM to pass?

No, one aligned pass is enough. A message passes DMARC when SPF passed and the domain it authenticated aligns with the From domain, or when DKIM passed and the d= domain in the signature aligns with the From domain. DKIM carries more of the weight in practice, because a DKIM signature survives forwarding where SPF breaks.

What happens when an SPF record needs more than 10 DNS lookups?

SPF evaluation returns a permanent error, which most receivers treat as no SPF at all. Every include, a, mx, ptr, exists and redirect counts toward the limit of ten, and each include also drags in whatever the provider's record expands to. Four or five providers can cross the limit without one obvious mistake, so check the full expansion, since counting the mechanisms in your own record misses what each include pulls in.

Should an SPF record end in -all or ~all?

Start with ~all, the soft fail that marks other senders as suspicious, while still discovering who sends on the domain's behalf. Move to -all, the hard fail that declares anything else forged, once the DMARC reports are quiet. Leaving ~all in place forever is a common half-measure.

Why does SPF fail when an email is forwarded?

A forwarded message, for example one sent on by a mailing list, arrives from the forwarder's server, and that server is not in the original domain's SPF record. SPF then fails through no fault of anyone. A DKIM signature survives the trip, which is a strong reason to sign outgoing mail with DKIM as well.

How do I rotate DKIM keys without breaking mail delivery?

Publish a second selector before rotating, switch signing to it, and remove the old selector a few days later. Following that order, no message is ever signed with a key that is not published. Use 2048-bit keys, with each public key published as a TXT record under its selector, such as selector1._domainkey.example.com.

How long should DMARC stay at p=none before moving to p=reject?

Run p=none with an rua reporting address for two to four weeks, and keep reading the aggregate reports until nothing surprising appears. The p=none policy changes nothing about delivery, but the reports reveal forgotten senders such as invoicing, the CRM, a monitoring tool or a form on the website. Then tighten to p=quarantine, watch, and move to p=reject, using pct= to ramp a percentage of mail if the volume is a concern.

What is the difference between relaxed and strict DMARC alignment?

Relaxed alignment, the default for both SPF and DKIM, lets a subdomain align with its parent domain. Strict alignment, set with aspf=s and adkim=s, demands an exact match. Relaxed is the right default for most senders, and strict is for those who know why they want it.

Read how we handle it in Cybersecurity.