SPF, DKIM, and DMARC are three DNS records that let a receiving server check that mail claiming to be from your domain really is. SPF lists the servers allowed to send for your domain. DKIM adds a cryptographic signature that proves the message came from your domain and wasn't changed. DMARC checks that at least one of them passed for the domain in the From address, tells the receiver what to do if not, and sends you reports.
SPF: which servers may send
SPF is a TXT record on your domain:
v=spf1 include:amazonses.com include:_spf.google.com ~all
Each include pulls in another provider's list of sending servers. The ending decides what happens to everything else. Per RFC 7208, ~all is a soft fail (treat with suspicion) and -all is a hard fail.
Two things about SPF catch almost everyone:
- It checks the envelope sender, not the From address. The envelope sender (also called the MAIL FROM or Return-Path) is where bounces go. Most providers use their own domain for it by default, so SPF passes for their domain. That matters for DMARC, below.
- It has hard limits. A domain must have only one SPF record, and evaluating it may take no more than 10 DNS lookups. Break either and SPF returns
permerror.
DKIM: a signature on every message
DKIM signs each message with a private key. The signature goes in a DKIM-Signature header that names the signing domain (d=) and a selector (s=). The receiver looks up the public key at selector._domainkey.domain in DNS, as defined in RFC 6376, and checks that the signed headers and body are unchanged.
On Amazon SES you never handle the key yourself. With Easy DKIM, AWS manages the key pair and you publish three CNAME records that point at it. SES then signs as your domain with a 2048-bit key by default.
Because the signature travels with the message, DKIM usually survives forwarding, where SPF does not. That makes DKIM the more reliable of the two for DMARC.
DMARC: alignment, policy, and reports
DMARC is a TXT record at _dmarc.yourdomain.com:
v=DMARC1; p=none; rua=mailto:dmarc@yourdomain.com
A message passes DMARC when SPF or DKIM passes and the domain it passed for is aligned with the From address. By default alignment is relaxed: mail.example.com aligns with example.com because they share the same organizational domain.
The p tag says what receivers should do with mail that fails:
| Policy | Meaning | Use it when |
|---|---|---|
p=none | Take no action, just report | You are starting out and reading reports |
p=quarantine | Treat failing mail as suspicious (usually spam folder) | Reports show your own services all pass |
p=reject | Reject failing mail | Quarantine has run cleanly |
The rua tag is where receivers send aggregate reports: XML summaries of which IPs sent mail as your domain and whether it passed. They are how you find a forgotten service before you enforce anything.
DMARC is now defined by RFC 9989 (May 2026), which replaced RFC 7489. One change worth knowing: the old pct tag for applying a policy to a percentage of mail was removed, so roll out with none, then quarantine, then reject instead.
Worked example: a message sent through Amazon SES
You send from hello@example.com through SES. Here is what a receiver checks, with and without a custom MAIL FROM domain:
| Check | Default SES setup | With MAIL FROM mail.example.com |
|---|---|---|
| SPF | Passes for an amazonses.com subdomain | Passes for mail.example.com |
SPF aligned with example.com? | No | Yes (relaxed) |
| DKIM | Passes, d=example.com (Easy DKIM) | Passes, d=example.com |
| DKIM aligned? | Yes | Yes |
| DMARC | Pass (via DKIM) | Pass (via SPF and DKIM) |
Both pass, but the right column passes twice. If a mailing list rewrites the body and breaks the DKIM signature, aligned SPF can still carry DMARC. That is why Mailmark sets up a custom MAIL FROM domain on every domain. The exact records are in the DNS records guide.
Getting to p=reject safely
- Publish SPF and DKIM for every service that sends as your domain: your app's provider, your helpdesk, your marketing tool, your office suite.
- Publish DMARC with
p=noneand aruaaddress. - Read the aggregate reports for a few weeks. Every IP that sends as your domain should be one of your services and pass in alignment.
- Fix the stragglers: add the missing
include, publish the missing DKIM records, or stop the service. - Move to
p=quarantine, keep reading reports, then move top=reject.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
SPF permerror | Two SPF records, or more than 10 lookups | Merge into one record and drop unused includes |
| SPF passes, DMARC fails | SPF passed for your provider's bounce domain, not yours | Set up a custom MAIL FROM, or make sure DKIM signs as your domain |
| DKIM fails only on some messages | A mailing list or gateway changed the signed content | Rely on DKIM for direct mail; list mail is expected to fail sometimes |
| Reports show IPs you don't recognize | A forgotten service, or someone spoofing your domain | Add the service if it's yours; enforcement will block the rest |
Mail rejected after moving to p=reject | A legitimate service that never passed in alignment | Go back to p=quarantine and fix that service first |
To test a domain from the outside, the free deliverability checker reads its SPF, DKIM, and DMARC records. For what else affects inbox placement, see the email deliverability guide.
Frequently asked questions
Do I need all three of SPF, DKIM, and DMARC?
Gmail and Yahoo require all three from anyone sending 5,000 or more messages a day, and Outlook.com does too. Smaller senders need SPF or DKIM at minimum, but publishing all three is cheap and protects your domain from spoofing.
Why does DMARC fail when SPF passes?
SPF checks the envelope sender (the bounce address), not the From address people see. If that envelope domain belongs to your email provider, SPF passes for their domain but isn't aligned with yours, so it doesn't count toward DMARC.
Does forwarding break SPF or DKIM?
Forwarding usually breaks SPF, because the forwarding server's IP isn't in your SPF record. DKIM usually survives, because the signature travels with the message, unless the forwarder changes the signed content.
When should I move DMARC from p=none to p=reject?
When your aggregate reports show that every legitimate source of mail for your domain passes SPF or DKIM in alignment. Go through p=quarantine first and watch the reports again.