Publish DMARC in monitoring mode
Add one TXT record at _dmarc on the domain in your From address. p=none does not change delivery, and rua asks receivers for aggregate reports that show which servers send mail as your domain and whether they pass SPF or DKIM in alignment. If the reports go to another domain, that domain must publish a record that authorizes them.
; DMARC record for example.com, monitoring only
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"
; Only if rua points to another domain, for example rua=mailto:reports@example.net,
; example.net publishes:
example.com._report._dmarc.example.net. TXT "v=DMARC1"
Move to quarantine, then reject
When the reports show every legitimate source passing, switch to p=quarantine, watch the reports again, then move to p=reject. RFC 7489 offered pct to apply the policy to part of the failing mail. RFC 9989, which replaces it, drops pct because partial values were applied unevenly, and adds t=y, which asks receivers to apply one level below the published policy. Receivers that still follow RFC 7489 ignore t=y, so add pct=0 while testing: it asks them for the same one-level-lower handling. Remove both tags to enforce.
; Publish one version at a time, in this order, after p=none
; 1. Quarantine in test mode (t=y, plus pct=0 for RFC 7489 receivers), then in full
_dmarc.example.com. TXT "v=DMARC1; p=quarantine; t=y; pct=0; rua=mailto:dmarc-reports@example.com"
_dmarc.example.com. TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.com"
; 2. Reject in test mode, then in full
_dmarc.example.com. TXT "v=DMARC1; p=reject; t=y; pct=0; rua=mailto:dmarc-reports@example.com"
_dmarc.example.com. TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@example.com"
Keep one SPF record per domain
A name may carry only one TXT record that starts with v=spf1; two make SPF fail with a permanent error. Merge every sender into one record. include: checks a provider's own record, and redirect= hands the whole policy to another domain, which helps when several domains share one policy. redirect= is ignored when the record also contains an all term.
; Before: two SPF records on one name (permerror)
example.com. TXT "v=spf1 include:_spf.mailhost.example ~all"
example.com. TXT "v=spf1 include:spf.newsletter.example ~all"
; After: one record
example.com. TXT "v=spf1 include:_spf.mailhost.example include:spf.newsletter.example ~all"
; Another domain that uses the same policy
example.org. TXT "v=spf1 redirect=example.com"
Stay within ten DNS lookups
SPF allows at most ten terms that need a DNS lookup, counted across every nested include: include, a, mx, ptr, exists and redirect. One more and SPF fails with a permanent error. Remove includes for services you no longer use, replace a and mx with ip4 or ip6 ranges you control, drop ptr, and move a bulk sender to a subdomain with its own SPF record. Copying a provider's addresses into your record also saves lookups, but the copy goes stale when the provider changes them. This checker counts only the top-level terms.
; One lookup each: include, a, mx, ptr, exists, redirect (plus every lookup inside an include)
; No lookup: ip4, ip6, all
; Before: 4 lookups in the top-level record alone
example.com. TXT "v=spf1 a mx include:_spf.mailhost.example include:spf.oldtool.example ~all"
; After: fixed address, unused service removed, bulk mail on its own subdomain
example.com. TXT "v=spf1 ip4:192.0.2.10 include:_spf.mailhost.example ~all"
news.example.com. TXT "v=spf1 include:spf.newsletter.example ~all"
Choose ~all or -all with care
End the record with ~all (softfail) or -all (fail), never with +all, which lets any server pass. -all is the stricter signal, but a receiver that checks SPF early can then reject forwarded mail before DMARC sees its valid DKIM signature. With an enforced DMARC policy, ~all leaves the decision to DMARC. A domain that sends no mail can publish v=spf1 -all.
; Choose one ending for example.com, not both
example.com. TXT "v=spf1 include:_spf.mailhost.example ~all"
example.com. TXT "v=spf1 include:_spf.mailhost.example -all"
; A domain that sends no mail
example.net. TXT "v=spf1 -all"
Align DKIM with your From domain
DMARC passes when SPF or DKIM passes for a domain aligned with the From address. Many services sign with their own domain by default, which passes DKIM but not alignment. Turn on signing with your own domain in each service, so the signature carries d=example.com, and publish the key or CNAME the service gives you under its selector. Relaxed alignment, the default, accepts any subdomain of the same organizational domain; adkim=s and aspf=s require an exact match.
; Key for a sending service, selector s1: a CNAME or a TXT record, as the service says
s1._domainkey.example.com. CNAME s1.dkim.mailhost.example.
s1._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOC..."
; Aligned signature in a delivered message: d= matches the From domain
From: news@example.com
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=s1; ...
A DNS change can take as long as the old record's TTL to reach every resolver. Then run the checker again on the domain in your From address, because it reads the exact hostname you enter.