Email Deliverability 101
Most people treat deliverability like a checkbox.
We set up SPF and DKIM. Why are we still going to spam?
The frustrating truth is: deliverability is not one setting. It's a trust system. Mailbox providers (Gmail, Outlook, Yahoo, etc.) are constantly scoring whether you deserve inbox placement.
I will be using a credit score analogy throughout this blog because it is quite analagous.
This post is a high-level mental model of deliverability. I'll walk through the layers in the order they're actually evaluated:
- Authentication & Identity (SPF, DKIM, DMARC)
- Reputation (Domain, IP, Sender)
- Sending Behavior (Bounces, Volume, Patterns)
- Content & Message Quality
- Engagement & User Signals
Then I'll cover why emails go to spam and give you a practical checklist.
TL;DR
- "250 OK" is not the same as "inbox." It just means the receiver accepted the message.
- Deliverability is a pipeline of trust: identity → reputation → behavior → content → engagement.
- SPF / DKIM prove identity, and DMARC enforces and aligns it.
- Bounces and complaints destroy reputation fast.
- Reputation exists at multiple layers: domain, IP, and sender identity.
The Email Reality Check: "Delivered" ≠ "In Inbox"
250 OK's don't mean much in terms of deliverability. It just means the server said okay to your message.
So when you ask:
"Why didn't my email show up?"
You need to be precise about which stage failed.
Here's the actual set of outcomes:
- Not accepted (SMTP rejected)
- Accepted (SMTP 250 OK)
- Delivered (landed somewhere in the mailbox)
- Spam (filtered)
- Inbox (placed)
- Missing (silently filtered or user rules)
Deliverability lives in stages 2–6.
Important: The SMTP sender can "successfully hand off" the message and still lose the deliverability battle after that.
The Deliverability Stack
When you debug deliverability, debugging random symptoms is painful:
- "Some users get it, some don't."
- "It works for Outlook but not Gmail."
- "Marketing emails go to spam but password resets are fine."
Here's the frame of thinking I like to use:
Takeaway: If layer 1 is broken, nothing below it matters. Each layer is a gate—pass all five to reach the inbox.
Let's walk through each layer!
Layer 1: Authentication (SPF, DKIM, DMARC)
These three are the foundation. It's checked first, and if it fails, you're already in trouble.
Fundamentally, it's proving you are who you say you are.
SPF DKIM DMARC answer:
- Who is allowed to send for this domain?
- Was the message modified in transit?
- Is the "visible sender" aligned with the authenticated identity?
- What should receivers do when checks fail?
Here's some example logic to put things into perspective:
//THIS ISN'T REAL CODE JUST TO HELP VISUALIZE
function exampleCheckAuthentication(email: Email): AuthResult {
const spf = checkSPF(email.senderIP, email.mailFrom)
const dkim = verifyDKIM(email.headers, email.body)
const dmarc = getDMARCPolicy(email.fromDomain)
// DMARC requires alignment
const aligned = spf.domain === email.fromDomain || dkim.domain === email.fromDomain
if (!aligned) {
if (dmarc.policy === 'reject') return { action: 'REJECT' }
if (dmarc.policy === 'quarantine') return { action: 'SPAM' }
}
return { action: 'CONTINUE', spf, dkim, dmarc }
}
SPF: "Is this IP allowed to send for this domain?"
SPF is a policy published in DNS that says:
If an email claims to be from this domain, these IPs/providers are allowed to send it.
So SPF helps prevent spoofing, but it's not the full story.
DKIM: "Was this message signed and unmodified?"
DKIM attaches a cryptographic signature to the message, that give providers like Gmail and Outlook an easy way to check you are the one that signed this email.
This proves:
- integrity (message wasn't modified)
- signing domain identity
Effectively this is to make sure some bad actors didn't tamper with the message while it was in transit.
DMARC: "Do SPF/DKIM align, and what's the policy?"
DMARC is the enforcement layer.
It does two key things:
1. Alignment
It makes sure the authenticated domains (SPF and/or DKIM) align with the visible from: joeshmoe@domain.com someone like you would see.
2. Policy
It tells receivers what to do if alignment/auth fails:
p=none(let it go through!) - bad ideap=quarantine(likely spam)p=reject(drop it)
DMARC is basically you telling Gmail what to do if neither SPF nor DKIM passes.
If you're past this spot, great.
Providers like Gmail come to the conclusion you are who you say you are, and this message was authentically sent by you. Now comes the vet: discovering your record (whether its criminal, or spotless)
Layer 2: Reputation (Domain, IP, Sender)
Once providers go "okay, you're ID is identified" the next question is: do we trust you?
A common misconception is:
We set up SPF/DKIM/DMARC, so we should be good.
Authentication only proves identity. Showing up to the DA with a real ID doesn't mean your criminal record is spotless.
Reputation is where mailbox providers decide:
- do we trust you?
- do users want your mail?
- do you behave like a stable sender?
function exampleCalculateReputation(sender: Sender): number {
let score = 50 // start neutral
// Domain history
score += sender.domain.ageInDays > 365 ? 10 : -10
score -= sender.domain.bounceRate * 100
score -= sender.domain.complaintRate * 500
// IP reputation
score += sender.ip.isWarmedUp ? 15 : -20
score -= sender.ip.blacklistCount * 25
// Sender-level signals
score += sender.replyRate * 50
score -= sender.unsubscribeRate * 30
return Math.max(0, Math.min(100, score))
}
Domain Reputation
The closest thing people use to this is a credit score. Its built over time, you don't start at a 800.
Example:
dookie.combilling.dookie.comsupport.dookie.com
Signals include:
- bounce rates
- complaint rates
- engagement patterns
- sending consistency over time
If your domain reputation is bad, you get filtered immediately even if auth passes.
IP Reputation
This is the trust score for the actual machines that send your mail.
Examples of when it matters
- dedicated IPs
- newly warmed IPs
- large volume senders
- shared IP pools (you can be impacted by neighbors)
If you're using a shared pool, IP reputation is partly out of your hands, but it still affects you. Contact your email provider if this might be a concern.
Sender Reputation
Different providers fuse different models, but generally it refers to reputation attached to the visible sender identity:
- From name + From address (
Support <support@agentmail.com>) - patterns of sending from that identity
- alignment stability
Mailbox providers may differentiate patterns across From addresses, but reputation is primarily domain- and IP-based.”
Layer 3: Sending Behavior (Bounces, Volume, Patterns)
Even with good auth and reputation, how you send matters.
Bounces: Hard vs Soft
Bounces are not just "delivery failures." They're reputation signals.
Think of bounces affecting your deliverability like past-due payments affecting your credit score.
One is not the end of the world, but its history that the email provider(or credit bureau) doesn't forget.
If mailbox providers see you generating lots of bounces, it suggests you're:
- sending to scraped lists
- sending to dead mailboxes
- not maintaining list hygiene
- behaving like a spammer
Hard Bounces (Permanent)
Hard bounces usually mean the message cannot be delivered.
Common causes:
- recipient address doesn't exist (
user@domain.cominvalid) - recipient domain doesn't exist
- blocked as invalid recipient
Soft Bounces (Temporary)
Soft bounces mean "try again later."
Common causes:
- mailbox is full
- recipient server is temporarily unavailable
- rate limiting
Takeaway: Bounces are input into reputation scoring. They are not just "ops logs."
function exampleHandleBounce(bounce: Bounce, sender: Sender) {
if (bounce.type === 'hard') {
// Permanent failure - stop sending immediately
addToSuppressionList(bounce.recipient)
sender.reputation -= 5
} else {
// Soft bounce - retry with backoff
if (bounce.retryCount < 3) {
scheduleRetry(bounce, delay: exponentialBackoff(bounce.retryCount))
} else {
sender.reputation -= 2
}
}
// High bounce rate = red flag
if (sender.bounceRate > 0.05) {
flagForReview(sender, reason: 'HIGH_BOUNCE_RATE')
}
}
Volume & Velocity
Mailbox providers watch for:
- sudden volume spikes
- sending to lots of brand-new recipients
- weird patterns (bursts, uniform content, list blasts)
Doing any of the above is not ideal.
Warm up new IPs/domains/inboxes gradually. Segment sends and avoid sudden spikes. In a nutshell warming up means exercising good sending hygeine with providers with email providers like Gmail to build rapport.
Will be releasing a more detailed blog on warming soon.
Layer 4: Content & Message Quality
Once you've passed auth, reputation, and behavior checks, the actual message gets scrutinized:
- Subject/body patterns - spammy keywords, ALL CAPS, excessive punctuation
- Link reputation - are you linking to sketchy domains?
- MIME/HTML correctness - malformed emails look suspicious
- Attachments - certain file types are red flags
This layer is why two emails from the same sender can have different outcomes. The content matters.
Some of our customers do all the right things but then the content includes words like FREE, 50% OFF, NO CREDIT CARD REQUIRED. As a human reading this, wouldn't these also raise red flags on your part as well?
Best to avoid spammy key words.
Layer 5: Engagement & User Signals
The final layer is the most powerful and hardest to control directly:
- Opens and replies - good signals
- Deletes without reading - bad signal
- "This is spam" complaints - catastrophic
Mailbox providers are constantly asking: "Will this user want this email?"
Your historical engagement data feeds into this prediction.
function examplePredictInboxPlacement(email: Email, recipient: User): Decision {
const history = getEngagementHistory(email.sender, recipient)
// Positive signals
let score = 0
score += history.openRate * 30
score += history.replyRate * 50
score += history.movedToInbox * 20
// Negative signals (these hurt a lot)
score -= history.markedAsSpam * 100
score -= history.deletedWithoutReading * 10
score -= history.unsubscribed * 40
// The million dollar question
if (score > 50) return 'INBOX'
if (score > 20) return 'PROMOTIONS'
return 'SPAM'
}
P.S: Having users actually be able to reply to your emails in the same thread and have a back-and-forth conversation with you is the absolute best way to prove to Gmail you deserve a higher deliverability score.
This means their customer is actually engaging with you and your email means something.
This is why transactional marketing email campaigns and service providers tend to be more scrutinized since theres no opportunity to reply to their messages.
Summary
Takeaway: Inbox placement is a trust and engagement prediction system.
What's Next (Deep Dives)
This post is just the beginning. Next are the zoom-ins.
Planned deep dives:
- SPF Deep Dive (DNS lookup limits, includes, common pitfalls)
- DKIM Deep Dive (selectors, rotation, canonicalization)
- DMARC Deep Dive (alignment rules, enforcement rollout, reporting)
- Domain vs IP Reputation (warmups, dedicated vs shared IP tradeoffs)
If you're building email infrastructure for agents (or just any high-volume product), deliverability is one of those things that feels invisible until it becomes the only thing that matters.
The Only Mental Model You Need
If you remember one sentence:
Deliverability is a trust pipeline, not a boolean.
- Authentication is how you prove who you are.
- Reputation is whether anyone believes you.
- Behavior and engagement are whether you stay believed.

