Guides
SPF, DKIM and DMARC Explained: Email Authentication for Humans
What SPF, DKIM and DMARC actually check, with annotated DNS records, the Gmail, Yahoo and Outlook sender rules, and a safe path from p=none to p=reject.

You bought a domain, set up hello@yourname.com, and sent your first invoice. It landed in the client’s spam folder. Or it arrived, but Gmail showed your name with “via” and someone else’s domain after it, or with a question mark beside it.
Both are Gmail saying it can’t fully vouch for you. A question mark means the message isn’t authenticated; “via” means “the domain it was sent from doesn’t match the domain in the ‘From:’ address”. The fix is three DNS records with unlovely names: SPF, DKIM and DMARC. None is hard once you know which question each answers, and since 2024 the big mailbox providers have stopped treating them as optional.
Email was built on trust
SMTP, the protocol that moves mail between servers, was designed in the early 1980s for a small network of people who knew each other. It has no built-in check that a sender is who they claim to be. Any server can connect to Gmail and announce that it’s delivering mail from your bank.
It also helps to know that every message carries two sender addresses:
- The envelope sender, given in the SMTP
MAIL FROMcommand and later recorded as theReturn-Pathheader. It’s where bounces go, and you rarely see it. - The header From, the name and address your inbox displays.
Think of a posted letter. The envelope has a return address for the postal service; the letter inside has a letterhead for the reader. Nothing forces them to match, and often they legitimately don’t: a newsletter service sets its own bounce address so it can process failures automatically. That gap explains most of what follows.
SPF: a published list of who may send
SPF (Sender Policy Framework, RFC 7208) is a TXT record on your domain listing the servers allowed to send mail for it. When a message arrives, the receiving server takes the connecting IP address and checks it against the SPF record of the envelope sender’s domain.
example.com. TXT "v=spf1 include:_spf.google.com include:_spf.mailer.example ip4:203.0.113.25 ~all"
v=spf1marks this as an SPF record.include:_spf.google.comauthorises Google Workspace’s servers. Each provider documents its own include.include:_spf.mailer.examplestands in for a newsletter or invoicing service.ip4:203.0.113.25authorises one specific machine, say the web server that sends your contact form mail.~allsays everything else is a “softfail”: probably not authorised.
The catch is that SPF checks the envelope sender, not the From you see. A spammer can pass SPF for their own throwaway domain while putting your address in the From line, so SPF alone doesn’t stop anyone spoofing the address people actually read.
Three rules catch people out:
- One SPF record per domain. Publishing two
v=spf1records gives a “permerror” result under the RFC, which receivers treat as a broken record. Add a new service by editing the existing record, never by adding a second one. - Ten DNS lookups, maximum. The
include,a,mx,ptrandexistsmechanisms and theredirectmodifier each cost a lookup, including those nested inside other people’s includes. Section 4.6.4 says going past ten must also return permerror.ip4,ip6andallare free. ~allversus-all.-allis a hard fail;~allis, in the RFC’s words, “a weak statement” that the host is probably not authorised. Hard fail sounds better, but once DMARC is in place~allis usually safer, for reasons covered below.
SPF also breaks when mail is forwarded. The forwarded copy arrives from the forwarder’s IP address, which isn’t in your record.
DKIM: a tamper-evident seal
DKIM (DomainKeys Identified Mail, RFC 6376) works on the message rather than the route. The sending server signs the message with a private key and adds a header; the matching public key sits in DNS for anyone to check.
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=google;
h=from:to:subject:date:message-id; bh=2jUSOH9N...; b=AuUoFEfD...
d=is the signing domain.s=is the selector, which tells the receiver where to find the key.h=lists the headers covered by the signature. The RFC says From must always be one of them.bh=is a hash of the body, andb=is the signature itself.
The receiver joins the selector and domain to find the public key:
google._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
Selectors let one domain hold several keys at once, one per sending service, and swap keys without downtime. Google Workspace’s default selector is google, and Google recommends a 2048-bit key where your DNS host allows it. Microsoft 365 uses two, selector1 and selector2, so it can rotate between them. Your newsletter tool will have its own.
Because the signature travels with the message, DKIM usually survives plain forwarding. What breaks it is modification: a mailing list that tags the subject line or appends a footer invalidates the signature.
DKIM has a gap of its own: nothing requires d= to match the From address. A spammer can sign perfectly valid mail with their own domain. A good signature proves the d= domain sent this exact message, not that the From line is honest.
DMARC: tying it all to the address you see
DMARC closes both gaps. It asks one question: did SPF or DKIM pass for a domain that matches the From domain? That match is called alignment, and a message passes DMARC if at least one of the two passes and aligns.
From: Jo Bloggs <invoices@example.com>
Return-Path: <bounce-8812@mailer.example> SPF passes for mailer.example: not aligned
DKIM-Signature: d=example.com; s=mlr1; ... DKIM passes for example.com: aligned
Result: DMARC passes, thanks to DKIM
Alignment is relaxed by default, so news.example.com aligns with example.com because they share an organisational domain. Setting adkim=s or aspf=s demands an exact match, which few small domains need.
The record lives at a fixed name under your domain:
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"
v=DMARC1is required and must come first.p=is your policy for mail that fails:none(deliver as normal, just report),quarantine(treat as suspicious, usually the spam folder) orreject(refuse it outright).rua=is where receivers send aggregate reports: XML summaries, usually daily, listing every IP that sent mail as your domain and whether it passed. It’s the most useful part of DMARC and the part most people skip, because it shows you the services you forgot about and anyone spoofing you.
Optional extras include sp= for subdomains and np= for subdomains that don’t exist, so you can be stricter about invented names like billing.example.com than about real ones.
This is also where -all bites. The DMARC spec warns that some receivers run SPF before DMARC, so -all can get a message refused on SPF alone, even one that would have passed DMARC through DKIM. Those rejections never appear in your reports, either.
DMARC became a proper standard in 2026
For over a decade DMARC was defined by RFC 7489, published in March 2015 as an Informational document: a description of what the industry was already doing, not an IETF standard. On 20 May 2026 the IETF published the long-running “DMARCbis” revision as RFC 9989, alongside RFC 9990 for aggregate reports and RFC 9991 for failure reports. Together they obsolete RFC 7489 and put DMARC on the Standards Track as a Proposed Standard.
For a domain owner, less changes than the fanfare suggests. Records still start v=DMARC1, and p= and rua= work as before. The np= tag above is new. The notable removal is pct, which was meant to apply your policy to a percentage of failing mail; the RFC says it was “usually not accurately applied” for anything other than 0 or 100. Its replacement is t=y, a test flag asking receivers to apply one level below your stated policy. Receivers will adopt the new rules at their own pace, so an old record with pct still parses, but don’t count on the percentage being honoured.
The three side by side
| SPF | DKIM | DMARC | |
|---|---|---|---|
| Question it answers | Is this server allowed to send for the envelope domain? | Did the signing domain send this, unaltered? | Does a pass match the visible From, and what if not? |
| Record location | example.com | selector._domainkey.example.com | _dmarc.example.com |
| Domain it checks | Envelope sender (Return-Path) | d= in the signature | Header From |
| Survives forwarding | Usually not | Usually, unless the message is modified | Only if DKIM survives |
| Current spec | RFC 7208 | RFC 6376 | RFC 9989 (replaced RFC 7489) |
Why this stopped being optional
Until 2024, all three were strongly recommended. Then the mailbox providers started enforcing them.
Google, from 1 February 2024. Every sender to personal Gmail accounts needs SPF or DKIM, valid forward and reverse DNS, TLS, and a spam rate below 0.3%. Bulk senders (close to 5,000 messages a day to personal Gmail accounts, counted across the whole domain, and permanent once reached) also need SPF and DKIM, a DMARC record (p=none is fine) with the From domain aligned, and one-click unsubscribe on marketing mail. Google stepped up enforcement in November 2025, and non-compliant mail now faces “disruptions, including temporary and permanent rejections.”
Yahoo, also from February 2024, with almost the same list: SPF or DKIM for everyone; SPF, DKIM, DMARC of at least p=none, alignment and one-click unsubscribe, honoured within two days, for bulk senders. Yahoo deliberately doesn’t publish a threshold: “We will not specify a volume threshold,” says its FAQ.
Microsoft, from 5 May 2025. Domains sending over 5,000 messages a day to Outlook.com, Hotmail and Live addresses must pass SPF and DKIM and publish DMARC of at least p=none, aligned with SPF or DKIM. Microsoft first said failing mail would go to Junk, then changed course in an update on 29 April: it is rejected outright with “550; 5.7.515 Access denied, sending domain [SendingDomain] does not meet the required authentication level.”
If you’re a freelancer sending forty emails a day, the bulk thresholds don’t apply. The baseline does, and Google’s guidelines say unauthenticated messages “might be marked as spam or rejected with a 5.7.26 error.” (The same rules made one-click unsubscribe mandatory for bulk senders, which is why mass unsubscribing got so much easier.)
How to check your own domain
In Gmail. Send a message from your domain to a Gmail address, open it, and choose Show original from the three-dot menu next to Reply. The top of the page summarises SPF, DKIM and DMARC as PASS or FAIL, with the IP or domain each was checked against. Further down, the raw Authentication-Results header shows the detail, such as dkim=pass header.d=example.com and dmarc=pass header.from=example.com. You want DMARC passing, and DKIM passing for your own domain rather than your provider’s.
With a free checker. MXToolbox has SPF, DKIM and DMARC lookups that parse your records and flag problems; the DKIM one needs the selector, which is the s= value in Show original. Learn and Test DMARC, sponsored by the monitoring company URIports, goes further: you send a test message to the address it shows you and it animates the conversation between the servers, check by check. It’s the quickest way to watch everything in this post actually happen.
A rollout that won’t bounce your own invoices
- List everything that sends as your domain. Your mailbox provider, newsletter tool, invoicing or accounting software, helpdesk, website contact form, booking system, the office scanner. The one you forget is the one that breaks.
- Publish one SPF record covering the services that use your domain as their envelope sender, ending in
~all. Many newsletter services use their own return path and need no include; their docs will say. - Turn on DKIM in every service, signing as your domain. Providers call it “domain authentication” or “custom DKIM”, and it’s usually a couple of CNAME records. This is the step that normally makes “via” disappear.
- Publish DMARC at
p=nonewithrua. Point reports at a service rather than your inbox, because raw XML is nobody’s idea of reading. Postmark’s DMARC digests give a free weekly summary of your top ten sources. - Read, fix, wait. Give it a few weeks, and a full month if something sends monthly, like invoice runs or payroll. Every legitimate source should pass. Anything unfamiliar is a service you forgot or someone pretending to be you.
- Move to
p=quarantine. Watch the reports for another few weeks. - Move to
p=reject. For a halfway step,p=reject; t=yasks receivers following the new spec to treat it as quarantine. Keep reading reports afterwards: someone will eventually sign up for a new tool without telling you.
Common mistakes
- Two SPF records, or too many includes. A new service’s instructions say “add this TXT record”, and now you have two and SPF fails for everything. When you hit the lookup limit, remove services you’ve stopped using before reaching for “SPF flattening” tools, which swap includes for IP lists that go stale when providers change addresses.
- Authenticating the service’s domain instead of yours. Out of the box, many services sign with their own domain and use their own return path. SPF passes, DKIM passes, neither aligns, DMARC fails, and Gmail shows “via”.
- Parking at
p=noneforever. Monitoring mode protects nobody. The bulk-sender rules only ask forp=none, so it’s tempting to stop there, but it’s a stage, not a destination. - Sending reports to a domain you don’t control. If
ruapoints at another domain, receivers only send reports once that domain publishes an authorising record at a name likeexample.com._report._dmarc.reports.example. Reputable report services set this up on their side. You can’t do it for a personal gmail.com address. - Leaving unused domains open. A domain that never sends email is free spoofing material. The UK government’s guidance for such domains is
v=spf1 -all, a DMARC record atp=rejectand a null MX record. Here-allis right, because nothing legitimate should ever pass. - Expecting DMARC to stop phishing. It protects your exact domain and nothing else. Lookalike domains, display-name tricks and mail from genuinely hacked accounts all pass authentication, which is why spotting phishing still takes a human eye.
ARC and BIMI, briefly
ARC exists because forwarding and mailing lists are DMARC’s weak spot. When Yahoo published p=reject for yahoo.com in April 2014, mailing lists started bouncing Yahoo users’ posts across the internet, because lists rewrite subjects and add footers. The Authenticated Received Chain (RFC 8617, July 2019, still Experimental) lets each intermediary record the authentication results it saw and seal them with its own signature. The final receiver can choose to trust it; Microsoft 365, for example, lets admins name trusted ARC sealers. It’s a job for whoever runs the forwarder or list, not something a domain owner publishes.
BIMI (Brand Indicators for Message Identification) puts your logo beside your messages in supporting inboxes. It requires DMARC at quarantine or reject, and Gmail also wants any percentage set to 100, plus an SVG logo. Gmail and Apple Mail also require a certificate: a Verified Mark Certificate (VMC), which needs a registered trademark and earns a checkmark in Gmail, or a Common Mark Certificate (CMC), which needs no trademark but does need twelve months of prior use of the logo. Yahoo shows logos without one. BIMI is not an IETF standard, just an individual Internet-Draft. For a freelancer it’s a nice-to-have at best.
Where your email client fits in
None of this happens in your email client. SPF is about which servers deliver your mail, DKIM signing happens on your provider’s outgoing server, and DMARC is a DNS record. A desktop client like Kanmail hands your outgoing mail to your provider’s own SMTP server, so once the DNS is right, mail sent from the app authenticates just like mail sent from webmail. If you run email on your own domain through Fastmail or another host, adding it is a standard IMAP setup.
The thing to avoid is sending as your domain through servers your records don’t cover, which is how a “via” label appears. We covered the most common version, forwarding one account into another and replying from it, in managing multiple email accounts.
The bottom line
SPF lists who may send. DKIM proves a message is intact and says who signed it. DMARC insists one of them matches the From address people actually read, and tells receivers what to do when it doesn’t. Start DMARC at p=none with reports on, fix what they show you, and work up to p=reject. It’s an afternoon of DNS and a few weeks of patience, and it’s the difference between an invoice in the inbox and a question mark next to your name.
Frequently asked questions
What is DMARC?
DMARC is a DNS record, published at _dmarc.yourdomain, that tells receiving mail servers what to do with messages that claim to come from your domain but fail authentication. A message passes DMARC when SPF or DKIM passes for a domain that matches the visible From address. The policy can be none (just report), quarantine (treat as suspicious) or reject (refuse it), and the rua tag asks receivers to send you regular reports.
What is DKIM?
DKIM is a digital signature added to outgoing email by the sending server. It covers the From header, other chosen headers and the body, and receivers check it against a public key the domain publishes in DNS at selector._domainkey.yourdomain. A valid signature proves the message was signed by that domain and hasn't been altered since. On its own it doesn't prove the From address is honest; that's DMARC's job.
What is an SPF record?
An SPF record is a TXT record on your domain, starting v=spf1, that lists the servers allowed to send mail for it. Receivers compare the IP address of the sending server with that list. You may only have one SPF record per domain, and it can trigger at most ten DNS lookups; breaking either rule makes SPF fail with a permanent error.
Do I need DMARC if I don't send bulk email?
Gmail and Yahoo only require DMARC from bulk senders, and Microsoft's rule applies above 5,000 messages a day. But every sender needs at least SPF or DKIM, and a DMARC record costs nothing. Once set to quarantine or reject, it is the only one of the three that stops someone putting your exact address in the From line, and its reports show you every service sending as your domain.
Why does Gmail show "via" next to my name?
Gmail adds "via" and a domain when the domain a message was sent from doesn't match the domain in the From address. It usually means a newsletter tool, CRM or forwarding setup is sending as you but signing with its own domain. Set up DKIM in that service using your own domain (often called domain authentication) and the label normally disappears.


