Three DNS records. Three different jobs. Three different failure modes. Most tutorials treat SPF, DKIM, and DMARC as a checklist — "add these records and you're done." That's not wrong exactly, but it hides the fact that each record is solving a distinct problem, and when one fails, it fails in a specific way that the other two may or may not compensate for.
This is the article for developers who want to understand what's actually happening — not just what to copy into their DNS zone.
SPF: Authorising the Sending IP
SPF — Sender Policy Framework — answers one question: is this IP address allowed to send email for this domain?
It operates at the SMTP envelope level, not the message level. When a receiving mail server accepts an incoming SMTP connection, it checks the MAIL FROM address (also called the envelope sender or return-path). The receiving server looks up the DNS TXT record for that domain and checks whether the connecting IP is listed as an authorised sender.
A basic SPF record looks like this:
v=spf1 ip4:203.0.113.10 include:sendgrid.net -all
Breaking this down:
v=spf1 — declares this is an SPF record. Required.
ip4:203.0.113.10 — authorises a specific IPv4 address.
include:sendgrid.net — instructs the receiving server to also fetch and evaluate the SPF record for sendgrid.net. If the sending IP is authorised under that record, it passes here too.
-all — any IP not matched by the preceding mechanisms is a hard fail.
The alternatives to -all:
+all — passes every IP. This is the equivalent of having no SPF record. Never use this for a real domain.
~all — softfail. The email is delivered but marked. Most receiving servers treat this as a minor negative signal rather than a rejection. Appropriate during setup phases.
?all — neutral. Provides no guidance.
-all — hard fail. Use this once your record is complete.
What SPF Does Not Check
SPF does not check the From: header — the address the recipient sees in their email client. It only checks the envelope sender, which is often invisible to end users. This is a critical distinction.
An attacker can send email with From: ceo@yourcompany.com in the visible header while using a completely different envelope sender domain. SPF will evaluate that envelope sender domain, find a passing result, and the email will pass SPF — despite the From: header showing your domain. This is why SPF alone is not sufficient.
The 10-Lookup Limit
SPF evaluation is bounded. The specification allows a maximum of 10 DNS lookups during evaluation of a single SPF record. Each include:, a:, mx:, and redirect= mechanism counts as one lookup.
This means a record with five or six include: mechanisms, each of which may themselves contain further includes, can easily exceed the limit. If evaluation hits 10 lookups before all mechanisms are assessed, the result is a permerror — treated by most receivers as a softfail or neutral.
The solution is to reduce the number of include: mechanisms or use an SPF flattening service that resolves all IP addresses and writes them as explicit ip4: and ip6: mechanisms.
DKIM: Proving the Message Wasn't Modified in Transit
DKIM — DomainKeys Identified Mail — solves a different problem than SPF. Where SPF asks "is this IP authorised to send for this domain?", DKIM asks "was this message cryptographically signed by the claimed domain, and has it been modified since?"
DKIM uses asymmetric cryptography. The sending mail server holds a private key. The corresponding public key is published in DNS under a selector subdomain. When a message is sent, the sending server creates a hash of certain message headers and the body, then encrypts that hash with the private key. This signature is added to the message as a DKIM-Signature header.
When a receiving server processes the message, it reads the DKIM-Signature header, fetches the public key from {selector}._domainkey.{domain} in DNS, and uses that key to verify the signature. If the signature verifies correctly, the message content and signed headers have not been modified since signing.
A DKIM public key DNS record looks like this:
mail._domainkey.example.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
The selector here is mail. The p= value is the base64-encoded public key.
What DKIM Does Not Check
DKIM does not verify that the From: header matches the signing domain. A message can be DKIM-signed by attacker.com while displaying From: ceo@yourcompany.com. The DKIM signature will validate correctly against attacker.com's public key. DKIM passes. The recipient sees your domain in the From header. Again, DKIM alone is not sufficient.
DKIM and Forwarding
Here is where DKIM and SPF diverge in a practically important way. When a message is forwarded — by a mailing list, an email forwarding service, or a colleague — the forwarding server typically changes the envelope sender (breaking SPF) but does not modify the message body or signed headers (preserving DKIM).
DKIM signatures survive forwarding. SPF results do not. For forwarded mail, DKIM is the authentication mechanism that keeps working. This is one reason why DKIM is generally considered more reliable than SPF in environments with significant forwarding.
Key Rotation
DKIM private keys should be rotated periodically. Generate a new key pair, publish the public key under a new selector, configure your mail server to sign with the new key, then retire the old selector. Because the selector is embedded in every signed message, in-flight messages still verify against the old key until delivered.
Use 2048-bit keys at minimum. 4096-bit is more secure but some DNS providers have TXT record length limits that complicate publication.
DMARC: Alignment and Policy
DMARC — Domain-based Message Authentication, Reporting, and Conformance — ties SPF and DKIM together and adds enforcement.
DMARC introduces the concept of alignment. Alignment checks whether the domains in SPF and DKIM match the From: header domain — the domain the end user actually sees.
For a DMARC check to pass, at least one of these must succeed:
- The domain in the envelope sender (checked by SPF) aligns with the
From: domain, and/or
- The domain in the DKIM
d= parameter aligns with the From: domain.
If SPF passes but the envelope sender domain doesn't align with the From: header domain, SPF doesn't contribute to DMARC passing. This is the alignment concept that neither SPF nor DKIM alone implements.
A DMARC record looks like this:
_dmarc.example.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@example.com; pct=100; adkim=r; aspf=r"
v=DMARC1 — version declaration.
p=quarantine — the policy.
rua=mailto:... — aggregate report destination. You'll receive daily XML reports from participating receivers.
pct=100 — the percentage of failing messages to apply the policy to. Setting this to 10 during rollout means 10% of failing messages get quarantined, 90% are delivered.
adkim=r — relaxed alignment for DKIM (subdomains acceptable).
aspf=r — relaxed alignment for SPF.
The Three Policy Levels
p=none is monitoring mode. Messages that fail DMARC alignment are delivered as normal. Reports are still sent if rua is set. This is where you start — you collect data to understand what's sending mail under your domain before enforcing anything.
The problem in practice: most domains never leave p=none. Once published, if the immediate deliverability problem goes away, nobody revisits the policy. p=none provides no protection against spoofing. Anyone can send email appearing to come from your domain, and your DMARC record explicitly instructs receivers to do nothing about it.
p=quarantine instructs receivers to send failing messages to spam. The intermediate enforcement level.
p=reject instructs receivers to refuse to accept messages that fail DMARC alignment. At p=reject, spoofed messages claiming to be from your domain are refused at the SMTP level. The recipient never sees them.
Understanding Aggregate Reports
The rua aggregate reports are essential for safe DMARC implementation. They show you:
- Which IP addresses sent email claiming to be from your domain
- What the SPF and DKIM results were for each
- What the DMARC disposition was
- How many messages were sent
If you move to p=reject before correctly capturing all your legitimate sending sources, you'll start rejecting your own legitimate mail. Aggregate reports show you what you're about to break before you enforce. Parse them manually or use a DMARC reporting service — there are several that produce readable dashboards from the raw XML.
Why All Three Must Work Together
SPF alone: You can verify the sending IP is authorised, but you can't prevent someone from spoofing the From: header, and your check breaks when mail is forwarded.
DKIM alone: You can verify message integrity and the signing domain, but the signing domain doesn't have to match the From: header domain, so it doesn't prevent spoofing as seen by the recipient.
DMARC alone (without SPF and DKIM): DMARC has no authentication signals to check alignment against. It can't function without at least one of SPF or DKIM.
All three together: SPF verifies the sending IP is authorised for the envelope sender domain. DKIM verifies the message was signed by a key published under a specific domain. DMARC checks that at least one of those domains aligns with the From: header domain and enforces a policy when they don't. Only when all three are correctly configured and aligned do you have genuine email authentication.
Getting to p=reject
The path:
- Set up SPF correctly — enumerate all sending sources, end with
-all.
- Configure DKIM for all sending servers and services. Verify signatures are being applied and validating.
- Publish DMARC at
p=none with an rua address.
- Wait at least two to four weeks and analyse the aggregate reports.
- Identify and fix any legitimate sources that are failing.
- Move to
p=quarantine at a low pct value. Increase gradually.
- Move to
p=reject.
This process takes weeks, not hours. Anyone who tells you to jump straight to p=reject on day one is setting you up for a mail outage.
The team behind FXRM has been working through these problems since long before the acronyms existed. Our email hosting comes with proper PTR configuration, DKIM signing, and DMARC policy configured from the start. If you want infrastructure where this is handled correctly rather than added as an afterthought, take a look at our email hosting.