Emails Going to Spam? How to Set Up SPF, DKIM, and DMARC Correctly
Complete guide to email authentication. Set up SPF, DKIM, and DMARC DNS records to stop your emails from landing in spam.
TL;DR
If your emails are landing in spam, the most likely cause is missing or misconfigured email authentication. You need three DNS TXT records — SPF (which servers may send for your domain), DKIM (a cryptographic signature proving the email wasn't tampered with), and DMARC (a policy telling receivers what to do when SPF/DKIM fail). Setting up all three correctly will dramatically improve your deliverability and protect your domain from spoofing. This guide walks you through every step with real DNS records and commands.
Prerequisites
- Access to your domain's DNS management (e.g., Cloudflare, Route 53, your registrar's panel)
- Knowledge of which mail service sends email on behalf of your domain (Google Workspace, Microsoft 365, your own server, transactional services like Mailchimp or SendGrid)
- A terminal with
digornslookupavailable - Admin access to your mail server or mail provider's console
Why Emails Land in Spam
Modern email receivers (Gmail, Outlook, Yahoo, etc.) use a trust-based model. When an email arrives claiming to be from you@yourdomain.com, the receiving server asks three questions:
- Is this server allowed to send for this domain? (SPF)
- Is the message cryptographically signed by this domain? (DKIM)
- What does the domain owner want me to do if checks fail? (DMARC)
If you have no authentication records, there is no way to distinguish your legitimate email from a spammer forging your address. Receivers default to distrust — your mail goes to spam or gets rejected entirely.
SPF — Sender Policy Framework
What It Does
SPF is a DNS TXT record on your domain that lists every IP address and mail server authorized to send email on your behalf. When a receiver gets an email from your domain, it checks the sending server's IP against your SPF record.
Creating Your SPF Record
An SPF record is a single TXT record on your root domain (@ or yourdomain.com). Here are real-world examples:
Google Workspace only:
v=spf1 include:_spf.google.com ~all
Microsoft 365 only:
v=spf1 include:spf.protection.outlook.com ~all
Google Workspace + SendGrid + a dedicated server:
v=spf1 include:_spf.google.com include:sendgrid.net ip4:203.0.113.50 ~all
Syntax breakdown:
v=spf1— required version tag, must come firstinclude:domain— authorize another domain's SPF record (delegates lookup)ip4:x.x.x.x— authorize a specific IPv4 addressip6:xxxx::xxxx— authorize a specific IPv6 addressa— authorize the IP(s) in your domain's A recordmx— authorize the IP(s) of your MX servers~all— soft fail everything else (recommended starting point)-all— hard fail everything else (stricter, use once you're confident)
Common SPF Mistakes
Multiple SPF records: You may only have one SPF TXT record per domain. Two records will cause a permanent error (permerror) and SPF fails entirely. Merge them into one.
# WRONG — two separate TXT records:
v=spf1 include:_spf.google.com ~all
v=spf1 include:sendgrid.net ~all
# CORRECT — one combined record:
v=spf1 include:_spf.google.com include:sendgrid.net ~all
Too many DNS lookups: SPF allows a maximum of 10 DNS lookups (includes, a, mx, redirect, exists mechanisms each count as one lookup). Exceeding this limit causes a permerror. Check your count:
dig +short TXT _spf.google.com
# This itself includes more domains — each one counts toward your 10
Use kitterman.com/spf/validate.html to check your lookup count. If you exceed 10, consider using an SPF flattening service or replacing include: with explicit ip4: entries for services with stable IPs.
Verify Your SPF Record
dig TXT yourdomain.com +short | grep spf
DKIM — DomainKeys Identified Mail
What It Does
DKIM adds a cryptographic signature to each outgoing email. The receiving server retrieves your public key from DNS and verifies the signature. This proves the email was actually sent by an authorized system and was not modified in transit.
DKIM DNS Record Format
DKIM records are TXT records at selector._domainkey.yourdomain.com. The selector is a label chosen by you or your provider.
# Example DKIM record:
# Host: google._domainkey.yourdomain.com
# Type: TXT
# Value:
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2K4P...longbase64string...
Enabling DKIM in Google Workspace
- Go to Google Admin Console → Apps → Google Workspace → Gmail → Authenticate email
- Select your domain and click Generate New Record
- Choose a DKIM key bit length (2048-bit recommended)
- Google gives you a TXT record value with selector
google - Add the TXT record in your DNS:
google._domainkey.yourdomain.com - Wait for DNS propagation (up to 48h, usually minutes)
- Return to Admin Console and click Start Authentication
Enabling DKIM in Microsoft 365
- Go to Microsoft 365 Defender → Email & collaboration → Policies → DKIM
- Select your domain
- Microsoft provides two CNAME records to add:
# CNAME Record 1:
Host: selector1._domainkey.yourdomain.com
Points to: selector1-yourdomain-com._domainkey.yourtenant.onmicrosoft.com
# CNAME Record 2:
Host: selector2._domainkey.yourdomain.com
Points to: selector2-yourdomain-com._domainkey.yourtenant.onmicrosoft.com
- After DNS propagation, toggle DKIM signing to Enabled in the portal
Enabling DKIM on a Generic Mail Server (OpenDKIM)
# Install OpenDKIM
sudo apt install opendkim opendkim-tools
# Generate a key pair
sudo opendkim-genkey -s mail -d yourdomain.com -b 2048
# This creates mail.private (private key) and mail.txt (DNS record)
cat mail.txt
# Add the contents as a TXT record at mail._domainkey.yourdomain.com
# Configure /etc/opendkim.conf
Selector mail
Domain yourdomain.com
KeyFile /etc/opendkim/keys/yourdomain.com/mail.private
# Restart and integrate with Postfix
sudo systemctl restart opendkim
# In /etc/postfix/main.cf add:
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
Verify Your DKIM Record
# Replace 'google' with your selector
dig TXT google._domainkey.yourdomain.com +short
Common DKIM Mistakes
- Wrong selector: If you query the wrong selector name, the lookup fails. Check email headers (
DKIM-Signature: s=selector) to find the correct one. - Record too long: DNS TXT records have a 255-character string limit. Long DKIM keys must be split into multiple quoted strings. Most DNS providers handle this automatically, but if you paste manually, ensure proper splitting.
- Forgot to enable signing: Adding the DNS record is not enough — you must also enable DKIM signing in your mail provider's admin panel.
DMARC — Domain-based Message Authentication
What It Does
DMARC ties SPF and DKIM together. It tells receiving servers: (a) check that SPF or DKIM passes and aligns with the From: domain, and (b) here is what to do when it fails (nothing, quarantine, or reject). DMARC also enables reporting so you can see who is sending email as your domain.
Creating Your DMARC Record
DMARC is a TXT record at _dmarc.yourdomain.com.
Phase 1 — Monitoring (start here):
v=DMARC1; p=none; rua=mailto:dmarc-reports@yourdomain.com; ruf=mailto:dmarc-forensic@yourdomain.com; fo=1;
This tells receivers to send you aggregate reports (rua) and forensic reports (ruf) without affecting delivery. Monitor for 2–4 weeks.
Phase 2 — Quarantine:
v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc-reports@yourdomain.com;
Quarantine 25% of failing emails. Increase pct gradually to 100 as you gain confidence.
Phase 3 — Reject:
v=DMARC1; p=reject; rua=mailto:dmarc-reports@yourdomain.com; adkim=s; aspf=s;
This is the gold standard. adkim=s and aspf=s enforce strict alignment (the domain in the From: header must exactly match SPF/DKIM domains, not just organizational match).
DMARC Tag Reference
v=DMARC1— version (required)p=none|quarantine|reject— policy (required)rua=mailto:...— aggregate report destinationruf=mailto:...— forensic report destinationpct=0-100— percentage of mail subject to policy (default 100)adkim=r|s— DKIM alignment: relaxed (default) or strictaspf=r|s— SPF alignment: relaxed (default) or strictfo=0|1|d|s— failure reporting options (1 = report if any mechanism fails)sp=none|quarantine|reject— subdomain policy
Reading DMARC Reports
Aggregate reports are XML files sent daily by receiving mail servers. They are not human-friendly. Use a free service to parse them:
- Postmark DMARC Tool (free weekly digests)
- DMARC Analyzer
- Report URI
Look for: sources sending as your domain that you don't recognize, SPF/DKIM failure rates, and alignment issues.
Verify Your DMARC Record
dig TXT _dmarc.yourdomain.com +short
Testing Your Configuration
Command-Line Checks
# Check all three records at once:
dig TXT yourdomain.com +short # SPF
dig TXT google._domainkey.yourdomain.com +short # DKIM
dig TXT _dmarc.yourdomain.com +short # DMARC
# Check MX for good measure:
dig MX yourdomain.com +short
Online Tools
- mail-tester.com — Send an email to their generated address, get a 1–10 score with detailed breakdown. Aim for 9+.
- MXToolbox — Enter your domain, run SPF/DKIM/DMARC checks, blacklist lookups.
- dmarcian.com — DMARC record inspector and policy analyzer.
- Google Admin Toolbox Check MX — toolbox.googleapps.com/apps/checkmx/
Check Email Headers
Send a test email to a Gmail account, open it, click the three dots → "Show original". Look for:
SPF: PASS with IP 203.0.113.50
DKIM: PASS with domain yourdomain.com
DMARC: PASS
All three should show PASS.
Google & Yahoo 2024 Sender Requirements
Since February 2024, Google and Yahoo enforce stricter rules for bulk senders (sending 5,000+ messages/day to their users):
- SPF and DKIM are mandatory for all senders
- DMARC with at least p=none is required for bulk senders
- One-click unsubscribe (List-Unsubscribe header) for marketing/promotional email
- Spam complaint rate below 0.3% (monitored via Google Postmaster Tools)
- Valid forward and reverse DNS for sending IPs
- TLS encryption for SMTP transmission
Even if you send fewer than 5,000 emails/day, implementing all three protocols is now considered baseline hygiene. Domains without DMARC will increasingly see deliverability issues across all major providers.
Troubleshooting
SPF Fails Despite Correct Record
- Check for multiple SPF records:
dig TXT yourdomain.com +short | grep spf— you should see exactly one. - Count your DNS lookups. Each
include:,a,mx, andredirectcounts. Nested includes count too. - Verify the sending IP is actually covered. Check email headers for the originating IP and trace it through your SPF includes.
DKIM Fails
- Confirm the selector matches. Check the
s=value in the DKIM-Signature header of a sent email. - Ensure the DNS record is at the correct hostname:
selector._domainkey.yourdomain.com - Check for key truncation. Some DNS panels silently truncate long TXT values. Verify the full key with
dig. - If using CNAME-based DKIM (Microsoft 365), ensure the CNAME target resolves correctly.
DMARC Reports Show Failures From Legitimate Sources
- A third-party service (CRM, helpdesk, newsletter tool) is sending as your domain but isn't in your SPF record or doesn't sign with your DKIM key.
- Fix: Add the service to your SPF
include:list and configure DKIM signing through the service's dashboard.
Emails Still Going to Spam After All Three Pass
Authentication is necessary but not sufficient. Also check:
- IP/domain reputation (check blacklists at MXToolbox Blacklists)
- Email content quality (spammy language, image-heavy, suspicious links)
- Sending volume and patterns (sudden spikes trigger filters)
- Missing
List-Unsubscribeheader on marketing emails
Prevention & Maintenance
Set Up Monitoring From Day One
- Always include
rua=in your DMARC record so you receive reports - Use a DMARC report processing service — don't let XML reports pile up unread in a mailbox
- Register at Google Postmaster Tools for spam rate and reputation data
Maintain a Sender Inventory
Keep a documented list of every service that sends email as your domain. When onboarding a new SaaS tool, immediately add it to your SPF record and configure DKIM. Common ones people forget:
- CRM systems (HubSpot, Salesforce)
- Helpdesk tools (Zendesk, Freshdesk)
- Transactional email (SendGrid, Mailgun, Amazon SES)
- Marketing platforms (Mailchimp, ActiveCampaign)
- Invoicing/accounting software
Gradual DMARC Enforcement
Never jump straight to p=reject. Follow the phased approach: p=none → monitor reports → p=quarantine with pct=25 → increase percentage → p=reject. This process should take 4–8 weeks minimum.
Regular Audits
Schedule quarterly checks:
# Quick health check script:
echo "=== SPF ==="
dig TXT yourdomain.com +short | grep spf
echo "=== DKIM ==="
dig TXT google._domainkey.yourdomain.com +short
echo "=== DMARC ==="
dig TXT _dmarc.yourdomain.com +short
echo "=== MX ==="
dig MX yourdomain.com +short
Subdomain Policy
Don't forget subdomains. Attackers often spoof subdomains (billing.yourdomain.com) that lack their own DMARC records. Use the sp=reject tag in your root DMARC record, or publish individual DMARC records for critical subdomains.
Need Expert Help?
Want it done right in 30 minutes? €39, I configure your DNS records.
Book Now — €39100% money-back guarantee