Email Authentication for Developers: SPF, DKIM, and DMARC Explained
Master email authentication protocols. Learn how SPF, DKIM, and DMARC prevent spoofing and improve deliverability for your applications.
Why Email Authentication Matters
Email spoofing is one of the oldest and most effective attack vectors. A malicious actor can send a message that appears to come from your domain, impersonating legitimate users or your application’s alerts. Without proper email authentication, your organization’s reputation suffers, users lose trust, and your messages land in spam folders.
Email authentication protocols—SPF (Sender Policy Framework), DKIM (DomainKeys Identified Mail), and DMARC (Domain-based Message Authentication, Reporting and Conformance)—form a three-layer defense that proves you own the domain sending the message. Together, they protect your brand, improve deliverability, and provide visibility into who’s sending mail on your behalf.
If you’re building applications that send transactional emails, newsletters, or alerts, understanding these protocols is essential. Major email providers (Gmail, Office 365, Yahoo) now enforce DMARC policies, making implementation not optional—it’s mandatory for reaching your users’ inboxes.
Understanding SPF (Sender Policy Framework)
What SPF Does
SPF is a DNS-based mechanism that specifies which mail servers are authorized to send email on behalf of your domain. When a recipient’s mail server receives an email, it performs an SPF check:
-
It extracts the domain from the email’s
Fromheader - It queries DNS for the SPF record of that domain
- It compares the sending IP address against the authorized list
- It returns a pass, fail, or soft-fail result
SPF is the first line of defense—it’s simple, widely supported, and quick to verify.
SPF Record Syntax
An SPF record is a DNS TXT record that begins with v=spf1. Here’s a typical example:
v=spf1 ip4:192.168.1.1 include:sendgrid.net include:_spf.google.com ~all
Breaking down the components:
-
v=spf1— SPF version (always v1) -
ip4:192.168.1.1— Authorizes a specific IPv4 address -
ip6:2001:db8::1— Authorizes a specific IPv6 address -
include:sendgrid.net— Includes the SPF records of another domain (common for SaaS email providers) -
a— Authorizes the A record (the domain’s own mail server IP) -
mx— Authorizes MX record IPs (mail exchange servers) -
ptr:mail.example.com— Authorizes based on reverse DNS (rarely used, not recommended) -
exists:%{i}.spf.example.com— Checks if a query returns an A record (advanced) -
~all— Soft fail (accept mail but mark as suspicious) for all unauthorized IPs -
-all— Hard fail (reject) for all unauthorized IPs
Practical SPF Setup
If your application sends email through a third-party service like SendGrid, Mailgun, or AWS SES, add their SPF include:
v=spf1 include:sendgrid.net include:_spf.google.com ~all
If you run your own mail server:
v=spf1 a mx ip4:203.0.113.5 ~all
This authorizes:
- Your domain’s A record IP
- Your MX record IPs
-
The explicit IP
203.0.113.5 - Soft-fails everything else
SPF Limitations
SPF has critical weaknesses:
-
Header forgery — SPF only checks the envelope
Fromaddress (used for routing), not the displayFromheader (what users see). An attacker can spoof the display header. - Forwarding breaks SPF — When mail is forwarded, the original sending IP no longer matches the forwarded domain.
- DNS lookup limit — SPF records can trigger at most 10 DNS lookups. Complex includes can exceed this and fail silently.
This is why DKIM and DMARC exist.
Understanding DKIM (DomainKeys Identified Mail)
What DKIM Does
DKIM cryptographically signs email messages using a public-key infrastructure. Instead of checking IPs, DKIM proves that a message was actually sent from your domain by attaching a digital signature.
The process:
- Your mail server generates an email
- It creates a hash of the message body and selected headers
- It encrypts the hash with a private key (stored securely on your server)
-
The signature is added as a
DKIM-Signatureheader - The recipient’s server retrieves your public key from DNS
- It decrypts the signature and verifies the hash
- If the hash matches, the message is authenticated
Un like SPF, DKIM authenticates the actual message content. It survives forwarding, because the signature remains attached.
DKIM Record Setup
DKIM requires two components: a private key (on your mail server) and a public key (published in DNS).
First, generate a key pair. Most email providers (SendGrid, Mailgun, AWS SES) generate this for you, but if you’re running your own mail server:
openssl genrsa -out dkim_private.pem 2048
openssl rsa -in dkim_private.pem -pubout -out dkim_public.pem
Extract the public key in DKIM format:
openssl rsa -in dkim_private.pem -pubout -outform PEM | sed '1d;$d' | tr -d '\n'
Publish the public key as a TXT record in DNS. The format is:
default._domainkey.example.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaGaK...."
Key parts:
-
default— The DKIM selector (you can have multiple selectors for key rotation) -
_domainkey— Required subdomain -
v=DKIM1— Version -
k=rsa— Key type -
p=...— The public key (base64-encoded)
Configuring Your Mail Server
If you use Postfix, add to /etc/postfix/main.cf:
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
milter_default_action = accept
Then run OpenDKIM:
apt-get install opendkim opendkim-tools
Configure /etc/opendkim.conf:
Socket inet:8891@localhost
KeyFile /etc/opendkim/dkim_private.pem
Selector default
Domain example.com
For SaaS Providers
If you use SendGrid, Mailgun, or AWS SES, they provide CNAME records or TXT records to add to your domain. For example, SendGrid provides:
mail.sendgrid.net CNAME example.sendgrid.net
default._domainkey.example.com CNAME example.sendgrid.net
Or a TXT record with the public key already included.
Understanding DMARC (Domain-based Message Authentication, Reporting and Conformance)
What DMARC Does
DMARC is a policy layer that sits on top of SPF and DKIM. It:
-
Aligns — Checks that the domain in the
Fromheader matches the domain in the SPF/DKIM authentication - Enforces — Specifies what the recipient should do if authentication fails (reject, quarantine, or monitor)
- Reports — Sends detailed reports about authentication results and failures
DMARC is powerful because it finally closes the header forgery loophole. Even if an attacker can forge the display From header, DMARC alignment checks that the authenticated domain matches.
DMARC Record Syntax
DMARC records are published as DNS TXT records under _dmarc.yourdomain.com:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=none; rua=mailto:[email protected]; ruf=mailto:[email protected]"
Key fields:
-
v=DMARC1— Version -
p=— Policy (required)-
none— Monitor only, don’t enforce -
quarantine— Fail messages to spam folder -
reject— Hard reject failures
-
-
rua=— Reporting URI for aggregate reports (sent daily) -
ruf=— Reporting URI for forensic reports (sent on failure) -
fo=— Failure reporting options (0=any,1=DKIM and SPF both fail,d=DKIM only,s=SPF only) -
aspf=— SPF alignment mode (r=relaxed,s=strict) -
adkim=— DKIM alignment mode (r=relaxed,s=strict) -
pct=— Percentage of messages to apply policy to (0-100, default 100) -
subdomain_policy=— Policy for subdomains
DMARC Alignment Modes
Relaxed alignment (default) — The authenticated domain is a parent domain of the From header domain:
From: [email protected]
SPF/DKIM authenticated domain: example.com
✓ PASSES relaxed alignment (mail.example.com is subdomain of example.com)
Strict alignment — The domains must match exactly:
From: [email protected]
SPF/DKIM authenticated domain: example.com
✗ FAILS strict alignment
Gradual DMARC Rollout
Don’t jump straight to p=reject. Start with monitoring:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=none; rua=mailto:[email protected]"
After a week, review the aggregate reports. Once you’ve fixed authentication issues, upgrade to quarantine:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=quarantine; pct=50; rua=mailto:[email protected]"
Gradually increase the percentage, then move to reject:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=reject; rua=mailto:[email protected]"
Getting Started: Step-by-Step Implementation
Step 1: Audit Your Current Setup
First, determine what’s currently sending email on your domain. Use our SPF Analyzer to validate existing records:
Examining: example.com
Current SPF: v=spf1 include:sendgrid.net ~all
Status: ✓ Valid syntax
DNS lookups: 2/10
Step 2: Publish an SPF Record
Identify all services sending mail on your behalf:
-
SendGrid? Add
include:sendgrid.net -
AWS SES? Add
include:amazonses.com -
Google Workspace? Add
include:_spf.google.com -
Your own mail server? Add
a mxorip4:203.0.113.5
Publish the combined record:
v=spf1 include:sendgrid.net include:_spf.google.com a mx ~all
Test using a tool like Kloubot’s DNS Lookup:
nslookup -type=TXT example.com
Step 3: Enable DKIM
If using a third-party service:
- Log into your provider’s dashboard
- Navigate to “Domain Authentication” or “DKIM Settings”
- Add your domain
- Copy the CNAME or TXT record they provide
- Publish to your DNS
- The provider will verify and enable DKIM
If self-hosting, install OpenDKIM and follow the configuration steps outlined above.
Step 4: Implement DMARC
Start with monitoring:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=none; rua=mailto:[email protected]; ruf=mailto:[email protected]"
Create mailboxes to receive reports. You’ll receive XML reports detailing:
- Which messages passed/failed SPF and DKIM
- Which IPs sent mail from your domain
- Authentication alignment results
Step 5: Review Reports and Iterate
Analyze aggregate reports to find:
- Legitimate senders you haven’t authorized
- Services that need SPF/DKIM configuration
- Alignment failures that need fixing
After a week, upgrade to quarantine with a phased rollout:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=quarantine; pct=25; rua=mailto:[email protected]"
Increase pct in increments of 25% weekly, monitoring for legitimate mail hitting spam. Once confident, move to reject:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=reject; rua=mailto:[email protected]"
Common Pitfalls and How to Avoid Them
Pitfall 1: SPF Record Too Complex
Problem: Each include:, a, mx, and other mechanism counts as one DNS lookup. Exceeding 10 lookups causes SPF to fail silently.
Example of too many includes:
v=spf1 include:sendgrid.net include:mailgun.org include:amazonses.com include:_spf.google.com include:sendkeys.io include:stripe.com include:twilio.com include:auth0.com include:mailchimp.com include:wordpress.com ~all
This can exceed the 10-lookup limit.
Solution: Consolidate includes. Create your own _spf.yourdomain.com record that includes other domains:
v=spf1 include:_spf.yourdomain.com ~all
_spf.yourdomain.com. 3600 IN TXT "v=spf1 include:sendgrid.net include:_spf.google.com include:amazonses.com ~all"
This uses only 1 lookup in the main record.
Pitfall 2: Misaligned DKIM Signatures
Problem: Your mail server signs with mail.example.com, but DMARC checks alignment with example.com.
Solution: Use strict alignment for DKIM:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=reject; adkim=s; aspf=s; rua=mailto:[email protected]"
Or ensure your mail server signs as the primary domain, not a subdomain.
Pitfall 3: Forwarding Breaks SPF
Problem: User forwards your email from their corporate domain. The forwarded message now comes from their mail server, not yours, breaking SPF.
Solution: SPF can’t be fixed for forwarding. This is why DKIM and DMARC exist—they survive forwarding. Ensure your DKIM signatures are correct, and recipients can verify authenticity even after forwarding.
Pitfall 4: Third-Party Senders Not Configured
Problem: Your support team uses Zendesk, your billing system uses Stripe, and your alerts come from PagerDuty—none are authorized in SPF.
Solution: Create a comprehensive audit:
# Check email logs to find unauthorized senders
grep "Return-Path:" /var/log/mail.log | cut -d'<' -f2 | cut -d'>' -f1 | sort | uniq
Add each service’s SPF include:
v=spf1 include:sendgrid.net include:zendesk.com include:stripe.com include:pagerduty.com ~all
Pitfall 5: Not Monitoring DMARC Reports
Problem: You publish DMARC but never read the reports.
Solution: Set up automated DMARC report aggregation. Services like Dmarcian, Valimail, or Agari parse reports and visualize failures. Or use a simple Python script:
import email
import zipfile
from io import BytesIO
def parse_dmarc_report(raw_email):
msg = email.message_from_string(raw_email)
for part in msg.walk():
if part.get_content_type() == "application/zip":
z = zipfile.ZipFile(BytesIO(part.get_payload(decode=True)))
for name in z.namelist():
with z.open(name) as f:
print(f.read().decode())
Testing and Validation
Use Online Tools
Validate your setup with:
- SPF Analyzer — Check SPF record validity and DNS lookup count
- DNS Lookup — Query TXT records directly
- Send a test email to mail-tester.com or appmailtest.com — These services receive your email and show SPF/DKIM/DMARC results
Example Test Email Output
SPF: PASS (192.168.1.1 is authorized by v=spf1 include:sendgrid.net ~all)
DKIM: PASS (Signature verification successful)
DMARC: PASS (DKIM alignment satisfied)
Spam Score: 0.0 / 10 (Excellent)
Command-Line Testing
Check SPF records:
nslookup -type=TXT example.com
Check DKIM public key:
nslookup -type=TXT default._domainkey.example.com
Check DMARC policy:
nslookup -type=TXT _dmarc.example.com
Verify DKIM signature on a received email (Gmail):
- Open the email
- Click “Show original”
-
Search for
DKIM-Signature - Look for authentication results headers
Why It Matters for Your Applications
Deliverability
Gmail, Microsoft, and Yahoo now require DMARC enforcement. Without it, your mail may be marked spam or rejected entirely. Implementing these protocols directly improves inbox placement.
Brand Protection
Email spoofing costs billions in fraud and credential theft. Criminals impersonate banks, payment processors, and popular SaaS platforms. SPF, DKIM, and DMARC make spoofing significantly harder, protecting your users and brand.
Compliance
Industries like finance and healthcare increasingly require email authentication proof. Implementing these protocols helps meet regulatory requirements.
Debugging Email Issues
When legitimate email fails, DMARC reports tell you exactly why. Aggregate reports show:
- How many messages passed/failed authentication
- Which IPs are sending from your domain
- Which alignments succeeded or failed
This intelligence is invaluable for diagnosing email problems.
Summary
- SPF — Authorizes IP addresses to send mail from your domain (simple, widely supported)
- DKIM — Digitally signs messages with a cryptographic signature (survives forwarding, stronger authentication)
- DMARC — Enforces policy based on SPF/DKIM alignment and generates reports (highest security, enables compliance)
Implement all three in order: SPF first for basics, then DKIM for robustness, then DMARC for enforcement. Start with monitoring (p=none), review reports for a week, then gradually enforce (p=quarantine then p=reject).
Your users deserve mail that reaches their inbox safely. These protocols make that possible.