
When mail from your domain lands in spam or is rejected, authentication is one of the first things to check. Google
and Yahoo
require all senders to use at least SPF or DKIM, while bulk senders must use SPF, DKIM, and DMARC. These mechanisms associate mail with your domain, but they do not guarantee inbox placement on their own.
This guide explains what each mechanism does, how the three work together, what the records look like, and how to verify your setup from the command line.
Why Email Needs Authentication
SMTP, the protocol that moves mail between servers, was designed without sender verification. Any server can connect to any other server and claim to send mail from example.com; nothing in the protocol stops it. That is why spammers and phishers can forge the From address of any domain.
Authentication closes this gap with DNS and message signing. SPF tells a receiver whether the connecting server is authorized for the envelope sender domain. DKIM associates a cryptographic signature with a signing domain. DMARC checks whether a passing SPF or DKIM identity aligns with the domain in the visible From address, then publishes the domain owner’s handling preference for failures.
How the Three Work Together
Each mechanism covers a different part of the delivery:
- SPF publishes which servers may send mail for your domain. Receivers check the connecting server’s IP against the list.
- DKIM adds a cryptographic signature to each message. Receivers verify it against a public key in DNS to confirm that the holder of the private key signed the message and that the signed content has not changed.
- DMARC ties the result to the visible From address, publishes a handling preference for failures, and can request reports from participating receivers.
Using all three gives you better spoofing protection and diagnostic data even when your sending volume is below provider bulk-sender thresholds.
SPF: Authorizing Sending Servers
SPF (Sender Policy Framework) is a TXT record on the domain itself listing authorized senders:
txt
example.com. 3600 IN TXT "v=spf1 mx ip4:203.0.113.10 include:_spf.google.com -all"
Reading the record left to right: v=spf1 identifies it as SPF, mx authorizes the servers named in the domain’s MX records, ip4:203.0.113.10 authorizes a specific address, and include:_spf.google.com pulls in another domain’s SPF list, which is how you authorize a provider such as Google Workspace to send for you.
The final mechanism sets the SPF result for everything not listed:
-all– Returnsfail, a clear statement that unlisted servers are not authorized.~all– Returnssoftfail, a weaker statement that the server is probably not authorized.+all– Returnspassfor every server, which defeats the purpose of SPF.
The receiving system decides how each result affects delivery. SPF itself does not require a specific action for fail or softfail.
Two rules prevent many common SPF errors. A domain must have exactly one SPF record because multiple records produce permerror. Evaluation can use at most 10 DNS-querying terms, including include, mx, and a; chained provider records can consume that limit quickly.
SPF also has a blind spot: it checks the envelope sender used during the SMTP transaction, not the From header the user sees. Ordinary forwarding often causes SPF to fail because the forwarder’s IP is not in the original sender’s record, unless the forwarder rewrites the envelope sender with Sender Rewriting Scheme (SRS). That is where DKIM helps.
DKIM: Signing Messages
DKIM (DomainKeys Identified Mail) uses public-key cryptography. Your mail server signs each outgoing message with a private key, adding a DKIM-Signature header. Receivers fetch the matching public key from DNS and verify the signature. A valid result shows that the holder of the private key signed the message and that the signed headers and body have not changed. It does not show that the message content is trustworthy.
The public key lives in a TXT record under a selector name, which allows multiple keys per domain:
txt
default._domainkey.example.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."
Here default is the selector; the signing server puts the selector name in each signature header so receivers know which key to fetch. The p= value is the base64-encoded public key, typically 2048-bit RSA.
Unlike SPF, DKIM requires software on the mail server to do the signing. On a self-hosted Postfix setup this is usually handled by a milter such as OpenDKIM or by Rspamd
, which generates the key pair and signs outgoing mail. Hosted providers generate the keys for you and tell you which records to publish.
DKIM generally survives simple forwarding because the signature travels with the message. A forwarding service, mailing list, or security gateway that changes a signed header or the message body can invalidate it.
DMARC: Policy and Reporting
SPF and DKIM authenticate domains that are not necessarily the one shown in the From address. DMARC (Domain-Based Message Authentication, Reporting, and Conformance) adds that connection and publishes a handling preference in a TXT record at _dmarc:
txt
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"
The p= tag describes how the domain owner views mail that fails DMARC:
p=none– Expresses no DMARC-based handling preference and is the normal starting point for monitoring.p=quarantine– Says the domain owner considers failing mail suspicious. A receiver may place it in spam or apply other scrutiny.p=reject– Says the domain owner considers the failed use of the domain invalid.
These values are preferences, not commands. A receiving system can use other signals when deciding whether to accept, quarantine, or reject a message. The current DMARC standard
specifically says that receivers must not reject mail solely because the sender publishes p=reject.
A message passes DMARC when at least one of SPF or DKIM passes and aligns. With the default relaxed alignment, the authenticated domain and the From domain must share the same organizational domain, so bounce.example.com can align with example.com. Strict alignment, enabled with aspf=s or adkim=s, requires identical domains.
Alignment is the part that blocks a common spoofing technique. An attacker can pass SPF for a domain they control while displaying your domain in the From header, but the result does not align and DMARC fails.
The rua= tag requests aggregate XML reports from participating receivers, commonly sent daily. Reports show which systems use your domain and how their messages authenticate. Start with p=none, identify legitimate services such as CRMs and monitoring tools, and fix their SPF or DKIM before considering enforcement. A report-processing service or self-hosted analyzer is easier to use than reading the raw XML. Do not treat p=reject as an automatic endpoint, especially for domains whose users send through mailing lists or forwarding services.
Checking Your Records with dig
All three mechanisms use DNS TXT records, although DKIM also requires a working signer. You can verify what the world sees with dig. Check SPF on the domain itself:
Terminal
dig +short example.com TXT
output
"v=spf1 mx ip4:203.0.113.10 include:_spf.google.com -all"
The answer may include unrelated TXT records. Confirm that exactly one returned string begins with v=spf1.
DKIM requires knowing the selector; check the record your signer uses:
Terminal
dig +short default._domainkey.example.com TXT
output
"v=DKIM1; k=rsa; " "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A..."
DNS can split a long public key into adjacent quoted strings. They form one TXT record when concatenated.
And DMARC always lives at the _dmarc subdomain:
Terminal
dig +short _dmarc.example.com TXT
output
"v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"
If a record is missing from the output, receivers cannot see it either. For more query options, see our dig command guide
. For an end-to-end test, send a message to a Gmail address and use “Show original”, which displays PASS or FAIL for SPF, DKIM, and DMARC on the received message.
Troubleshooting
A new TXT record does not appear
Check that you used the correct DNS host name: @ or the bare domain for SPF, <selector>._domainkey for DKIM, and _dmarc for DMARC. DNS caches may continue returning the previous answer until the record’s TTL expires.
SPF returns permerror
Look for multiple TXT records beginning with v=spf1 and merge them into one. If there is only one record, count its DNS-querying terms and the terms inside every include; exceeding the 10-lookup limit also causes permerror.
SPF or DKIM passes but DMARC fails
The passing identity is probably not aligned with the visible From domain. Inspect the Authentication-Results header for the SPF envelope domain and the DKIM d= signing domain. Configure a custom return path or DKIM signing domain under your own organizational domain.
DKIM reports a body hash mismatch
Something changed the body after it was signed, often a mailing list footer, security gateway, or forwarding service. Compare a directly delivered message with the modified path, and make sure the published selector and key match the active signer.
Quick Reference
| Mechanism | What the receiver checks | DNS record location | Example value |
|---|---|---|---|
| SPF | Connecting IP against the envelope sender policy | TXT at example.com |
v=spf1 mx -all |
| DKIM | Signature against the selector’s public key | TXT at <selector>._domainkey.example.com |
v=DKIM1; k=rsa; p=<key> |
| DMARC | SPF or DKIM alignment with the visible From domain | TXT at _dmarc.example.com |
v=DMARC1; p=none; rua=mailto:... |
Conclusion
SPF authorizes sending infrastructure, DKIM associates a valid signature with a domain, and DMARC checks alignment with the visible From address. If you run your own stack, our guides on setting up Postfix and Dovecot
and integrating Rspamd
cover the server-side configuration, including DKIM signing.
