SPF, DKIM and DMARC explained with a working DNS setup
SPF lists the servers allowed to send for your domain. DKIM signs each message so a receiver can verify it was not altered. DMARC ties both to the From address you show the world and tells receivers what to do on failure. Publish all three, start DMARC with a monitoring policy, then tighten only after the reports look clean.
SPF: one domain, one record, every sender
SPF is a TXT record on the domain. It lists which hosts may send for that domain. A domain can publish exactly one SPF record, so every provider you send through has to appear inside it, either as a host or as an include. Two SPF records on one domain is a permanent fail and one of the most common mistakes we see.
Keep the lookup count in mind. Each include costs a DNS lookup and there is a hard limit of ten. If a provider you no longer use is still listed, removing it is free capacity for one you do use.
DKIM: your provider signs, you publish the key
DKIM puts a signature header on each message using a private key held by the sending service. The matching public key lives in DNS at a selector the provider tells you, for example a TXT record at selector._domainkey.yourdomain.com. You do not generate the signature; you publish what the provider hands you.
If you send through more than one provider, each has its own selector, and all of them can coexist. A message that fails DKIM but passes SPF can still pass DMARC only if SPF aligned with the From domain, which is why alignment matters more than either check alone.
DMARC: policy, reports and the roll-out order
DMARC is a TXT record at _dmarc.yourdomain.com. It names the policy for failing messages, an address for aggregate reports, and how strictly the From domain must align. Start at p=none so nothing is blocked while you collect reports, read them, and fix whatever is sending without your knowledge.
When reports show only your real senders passing, move to p=quarantine, then to p=reject. Keep an allowance for subdomains you do not intend to use. A DMARC record is a promise about every stream on the domain, transactional mail included.
Common DNS mistakes that look correct
A record with the right syntax can still be wrong. Two SPF records on one domain is the classic: both look valid, together they fail. A DKIM selector published on the wrong host, such as the bare domain instead of selector._domainkey, is invisible until reports show signatures failing. A DMARC record at p=none that nobody reads is a monitoring policy that monitors nothing.
Another frequent problem is a CNAME colliding with a TXT record at the same name, which some resolvers handle inconsistently. Publish the record type the provider specifies, at the exact host it specifies, and check it with a public DNS lookup rather than assuming the panel saved it.
When something still fails, look at the raw headers of a real message you sent. The Authentication-Results header lists what the receiver checked and what it found. It is the closest thing to a straight answer you will get.
The three records at a glance
| Record | Where it lives | What it decides |
|---|---|---|
| SPF | TXT on the domain | Which hosts may send for the domain |
| DKIM | TXT at selector._domainkey | Whether the message was signed by your key |
| DMARC | TXT at _dmarc | What happens when SPF or DKIM does not align |
Policies are published, not enforced by any single provider. Each receiving system applies them in its own way.
Roll-out order that does not block your own mail
- Inventory every service that sends for the domain, transactional mail included
- Publish one SPF record that includes each active sender
- Publish every DKIM selector the providers issue
- Start DMARC at p=none with a reporting address you actually read
- Read reports for a few weeks and fix unknown senders
- Move to p=quarantine, confirm no legitimate mail is affected
- Move to p=reject only after quarantine is boring
A worked example with hypothetical records
Say a company sends cold email through one provider, invoices through another, and has a support desk that sends from a subdomain. A workable shape is one SPF record listing both providers, two DKIM selectors, and a DMARC policy at p=none with a reports address.
After a month, reports show the marketing provider passing and the invoice provider failing DKIM on a selector nobody had published. Publishing that selector fixes it, and only then does the policy move to quarantine. Doing it the other way round blocks invoices for a day and costs a morning of support.
- 1.Write down every sender, including the ones you forgot
- 2.Publish SPF, then DKIM per provider, then DMARC at p=none
- 3.Read reports weekly until failures have a name
- 4.Tighten the policy one step at a time
What this will not do
- Authentication does not decide inbox versus spam on its own; reputation and engagement still count.
- A DMARC record does not stop someone forging a similar-looking domain.
- Reports are summaries; they will not tell you whether a specific person wanted your email.
Questions people ask about this
Can I skip SPF if I have DKIM?
You can, but you lose the redundancy that makes DMARC resilient. With both, a broken signature does not automatically fail the message. Publish both and keep them accurate.
Why did adding a second SPF record break everything?
A domain may publish only one SPF record. Two records is a permanent error for receivers, so every message fails the SPF check regardless of content.
Should DMARC start at reject?
Not unless you already know every sender on the domain. Start at p=none, read reports, fix the gaps, then tighten. Reject on day one is how legitimate mail gets blocked.
Does DMARC affect subdomains?
Yes, by default. A policy on the organisational domain applies to subdomains unless you publish a stricter or looser record for them. Decide deliberately which subdomains may send.
What does Authentication-Results actually tell me?
It is the receiving server's own record of what it checked: whether SPF and DKIM passed, which domain and selector were used, and whether DMARC aligned. It answers what this receiver thought of my message better than any dashboard.