Every developer who's sent transactional email has eventually landed in spam. The usual advice โ "add SPF, add DKIM, add DMARC" โ is correct but incomplete. Many teams add all three records, still end up in spam, and have no idea why. The reason is almost always misconfiguration or a misunderstanding of what each mechanism actually does.
This post explains SPF, DKIM, and DMARC from the perspective of what problem each one was designed to solve, how they interact, and the specific sequence for deploying them without accidentally blocking your own legitimate mail in the process.
The problem: email has no built-in authentication
SMTP โ the protocol email runs on โ was designed in an era when the internet was a small trusted network of universities and research institutions. The From: header in an email is entirely self-reported. Nothing in the base protocol prevents a server from claiming to send mail from any address it likes. This is why phishing and spoofing are so easy: technically, anyone can send an email that says it's from ceo@yourbank.com.
SPF, DKIM, and DMARC were each created to address parts of this problem. They are DNS-based: the sending domain publishes records that receiving mail servers can verify. None of them require any protocol changes to SMTP itself.
SPF: who is authorized to send mail for this domain
SPF (Sender Policy Framework) lets a domain publish a list of IP addresses and hostnames that are authorized to send email on its behalf. A receiving server looks up the SPF record of the domain in the envelope sender (the MAIL FROM in the SMTP conversation, sometimes called the "return path" or "bounce address") and checks whether the sending IP is in that list.
The most important choice is the all qualifier at the end:
+allโ pass everything (useless, defeats the purpose)~allโ softfail: mark unlisted senders as suspicious but accept the mail-allโ hardfail: reject mail from unlisted senders
SPF limitation most guides skip: SPF only checks the envelope sender, not the From: header the user sees. A spoofed email can have a legitimate envelope sender (passing SPF) while showing a completely different address in the From: header. This is why SPF alone doesn't stop display-name phishing. DMARC closes this gap with the alignment requirement.
The other common SPF pitfall: the 10-lookup limit. Each include: directive triggers a DNS lookup, and each of those can trigger more. SPF processing stops after 10 total lookups and the check fails. If you use multiple email service providers (transactional + marketing + CRM), you can hit this limit easily. Use tools like dmarcian.com/spf-survey/ to count your lookups before publishing.
DKIM: cryptographic proof the message wasn't tampered with
DKIM (DomainKeys Identified Mail) works completely differently from SPF. Instead of IP authorization, it uses public-key cryptography. The sending mail server signs specific message headers and the body with a private key. The signature is added as a DKIM-Signature header. The receiving server retrieves the corresponding public key from DNS and verifies the signature.
The selector (mail in mail._domainkey.example.com) lets you have multiple DKIM keys simultaneously โ useful for rotating keys without downtime. Email service providers assign their own selectors; you'll see records like s1._domainkey or google._domainkey.
What DKIM proves: that the owner of the signing domain (specifically, whoever holds the private key) sent or authorized this message, and that the signed headers and body haven't changed in transit. What DKIM doesn't prove: that the From: header matches the signing domain. A spammer can DKIM-sign mail from spammer.com and put From: ceo@yourbank.com โ the DKIM signature is valid, but it proves nothing about the claimed sender identity.
Prefer ed25519 keys for new DKIM deployments. They're smaller (shorter DNS records), faster to verify, and considered more secure than 2048-bit RSA. The main caveat: some very old mail servers don't support ed25519 โ for broad compatibility, publish both an RSA key and an ed25519 key with different selectors.
DMARC: policy and alignment
DMARC (Domain-based Message Authentication, Reporting and Conformance) is the mechanism that ties SPF and DKIM together and actually lets a domain owner enforce policy against messages that fail authentication.
DMARC does two things: it requires alignment (the authenticated domain must match the From: header domain), and it lets the domain owner specify a policy for what receivers should do with unauthenticated mail.
Alignment is the key concept. For DMARC to pass, either SPF or DKIM must pass and the authenticated domain must align with the From: header domain. Relaxed alignment (the default) allows subdomain matches โ mail.example.com aligns with example.com. Strict alignment requires an exact match.
This is what closes the SPF gap. Under DMARC, it's no longer enough to have a valid SPF pass โ the domain that SPF authenticated has to match the domain the user sees in the From: header.
The deployment sequence: don't go straight to p=reject
The most common DMARC mistake is jumping straight to p=reject. This will block legitimate mail from any sending source you haven't yet configured. The correct sequence:
p=none (monitor)
Publish DMARC with p=none and an rua address. No mail is blocked. Aggregate reports arrive daily showing which sources are passing and failing. Inventory every sending source: your mail server, transactional ESP, marketing platform, CRM, support ticketing.
p=quarantine (pct=10โ100)
Once reports show all legitimate sources passing, move to p=quarantine; pct=10. Start at 10% to catch any missed sources. Monitor for legitimate mail appearing in spam. Increase pct in steps: 25, 50, 100. Fix any sources that appear.
p=reject
Once quarantine at 100% is stable for 2+ weeks with no legitimate mail affected, move to p=reject. Now any mail claiming to come from your domain that fails DMARC is refused outright. This is full protection against email spoofing.
Reading aggregate DMARC reports
DMARC aggregate reports (rua) are daily XML files that can be difficult to read raw. Use a free tool like dmarcian.com, dmarc.postmarkapp.com, or mxtoolbox.com/dmarc to parse them visually. What to look for in each report:
- Source IPs you don't recognize โ could be a forgotten sending system (CRM, HR platform) or an active spoofing attempt
- SPF pass but DMARC fail โ SPF authenticated a different domain than
From:; common with email forwarding and some ESPs that use their own return-path domain - DKIM pass but DMARC fail โ the DKIM signature is valid but the signing domain doesn't align with
From: - Both fail โ mail not sent from any of your authorized systems; either a legitimate source you haven't configured or spoofed mail
47mail and DMARC
47mail handles the complete SPF/DKIM/DMARC setup for every domain you send from. When you add a sending domain, 47mail generates the DNS records to publish (including an ed25519 DKIM key with automatic rotation every 90 days), parses your DMARC aggregate reports automatically, and surfaces any failing sources in the dashboard. The report parsing runs continuously โ not just a daily digest โ so you see new unknown sources immediately rather than 24 hours later.
The DMARC deployment sequence is also managed: 47mail starts at p=none, monitors until all your configured sending sources are passing, then walks you through the quarantine and reject stages with explicit confirmation at each step. No accidental p=reject deployments.
Quick diagnostic checklist: Run dig TXT _dmarc.yourdomain.com, dig TXT yourdomain.com (for SPF), and dig TXT selector._domainkey.yourdomain.com (for DKIM) to verify your records are published correctly. Then send a test message to check-auth@verifier.port25.com โ it'll reply with a full DMARC/DKIM/SPF authentication report.