DNS, SPF, DKIM, DMARC: Why Your Email Goes to Spam (and How Attackers Impersonate You) Everything you need to know about the three protocols that separate your legitimate email from the spam folder — and that separate your brand from being used by scammers. Introduction You send an important email to a client.
Everything you need to know about the three protocols that separate your legitimate email from the spam folder — and that separate your brand from being used by scammers.
You send an important email to a client. They reply two days later: "sorry, it went to spam". You send another to a lead, and it simply never arrives. And meanwhile, someone on the internet is sending email impersonating your company, asking your clients for transfers, and you only find out when the client calls to complain.
Welcome to the world of email authentication. A place where three acronyms — SPF, DKIM and DMARC — decide whether you exist digitally or not.
The good news is that these three protocols solve 95% of deliverability and spoofing problems. The bad news is that the absolute majority of domains on the internet don't have even one of them configured correctly. And since February 2024, Google and Yahoo started requiring DMARC for senders who send more than 5,000 emails per day.
The email protocol (SMTP) was created in 1982 and had no authentication mechanism. Literally none. Any server can send an email claiming to be from any address.
For decades this worked because the internet was small. Spam came, phishing came, organized fraud came. The solution wasn't to rewrite SMTP — it was to add authentication layers on top, using DNS:
The three work together. Alone, they have holes. Combined, they form reasonable defense.
Email authentication is not "optional security". It's basic infrastructure. Without it: legitimate emails go to spam, attackers can impersonate you, and Google/Yahoo simply reject much of the traffic from those who don't authenticate.
You publish in DNS a list of servers authorized to send email on behalf of your domain. The destination server consults that list and verifies that the source IP is authorized.
A single TXT record:
empresa.com.br. IN TXT "v=spf1 ip4:200.150.100.10 include:_spf.google.com -all"
Breaking it down:
v=spf1 — versionip4:200.150.100.10 — authorizes this IPinclude:_spf.google.com — authorizes Google Workspace IPs-all — any other IP is rejectedCommon mechanisms:
| Mechanism | What it does | |---|---| | ip4:1.2.3.4 | Specific IP | | ip4:1.2.3.0/24 | IP range | | a | A record IP | | mx | MX IPs | | include:domain.com | Includes SPF from another domain | | redirect=other.com | Replaces with SPF from another |
Qualifiers:
| Syntax | Meaning | |---|---| | +all | Accept everything (NEVER use) | | -all | Reject everything not in the list | | ~all | SoftFail — accept but mark | | ?all | Neutral (equivalent to not having SPF) |
Google Workspace only:
"v=spf1 include:_spf.google.com -all"
Microsoft 365 only:
"v=spf1 include:spf.protection.outlook.com -all"
Hybrid (M365 + own server + marketing + transactional):
"v=spf1 ip4:200.150.100.10 include:spf.protection.outlook.com include:_spf.mailgun.org include:sendgrid.net -all"
10 DNS lookup limit. Each include, a, mx, exists counts. Exceeded it? SPF breaks with permerror and for many servers that's equivalent to failing. The limit is recursive — if you include Google's SPF, and Google includes others, they all count.
Breaks with forwarding. Forwarded email comes from a server that's not in your SPF. Fails.
Doesn't protect the visible "From:". SPF verifies the MAIL FROM (envelope), not the From: that appears to the user. Attacker can pass SPF perfectly and show From: ceo@yourcompany.com.br.
No encryption. Only checks IP. Compromised authorized server? Attacker sends whatever they want.
dig TXT empresa.com.br +short
# Tools:
# - mxtoolbox.com/spf.aspx
# - dmarcian.com/spf-survey/
# - kitterman.com/spf/validate.html
+all or ?all — nullifies protectioninclude pointing to nonexistent domainCryptographic digital signature on each email sent.
Guarantees authenticity (it really came from the key owner) and integrity (it wasn't altered in transit).
default._domainkey.empresa.com.br. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC7VK..."
default.domainkey.empresa.com.br — format [selector].domainkey.[domain]v=DKIM1 — versionk=rsa — algorithmp=... — public key in Base64The selector allows you to have multiple DKIM keys active simultaneously. Each service uses its own selector.
Google Workspace: Admin Console → Apps → Gmail → Authenticate email → Generate. Publish the record it gives you.
Microsoft 365: Defender → Email & collaboration → Threat policies → DKIM → enable (uses CNAMEs).
Mailgun, SendGrid, Mailchimp, Amazon SES: all have wizards.
Own server (Postfix with OpenDKIM):
sudo apt install opendkim opendkim-tools
sudo mkdir -p /etc/opendkim/keys/empresa.com.br
cd /etc/opendkim/keys/empresa.com.br
sudo opendkim-genkey -s mail -d empresa.com.br -b 2048
sudo chown opendkim:opendkim mail.private
cat mail.txt # DNS record to publish
DKIM-Signature header added to each email:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=empresa.com.br; s=default;
h=from:to:subject:date:message-id;
bh=BASE64_BODY_HASH;
b=BASE64_SIGNATURE
d= — domain that signeds= — selectorh= — signed headersbh= — body hashb= — signatureBreaks with modification in transit. Mailing lists that add footers invalidate the signature.
Weak key. Use 2048 bits minimum. RSA 1024 is considered broken.
No rotation. Best practices say rotate every 6-12 months. Almost no one does.
Doesn't protect the visible From: by itself — the d= can be different from From:. That's where DMARC comes in.
dig TXT default._domainkey.empresa.com.br +short
Best way: send an email to check-auth@verifier.port25.com and receive a full report.
SPF and DKIM verify technical things but don't enforce decisions. And neither verifies if the visible From: matches the authenticated domain.
DMARC solves:
From: to match authenticated domain_dmarc.empresa.com.br. IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc@empresa.com.br; ruf=mailto:dmarc-forensic@empresa.com.br; fo=1; adkim=s; aspf=s; pct=100"
| Parameter | Function | |---|---| | v=DMARC1 | Version | | p= | Policy: none, quarantine, reject | | sp= | Policy for subdomains | | rua= | Email for aggregate reports (daily XML) | | ruf= | Email for forensic reports | | pct= | % of traffic that applies the policy | | adkim= | DKIM alignment: r or s | | aspf= | SPF alignment: r or s | | fo= | When to generate forensic reports |
p=none — monitoring mode. Does nothing, but sends reports. Always start here.
p=quarantine — quarantine. Failing emails go to spam.
p=reject — rejection. Failing emails are rejected on delivery. The final goal.
Relaxed (r): organizational domains match. email.empresa.com.br aligns with empresa.com.br. Standard.
Strict (s): has to be exactly equal.
To pass DMARC, the email needs:
MAIL FROM align with From:, ORd= align with From:When you define rua=, you receive daily XMLs from Google, Microsoft, Yahoo, etc. with:
You discover things like:
The XMLs are horrible to read. Use services that do parsing: Postmark DMARC Monitoring (free), Dmarcian, EasyDMARC, Valimail, OnDMARC.
1. Configure SPF and DKIM first.
2. Start with p=none:
"v=DMARC1; p=none; rua=mailto:dmarc@empresa.com.br; fo=1"
3. Monitor for 2-4 weeks with Dmarcian/Postmark.
4. Migrate to p=quarantine with pct=10:
"v=DMARC1; p=quarantine; pct=10; rua=mailto:dmarc@empresa.com.br; fo=1"
5. Increase pct= gradually — 25%, 50%, 75%, 100%.
6. Move to p=reject:
"v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc@empresa.com.br; ruf=mailto:dmarc-forensic@empresa.com.br; fo=1; adkim=s; aspf=s"
The journey takes 1-3 months to do properly. Don't jump to reject directly unless you want to spend the evening explaining to the CEO why emails stopped.
p=reject directlysp= for subdomainsAttacker sends email saying From: ceo@empresa.com.br. Without SPF/DKIM/DMARC, it arrives normally.
Defense: SPF with -all + DMARC with p=reject.
empresa.com.br has DMARC. But vendas.empresa.com.br doesn't. Attacker uses the subdomain.
Defense: always sp=reject in the main DMARC.
Attacker registers empressa.com.br (two s), empresa.com.co, empresa-support.com. Technically theirs, passes all checks, looks like yours.
Defense: monitoring of similar domains (DomainTools, DNSTwist), training, BIMI, brand protection tools.
Attacker uses their own email but puts "Ceo Company" in the display name. Mobile client only shows "Ceo Company".
Defense: training + filters that detect display name spoofing.
Attacker gains access to legitimate account (phishing, leaked password). Everything passes all checks because it really is legitimate.
Defense: MFA, anomalous behavior monitoring.
Attacker compromises your supplier. Sends emails from the supplier's real server, often replying to existing threads.
Defense: vigilance, training, out-of-channel verification for financial requests.
"HSTS of email". Guarantees delivery via encrypted TLS, prevents downgrade. Configuration has two parts: DNS record + HTTPS page at mta-sts.empresa.com.br.
Reports about TLS failures in delivery.
_smtp._tls.empresa.com.br. IN TXT "v=TLSRPTv1; rua=mailto:tls-reports@empresa.com.br"
Verified logo of your brand appearing in the recipient's inbox. Requires DMARC with p=quarantine or p=reject + SVG logo + ideally VMC (paid certificate).
Huge visual credibility advantage.
Solves the problem of forwarding/lists that break SPF/DKIM. Intermediate servers attest to the original authentication. Implemented automatically by major providers.
Protects against falsification of DNS itself. Cryptographically signs records. Essential extra layer.
In order of frequency:
Complete analysis:
Terminal:
dig TXT empresa.com.br +short | grep spf
dig TXT default._domainkey.empresa.com.br +short
dig TXT _dmarc.empresa.com.br +short
dig MX empresa.com.br +short
dig -x 200.150.100.10 +short
Received email headers: Gmail → three dots → "Show original". Look for Authentication-Results::
Authentication-Results: mx.google.com;
spf=pass smtp.mailfrom=sender@empresa.com.br;
dkim=pass header.i=@empresa.com.br header.s=default;
dmarc=pass (p=REJECT) header.from=empresa.com.br
pass on all three is what you want.
-all, under 10 lookupsp=none — start monitoringp=quarantine graduallyp=rejectsp=reject for subdomainsEmail authentication seems complicated until you do it once. SPF, DKIM and DMARC together solve 95% of deliverability problems and prevent 95% of direct spoofing attacks.
Not doing this, in 2026, is negligence. Google and Yahoo are already massively rejecting those who don't authenticate. In a few years, sending email without SPF/DKIM/DMARC will be as unthinkable as dial-up modem.
And the best part: it's not expensive. The three protocols are free, documentation is abundant, monitoring tools have free tier, results are immediate.
SentinelHub does exactly this: monitors SPF, DKIM, DMARC, MTA-STS, DNSSEC and all critical DNS records of your domain. When something changes — someone adds a new service and exceeds the SPF limit, someone accidentally removes the DMARC record, someone forgets to renew a DKIM key — you find out. In Portuguese.
Client who receives your email in spam is client who loses confidence. Client who receives email from a scammer impersonating you is client you lose.
Found it useful? Share with your marketing team and the sysadmin who manages the email server. Especially if you're still sending emails marked as "[SPAM]" to your own inbox.