Email authentication is one of those infrastructure domains where the gap between “I set it up” and “it actually works” is enormous, and the gap between “it works” and “it works well” is larger still. Developers ship products, configure SPF and DKIM because their transactional provider’s onboarding checklist says to, and then discover months later that their password-reset emails are landing in spam for a measurable percentage of users. The mechanics behind email deliverability SPF DKIM DMARC setup are not actually complicated — but they require understanding the protocol chain in the right sequence, and most tutorials stop at syntax without explaining the reasoning that makes the decisions obvious.
Why Emails Go to Spam: The Real Picture
Receiving mail servers — and increasingly, the reputation networks those servers consult — evaluate inbound messages on a combination of signals. Authentication is one category. Sending reputation is another. Content analysis is a third. Most engineers assume content is the dominant factor and optimize accordingly, adding unsubscribe headers and avoiding spam trigger words. In reality, for transactional email sent from a properly configured domain, failed or missing authentication is the fastest path to the spam folder.
The authentication trifecta — SPF, DKIM, and DMARC — exists to answer three questions that receiving servers need answered before they’ll route a message to the inbox:
- SPF: Was this message sent from a server that the domain owner authorized?
- DKIM: Was this message cryptographically signed by the sending domain, and has it been tampered with in transit?
- DMARC: What should the receiver do if SPF or DKIM fail, and how should alignment be enforced?
Each of these operates independently at the DNS and SMTP layer. A message can pass SPF and fail DKIM, or pass DKIM and fail DMARC alignment. Understanding the failure modes requires understanding each component in isolation before understanding how they interact.
SPF: Authorized Senders, Declared in DNS
SPF (Sender Policy Framework) works by publishing a DNS TXT record on your domain that enumerates the servers permitted to send mail claiming that domain as their MAIL FROM. When a receiving server accepts an incoming message, it looks up the SPF record for the domain in the envelope sender address and checks whether the sending server’s IP is included.
A minimal SPF record looks like this:
v=spf1 include:_spf.google.com include:sendgrid.net ip4:203.0.113.10 -all
The v=spf1 prefix identifies the record type. Each mechanism (include:, ip4:, a, mx) specifies a source of authorized senders. The qualifier at the end — -all, ~all, or ?all — determines what happens to messages that don’t match any mechanism: hard fail, soft fail, or neutral. Use -all in production. Soft fail (~all) tells receivers “probably not authorized” but many treat it as permissive. Hard fail is the only signal that actually enforces your policy.
The 10-Lookup Limit
SPF imposes a maximum of 10 DNS lookups during evaluation. This is a hard limit defined in RFC 7208, not a guideline. Every include:, a, mx, redirect=, and exists mechanism triggers a lookup. The ip4: and ip6: mechanisms do not, because they specify IP addresses directly.
The problem becomes real quickly. A single include:_spf.google.com may itself include sub-references, consuming 3–4 lookups internally. Add SendGrid, Mailchimp, a transactional email provider, and your own mail server, and you’re at the limit before you’ve finished your onboarding checklist. Exceeding 10 lookups causes SPF to return a permerror, which is treated the same as a hard fail.
Solutions: flatten your SPF record periodically using a tool like dmarcian’s SPF Surveyor or MXToolbox. This means replacing include: chains with their resolved IP ranges as static ip4: blocks. The tradeoff is that flattened records require maintenance when your providers update their IP ranges. Some providers offer SPF macro syntax or dedicated flattening services to automate this, which is worth paying for if you have more than three sending services.
Common SPF Mistakes
- Two SPF records on the same domain. RFC 7208 requires that exactly one SPF record exist per hostname. Multiple TXT records beginning with
v=spf1cause apermerror. When adding a new sending service, edit the existing record — do not create a second one. - SPF on the wrong domain. SPF validates the envelope sender (
MAIL FROM), not theFrom:header the user sees. If your transactional provider sends frombounce.yourapp.com, the SPF record needs to exist onbounce.yourapp.com, not just onyourapp.com. - Forgetting subdomain senders. SPF is not inherited by subdomains. If you send from
notifications.example.com, that subdomain needs its own SPF record. - Using
~allpermanently. Soft fail is appropriate during initial testing, not as a permanent posture. Receivers that honor~allas “probably spam” will eventually train their filters to treat your domain accordingly.
DKIM: Cryptographic Signing That Survives Forwarding
DKIM (DomainKeys Identified Mail) addresses a limitation of SPF: SPF breaks on email forwarding because the forwarding server’s IP is not in the original sender’s SPF record. DKIM instead attaches a cryptographic signature to the message headers and body, allowing any receiver downstream in the delivery chain to verify the signature using a public key published in DNS.
The sending server generates a signature using a private key and inserts it as a DKIM-Signature header. The signature covers selected headers (typically From:, Subject:, Date:, Message-ID:) and a hash of the message body. The receiving server retrieves the corresponding public key from a TXT record at [selector]._domainkey.[domain] and verifies the signature. If the message was modified in transit or the key doesn’t match, verification fails.
Selectors and Key Management
The selector in the DKIM DNS path allows a domain to publish multiple DKIM keys simultaneously. This is essential for key rotation. When you rotate a DKIM key, you publish the new key under a new selector, configure your sending infrastructure to sign with the new key, and only after some propagation delay remove the old selector. This prevents in-flight messages signed with the old key from failing verification during the rotation window.
A common selector naming convention is to embed a date or version: k1._domainkey, k2._domainkey, or 2024q1._domainkey. The specific naming doesn’t matter; what matters is that it’s unique and you can track which key corresponds to which selector across your sending infrastructure.
Key length matters. RSA-1024 is deprecated and should not be used — Gmail began rejecting it, and other major providers followed. RSA-2048 is the current minimum. Ed25519 is more compact and computationally efficient but has spotty support in older receiving software. If your ESP supports both, publish an Ed25519 key and a 2048-bit RSA key on different selectors; the sending server can be configured to try Ed25519 first.
Practical DKIM Mistakes
- Not signing all headers in the From. DKIM signatures that don’t include the
From:header provide weak protection. Most modern signing configurations include it by default, but verify this in your ESP’s DKIM configuration panel. - Setting DKIM key TTL too high before rotation. If your DKIM TXT record has a TTL of 86400 and you start signing with a new key, receivers may cache the old key for 24 hours and fail to verify new signatures. Drop the TTL to 300 before rotating.
- Using a third-party provider without verifying DKIM is enabled. Several ESPs enable SPF automatically but require manual DKIM configuration through their dashboard. Check that DKIM signing is active, not just SPF delegation.
DMARC: Policy, Alignment, and Visibility
DMARC (Domain-based Message Authentication, Reporting, and Conformance) does two things: it ties SPF and DKIM to the From: header domain through alignment requirements, and it tells receivers what to do with messages that fail that alignment check. It also enables aggregate and forensic reporting that gives domain owners visibility into how their domain is being used across the internet.
The DMARC record is a TXT record published at _dmarc.[domain]:
v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; ruf=mailto:dmarc-forensic@example.com; pct=100; adkim=s; aspf=s
Policy Levels
| Policy | Effect | When to Use |
|---|---|---|
p=none |
Monitor only. No action taken on failing mail. | Initial deployment. Collect reports before enforcing. |
p=quarantine |
Failing mail goes to spam/junk folder. | After confirming legitimate mail passes. Intermediate enforcement. |
p=reject |
Failing mail is rejected at the SMTP layer. | Full enforcement. Target state for all sending domains. |
The path from none to reject should be deliberate. Start at none, set up aggregate report processing, and spend two to four weeks understanding what sources are sending mail claiming your domain. Only after you’ve confirmed all legitimate senders are authenticated should you move to quarantine, and then to reject.
Alignment Modes
DMARC alignment requires that the domain passing SPF or DKIM matches the domain in the From: header. Relaxed alignment (aspf=r, the default) allows organizational domain matching — mail.example.com aligns with example.com. Strict alignment (aspf=s) requires an exact match.
Strict alignment is the more secure posture but requires more careful configuration. If your transactional provider sends from a subdomain of your domain for bounce tracking purposes, strict SPF alignment will fail. Know what your sending infrastructure actually uses before setting strict mode.
Aggregate Reports
The rua= tag specifies where aggregate reports (XML files summarizing authentication results across all messages claiming your domain) should be sent. These reports are the only reliable way to discover unauthorized use of your domain and to confirm that all legitimate sending sources are properly authenticated.
Processing raw DMARC XML is impractical at any volume. Use a DMARC reporting service: dmarcian, Valimail, or Postmark’s DMARC monitoring. All offer free tiers sufficient for most indie developers and small teams. The value is the visibility — you’ll discover marketing automation tools, CRM platforms, and legacy mail scripts sending from your domain that your current SPF record doesn’t cover.
The Google and Yahoo 2024 Requirements
In February 2024, Google and Yahoo enforced new requirements for bulk senders (those sending more than 5,000 messages per day to Gmail or Yahoo accounts). The requirements codified what had been best-practice guidance for years:
- SPF or DKIM must pass (both is strongly recommended)
- DMARC must be published at minimum
p=none - The
From:domain must align with either SPF or DKIM - Unsubscribe headers (
List-UnsubscribeandList-Unsubscribe-Post) are required for marketing mail - One-click unsubscribe must be honored within two days
- Spam complaint rates must stay below 0.3% (0.1% target)
The practical effect for transactional email was that many senders who had neglected DMARC suddenly found deliverability degrading to Gmail addresses. The threshold of 5,000 messages per day is lower than it sounds — a SaaS with a few thousand active users easily crosses it through password resets, notifications, and weekly digests combined. Even senders below this threshold observed correlation between DMARC absence and increased spam classification.
The correct response is not to add DMARC at p=none purely for checkbox compliance. The correct response is to treat this as the forcing function to actually reach p=reject.
Transactional Email Services: An Honest Comparison
The choice of ESP (Email Service Provider) affects deliverability, developer experience, and operational complexity. The major options for transactional email each have genuine tradeoffs worth understanding.
Resend
Resend launched in 2023 targeting developers, with a React Email integration and an API that feels modern. DKIM signing is handled automatically. Their deliverability on shared IPs is good for most use cases, and their dashboard provides per-email logs that are genuinely useful for debugging. The weakness: they’re newer, so their shared IP reputation history is shallower than Postmark or SES, and their dedicated IP offering has a higher minimum volume requirement relative to cost. Strong choice for new projects where developer experience matters and volume is under 100,000 emails per month.
Postmark
Postmark has the best reputation for transactional deliverability among shared IP providers. They built their business around strict sender policies — they reject bulk and marketing email, keeping their shared IPs clean for transactional use. Their bounce processing and spam complaint handling are thorough. The API is well-documented. More expensive than SES per message, but for applications where password-reset deliverability is existential, the deliverability premium is worth it.
Amazon SES
SES is the price leader. At $0.10 per 1,000 messages and effectively unlimited throughput, it’s the default choice for high-volume senders building on AWS infrastructure. The tradeoff is that SES shared IPs are mixed-use — marketing and transactional senders coexist — so shared IP reputation is less predictable than Postmark. SES rewards senders who configure dedicated IPs and manage their own reputation carefully. The configuration overhead is higher: DKIM setup requires manual DNS record creation through SES console or CDK, and the sandbox mode requirement on new accounts means you need to explicitly request production access. For teams already on AWS with >500k emails/month, SES is hard to argue against.
SendGrid
SendGrid (now Twilio SendGrid) is the incumbent. It works, the API is widely documented, and it has broad integration support across platforms. The honest assessment: their shared IP deliverability has historically had more variability than Postmark, their pricing tiers are less transparent than they appear, and their support response times are slower than the alternatives for lower-tier customers. There’s no reason to migrate away from SendGrid if it’s working, but there are better defaults for new projects.
Domain Warm-Up: Why New Domains Need It
Receiving servers and reputation networks have no history for a new domain or a new sending IP. No history is treated as suspicious history. Sending 10,000 emails on day one from a new domain will trigger rate limiting, spam classification, or outright blocking from major providers regardless of authentication setup.
Warm-up involves gradually increasing sending volume over two to six weeks, starting with your most engaged users (those most likely to open and interact) and only high-priority transactional mail. A rough schedule:
- Week 1: 50–200 messages per day, highest-engagement recipients only
- Week 2: 500–1,000 messages per day, expanding to confirmed-opted-in users
- Week 3–4: 5,000–10,000 messages per day, full transactional volume
- Week 5–6: Full marketing volume if applicable
Monitor spam complaint rates throughout. A rate above 0.1% during warm-up indicates a list hygiene problem that will worsen, not improve, as volume scales. Google Postmaster Tools provides complaint rate data for Gmail recipients and should be your primary signal during warm-up.
Dedicated IP vs. Shared IP
Shared IPs mean your sending reputation is partially a function of other senders on the same IP range. With reputable ESPs, shared IPs for transactional mail are generally fine — the ESP actively polices their sender base. The argument for dedicated IPs is that you control your own reputation entirely.
Dedicated IPs make sense when:
- Your sending volume is sufficient to maintain a warm IP (generally above 50,000 emails per month with consistent daily volume). An inconsistently used dedicated IP is worse than a reputable shared IP.
- You have the operational capacity to monitor IP reputation, handle blocklist listings proactively, and manage warm-up when adding new IPs.
- Your deliverability requirements justify the additional cost (typically $20–30/month per IP with most ESPs).
Below 50,000 monthly emails, a reputable shared IP on Postmark or Resend outperforms a dedicated IP managed by a team without deliverability expertise. The reputation that comes with a well-maintained shared pool is a feature, not a limitation.
Monitoring Tools
Google Postmaster Tools provides domain reputation, IP reputation, spam rate, and authentication pass rates for mail delivered to Gmail. Free. Setup requires adding a TXT verification record to your domain. If you send any volume to Gmail addresses, this is non-negotiable. The domain reputation dashboard is the most direct signal you have for how Gmail is classifying your domain-level reputation.
MXToolbox is the go-to for quick DNS record inspection and blacklist checks. Their SuperTool checks SPF, DKIM, DMARC, and MX records in one view. The blacklist monitor alerts when your sending IPs appear on any major blocklist. The free tier is sufficient for most use cases.
dmarcian provides DMARC aggregate report parsing, SPF surveyor for flattening analysis, and domain health checks. Their DMARC management workflow is the clearest of the dedicated tools. The free tier limits the number of domain records processed per month, but is viable for domains under 100,000 monthly sends.
Mail-Tester (mail-tester.com) is useful during initial setup. Send a test message to their unique address and receive a score with specific diagnostic feedback on SPF, DKIM, DMARC, content analysis, and header hygiene. Not a substitute for ongoing monitoring but helpful for initial validation.
When Everything Is Configured Correctly But Emails Still Go to Spam
This is the most frustrating class of deliverability problem, because the solution space shifts from protocol configuration to reputation management. Authentication passing is a prerequisite for inbox placement, not a guarantee.
Diagnose in this order:
- Check Google Postmaster Tools domain reputation. A “Low” or “Bad” rating means Gmail has history with your domain beyond individual message signals. This is the most likely culprit for persistent spam classification despite passing authentication.
- Check IP blacklist status via MXToolbox. An IP on Spamhaus, SORBS, or another major blocklist will cause widespread delivery failure. Dedicated IP holders need to monitor this actively.
- Examine spam complaint rates. If your complaint rate exceeds 0.1% on Gmail or Yahoo, spam classification follows algorithmically regardless of authentication status. The fix is list hygiene, not DNS configuration.
- Verify DMARC alignment, not just pass. SPF passing but DMARC misaligned (because the
From:domain doesn’t match the SPF-passing envelope sender) can cause classification issues even when individual mechanisms pass. Read theAuthentication-Results:header on a delivered message to see exactly what passed and what aligned. - Examine content and sending patterns. Very low open rates signal to mailbox providers that recipients don’t want the mail. Cleaning lists, sunsetting unengaged subscribers, and targeting mail to users with demonstrated engagement is the long-term fix for reputation recovery.
Deliverability problems that persist after confirming clean authentication and IP reputation are almost always a list quality issue. Send less mail, to more engaged recipients, and reputation improves. There is no technical shortcut around this.
Authentication setup is a solved problem with well-defined correct answers. The gap between developers who have it configured and developers who have it configured correctly — strict SPF with maintained lookup counts, DKIM with rotation-ready selector management, DMARC progressing toward p=reject with aggregate report visibility — is where inbox placement is actually won. Get the protocols right, pick a transactional provider whose shared IP reputation matches your use case, and treat deliverability monitoring as an ongoing operational concern rather than a one-time setup task.
Key Takeaways
- SPF, DKIM, and DMARC each address a different authentication question. All three are required. None substitutes for the others.
- The SPF 10-lookup limit is a real operational constraint, not an edge case. Monitor and flatten records as sending infrastructure grows.
- DMARC at
p=noneis a starting point.p=rejectis the destination. The path requires aggregate report monitoring to confirm all legitimate senders are authenticated before enforcing. - Google and Yahoo’s 2024 requirements are minimum baseline — they describe the floor, not the ceiling.
- Postmark for reliability, SES for volume and cost, Resend for developer experience — each has genuine strengths.
- Dedicated IPs require sufficient volume and operational attention to outperform a reputable shared pool.
- Persistent spam classification after passing authentication is almost always a list hygiene or sending reputation problem, not a DNS problem.
Frequently Asked Questions
Do I need all three — SPF, DKIM, and DMARC?
Yes. SPF alone authenticates the envelope sender but not the visible From: address. DKIM alone provides no policy signal for receivers on what to do with unauthenticated mail. DMARC ties them to the From: domain and provides policy enforcement. Google’s 2024 requirements make DMARC mandatory for bulk senders, and the trend is toward requiring it across all sending categories.
How long does it take for SPF and DKIM changes to propagate?
DNS propagation depends on TTL settings and resolver caching. With a TTL of 3600 (one hour), plan for up to an hour before changes are globally visible. Reducing TTL to 300 seconds 24 hours before making changes minimizes the propagation window. After changes are confirmed globally via MXToolbox or dnschecker.org, restore the TTL to its normal value.
What DMARC policy should I start with?
Start with p=none and configure aggregate report delivery (rua= tag) to a mailbox you actually monitor or a DMARC reporting service. After two to four weeks of report analysis confirming all legitimate senders pass authentication, move to p=quarantine. After another monitoring period with no legitimate mail landing in quarantine, move to p=reject.
My transactional provider sets up DKIM automatically — do I still need to do anything?
Verify the setup. Many providers add CNAME records pointing to their own DKIM keys, which means they’re signing on your behalf using their infrastructure. This passes DKIM verification but means the provider controls the signing key. For higher-security applications, consider whether you want to own your own DKIM keys by generating them independently and configuring the provider to use them. For most use cases, the provider-managed CNAME approach is practical and acceptable.
Can I use the same domain for both marketing and transactional email?
You can, but separating them onto different subdomains (mail.example.com for transactional, news.example.com for marketing) is the better architecture. Marketing email generates higher complaint rates than transactional email by nature. Subdomain separation means a marketing campaign with a high complaint rate doesn’t damage the transactional sending reputation. Both subdomains need their own SPF, DKIM, and DMARC records.