Google and Microsoft made all three mandatory in 2024. If your domain is missing any one of them, your cold emails are being rejected or spam-filtered before your subject line is ever seen. This guide sets them up correctly.
Run these commands to instantly check your domain. Replace yourdomain.com with your actual domain:
# Check SPF
dig TXT yourdomain.com | grep spf
# Check DMARC
dig TXT _dmarc.yourdomain.com
# Check DKIM (replace 'selector' with your actual DKIM selector)
dig TXT selector._domainkey.yourdomain.com
A DNS TXT record that lists which mail servers are authorised to send email from your domain. When a receiving server gets an email claiming to be from yourdomain.com, it checks your SPF record. If the sending server IP is not listed, the email fails SPF.
Adds a cryptographic signature to every email. The receiving server fetches your public key from DNS and uses it to verify the signature. If the email was modified in transit, the signature fails. DKIM proves the email was genuinely sent by you and was not tampered with.
A policy record that tells receiving servers what to do when SPF or DKIM checks fail: monitor only (p=none), send to spam (p=quarantine), or reject outright (p=reject). Also enables DMARC reports - XML summaries of your sending activity sent to your monitoring email.
SPF is a single DNS TXT record added to your domain. It lists the IP addresses and mail services allowed to send from your domain. You should have exactly one SPF record - multiple SPF records cause failures.
# Basic SPF record (replace with your actual email provider)
v=spf1 include:_spf.google.com ~all
# If sending via multiple providers (e.g. Google + Mailgun):
v=spf1 include:_spf.google.com include:mailgun.org ~all
# Common provider includes:
# Google Workspace: include:_spf.google.com
# Microsoft 365: include:spf.protection.outlook.com
# Instantly/Smartlead: include:spf.instantlyai.com (if custom domain)
# SendGrid: include:sendgrid.net
# Mailgun: include:mailgun.org
# Amazon SES: include:amazonses.com
| Qualifier | Meaning | Use |
|---|---|---|
| +all | Pass - allow all senders | Never use |
| ~all | SoftFail - allow but mark | Good default |
| -all | Fail - reject unlisted senders | Use after confirming all senders are listed |
| ?all | Neutral - no policy | Avoid - same as no record |
include: directive typically costs 1 lookup. If you have many sending services, you may hit the limit - use an SPF flattening service or consolidate to a single ESP.
DKIM keys are generated by your email provider, not manually created. Go to your provider settings and find the DKIM setup section. They will give you a selector name and a public key to add to your DNS.
Admin > Apps > Google Workspace > Gmail > Authenticate Email. Generate new record. Add the provided TXT record to DNS under: [selector]._domainkey.yourdomain.com
Admin Center > Settings > Domains > [your domain] > DNS records. Microsoft adds DKIM records automatically for M365 domains. Verify under: selector1._domainkey.yourdomain.com
Domain settings > Email Authentication > Generate DKIM. Add the TXT record provided to your DNS at: [selector]._domainkey.yourdomain.com
Settings > Sender Authentication > Domain Authentication. Follow the wizard. SendGrid generates two CNAME records (not TXT) for DKIM.
# Your DKIM record format in DNS:
# Type: TXT
# Name: [selector]._domainkey.yourdomain.com
# Value: v=DKIM1; k=rsa; p=[your-public-key]
# Example (key shortened):
# Type: TXT
# Name: google._domainkey.yourdomain.com
# Value: v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC...
DMARC is a single TXT record added at _dmarc.yourdomain.com. Always start with p=none to collect reports first - never jump straight to p=reject.
p=none
v=DMARC1; p=none; rua=mailto:[email protected]
No emails are blocked. DMARC reports are collected and sent to your rua address. Analyse reports to find all sending sources before enforcing anything.
p=quarantine
v=DMARC1; p=quarantine; pct=25; rua=mailto:[email protected]
Failing emails are sent to spam for 25% of traffic (pct=25). Increase pct gradually as you confirm no legitimate email is failing. Monitor reports closely.
p=reject
v=DMARC1; p=reject; rua=mailto:[email protected]
Failing emails are rejected outright. Only move here when you are confident all legitimate sending sources pass SPF and DKIM.
| Tag | Purpose | Recommended value |
|---|---|---|
| p | Policy for failing emails | none > quarantine > reject |
| rua | Aggregate report email | mailto:[email protected] |
| pct | % of mail policy applies to | 25 > 50 > 100 during rollout |
| sp | Policy for subdomains | reject (if you do not send from subdomains) |
| adkim | DKIM alignment mode | r (relaxed) - usually fine |
| aspf | SPF alignment mode | r (relaxed) - usually fine |
DNS only allows one SPF record. If you add a second, receivers evaluate the first and ignore the second - or treat both as invalid. Combine all includes into a single record.
Going straight to reject without monitoring will block legitimate emails from sources you did not know about (a CRM tool, an HR system, a transactional email provider). Always start at p=none for 2-4 weeks.
Providers sometimes give you a DKIM record but you add it to the wrong subdomain. The full DKIM record name is [selector]._domainkey.yourdomain.com - confirm both the selector name and the _domainkey portion are correct.
Cold email teams often send from multiple domains (yourdomain.com, yourdomain-outreach.com, etc.). Each domain needs its own SPF, DKIM, and DMARC records. The main company domain records do not cover secondary sending domains.
DNS changes can take 24-48 hours to propagate globally. Do not test immediately after adding records - wait at least 30 minutes and use a TTL-aware checker like MXToolbox.
SPF, DKIM, and DMARC prove to ISPs that your emails are authentic. They do not prevent bounces from invalid addresses. A verified domain sending to an unverified list will still accumulate bounce damage. Authentication and list verification work together - one without the other leaves deliverability gaps.
Ayoub built BounceZero's 5-stage validation pipeline, its dedicated BGP-announced IP infrastructure, and the Patroni HA PostgreSQL cluster behind every verification. Previously built high-volume email delivery infrastructure. Trained at 1337 Benguerir (École 42 network, 2019). Open-source: bgp_analyzer.
Provider behaviour, DNS setup, warm-up, and inbox placement
SPF syntax, provider includes, 10-lookup limit fix, ~all vs -all explained
DNS records, DMARC policy progression, verification commands, cold email setup
How to warm up a new email domain in 2026: the right tool, a realistic 30-day timeline
Benchmarks, Apple MPP inflation explained, and what metrics to track instead
12 steps to keep hard bounce rate under 2% - prevention + recovery
Hard vs soft bounces, ISP thresholds, 6-step reduction plan, benchmarks, suppression list management
Continue through related topics