SPF, DKIM and DMARC Explained: How to Stop Email Spoofing
Email was built without any check on who a message is really from. Anyone can put your address in the From line, and without the right DNS records a receiving server can't tell a fake invoice from a real one. Three records fix this. SPF lists the servers allowed to send for your domain, DKIM adds a signature to each message, and DMARC tells receivers what to do when a message fails and sends you reports about it. Here is how each works, with records you can adapt and a rollout order that won't block your own mail.
The examples use example.com and the documentation address 203.0.113.10.
SPF: which servers may send for you
SPF (Sender Policy Framework, RFC 7208) is a TXT record on your domain listing the servers allowed to send its mail. A domain that uses Google Workspace and also sends from its own web server might publish:
v=spf1 include:_spf.google.com ip4:203.0.113.10 ~all
Receivers read it left to right. include: pulls in another domain's SPF list, ip4: and ip6: name addresses or ranges, and a and mx mean "the servers this domain's A or MX records point to". The last term says what to do with everything else:
| Ending | Result | What receivers take from it |
|---|---|---|
-all | Fail | Not authorised; the message may be rejected |
~all | Soft fail | Probably not authorised; usually accepted but treated as suspicious |
?all | Neutral | No opinion, so no protection |
+all | Pass | Anyone may send as you; never use it |
Three rules catch people out. A domain may have only one SPF record; two records make SPF fail with a permanent error. Checking SPF may take at most 10 DNS lookups: every include, a, mx, ptr, exists and redirect counts, including those nested inside the includes, and going over is another permanent error. And SPF checks the envelope sender (the bounce address, often shown as Return-Path), not the From address people see. A newsletter service can pass SPF for its own bounce domain while showing your address in From. That gap is why DMARC exists.
DKIM: a signature on every message
With DKIM (RFC 6376) the sending server signs each message with a private key. The signature travels in a DKIM-Signature header, where d= names the signing domain and s= the selector. The receiver fetches the public key from selector._domainkey.domain, for example s1._domainkey.example.com, and checks that the signed parts of the message haven't changed on the way.
The DNS record looks like v=DKIM1; k=rsa; p=MIIBIjANBg..., where p= holds the public key; an empty p= means the key has been revoked. Use 2048-bit RSA keys: RFC 8301 makes 1024 bits the minimum and recommends 2048. Selectors let you run several keys at once, one per service, and change keys without downtime.
Microsoft 365 and Google Workspace create keys for you in their admin centres (Microsoft uses the selectors selector1 and selector2; Google's default is google). Newsletter, CRM and helpdesk services usually give you DKIM records to publish. You only make keys yourself for your own mail server.
DMARC: the policy that ties them together
DMARC is a TXT record at _dmarc.example.com. A message passes DMARC when SPF or DKIM passes and the domain that passed matches the From domain. This matching is called alignment. Relaxed alignment, the default, accepts the same organisational domain, so mail.example.com aligns with example.com; strict alignment needs an exact match.
Back to the newsletter. SPF passes for the service's bounce domain, which doesn't align. But if the service signs with d=example.com, DKIM aligns and the message passes DMARC. That is why DKIM matters most for third-party senders.
The p= tag sets the policy: none (monitor only), quarantine (treat as suspicious, usually the spam folder) or reject. The rua= tag says where receivers send aggregate reports: XML summaries, usually daily, of who sent mail using your domain and whether it passed. A first record is often:
v=DMARC1; p=none; rua=mailto:[email protected]
DMARC was updated in May 2026. RFC 9989 replaced RFC 7489 and changed a few practical things. The pct tag, which applied the policy to a percentage of mail, is gone, and a test flag, t=y, takes its place: receivers apply one step softer than your policy, so p=reject is treated as quarantine and p=quarantine as none. A new np= tag covers subdomains that don't exist, a favourite of spoofers. And receivers now find your policy by walking up the DNS tree instead of relying on a public list of domain suffixes.
What the big mailbox providers expect
Since February 2024, Gmail and Yahoo have required bulk senders to authenticate their mail. Gmail counts you as a bulk sender at more than 5,000 messages a day to Gmail addresses. Yahoo's sender requirements spell out the details: every sender needs at least SPF or DKIM, and bulk senders need both, a DMARC record of at least p=none, a From domain aligned with SPF or DKIM, and one-click unsubscribe. Even if you never send in bulk, meeting those rules is the simplest way to keep out of spam folders.
A safe order to set it up
- List everything that sends as your domain: your mailbox provider, website forms, invoicing, CRM, helpdesk, newsletters, and scanners or printers that email.
- Publish one SPF record covering them all, ending in
~all. - Turn on DKIM for each service, using the records it gives you.
- Publish DMARC with
p=noneand a report address, then read the reports for two to four weeks. Anything legitimate that fails needs fixing at step 2 or 3. - Move to
p=quarantine, thenp=reject. To soften the last step, publishp=reject; t=yfirst, which asks receivers to quarantine instead while you watch the reports. - Once nothing legitimate fails, change SPF to
-all.
A domain that never sends email should say so, with v=spf1 -all and v=DMARC1; p=reject.
How to do it with SAA Tool
- Open the SPF Record Generator, enter Your domain, tick each service under Email services that send as you, add any other server IPs, choose Soft fail (~all) and click Copy. Publish it as a TXT record at
@, replacing any old SPF record. - For your own mail server, open the DKIM Record Generator, set the Selector, keep RSA 2048-bit (recommended) and click Create key pair. Click Copy for the DNS record value to publish at
selector._domainkey, then Download private key (.pem) and install it on the server. The key pair is made in your browser and never sent to us. - Open the DMARC Generator, choose Monitor only (none) as the Policy, enter an address under Send daily reports to (rua) and click Copy. Publish it as a TXT record named
_dmarc. The generator follows RFC 9989, so it offers Test mode (t=y) rather than pct. - Once the change is live, enter the domain in the TXT Record Checker and click Look up. It labels each record and flags duplicate SPF records or a DMARC record in the wrong place.
- Run the SPF, DKIM & DMARC Checker: enter the domain, add your DKIM selector if you know it, and click Check. It counts SPF lookups the way receivers do, nested includes too, and lists what to fix. Without a selector it tries 11 common ones.
- Check where your mail is delivered with the MX Record Checker. It names the email provider and spots MX records that point to an IP address or a CNAME.
The checkers read public DNS through Cloudflare's resolver, so they see what receivers see. After a change, an old record can linger until its TTL runs out; DNS records explained covers why.
Common mistakes
- Two SPF records after adding a new service. Merge them into one.
- Too many includes. Remove services you no longer use; the limit of 10 counts nested lookups.
- Leaving DMARC at
p=nonefor years. It only reports; fake mail is still delivered. - Jumping straight to
p=rejectwithout reading reports, and blocking your own invoices or website forms. - Putting the DMARC record on the domain itself instead of at
_dmarc. - Publishing the DKIM private key. Only the public key goes in DNS.
- Sending reports to another domain that hasn't agreed to take them. It must publish a record at
example.com._report._dmarc.theirdomain; report services usually do this for you.
Sources
- RFC Editor: RFC 7208, Sender Policy Framework (SPF)
- RFC Editor: RFC 6376, DomainKeys Identified Mail (DKIM) Signatures
- RFC Editor: RFC 8301, Cryptographic Algorithm and Key Usage Update to DKIM
- RFC Editor: RFC 9989, Domain-Based Message Authentication, Reporting, and Conformance (DMARC)
- Yahoo Sender Hub: Sender Best Practices
- Google: New Gmail protections for a safer, less spammy inbox
Spotted a mistake or something out of date? Tell us and we'll fix it.