--forcepushed--fp
  • Home
  • Articles
  • Resources
  • Projects

Build smarter, ship faster, and stand out from the crowd.

Subscribe or follow on X for updates when new posts go live.

Follow on X

Why Email Is Surprisingly Hard

When I first needed to send email for SaaS apps and other features, I assumed it was a solved, boring problem.

It turns out email is anything but simple and getting it right meant learning way more about infrastructure, trust, and reputation than I expected.

It was more work than I planned for, but absolutely worth it once I understood what was really going on under the hood.

How Email Works (From an App or Business to a Customer)

Until I started doing this for myself, I naively thought email was simple: you type a message, hit “send,” and it shows up in someone’s inbox.

Behind the scenes, however, it’s a distributed system involving multiple actors, protocols, and trust mechanisms. From an app or business perspective, sending email is less like sending a message and more like handing a letter to a global postal network and hoping it clears every checkpoint along the way.

At a high level, sending an email looks like this:

  1. Your application generates an email
  2. The email is handed to a sending mail server
  3. The sending server locates the recipient’s mail server
  4. The message is transferred between servers
  5. The recipient’s server evaluates trust and spam signals
  6. The message is delivered (or rejected) to the user’s inbox

Each step has failure modes, security checks, and reputation implications.

Why Email Is Hard for Businesses

From an engineering perspective, email is:

  • Federated (no central authority)
  • Asynchronous and failure-prone
  • Heavily reputation-based
  • Sensitive to configuration mistakes
  • Actively hostile to abuse

It’s a system built for resilience and decentralization, not developer convenience.

Core Actors in the Email Ecosystem

1. The Sending Application

This is your product, backend service, or system that wants to send email (password resets, invoices, notifications, marketing messages, etc.).

The application typically:

  • Constructs the email content (headers + body)
  • Calls an SMTP server or email API
  • Does not usually send email directly to the internet

2. Outbound Mail Server (SMTP Server / ESP)

Most apps use a mail transfer agent (MTA) or a third-party Email Service Provider (ESP) like SendGrid, Amazon SES, or Postmark.

Responsibilities include:

  • Accepting email from your app
  • Queuing and retrying delivery
  • Talking SMTP to other mail servers
  • Signing messages for authentication
  • Tracking bounces, complaints, and delivery status

This server represents your “sending identity” to the rest of the internet.

3. DNS (Domain Name System)

We'll go into this in more detail below, but essentially DNS is the directory email servers rely on to find each other and establish trust.

Critical DNS records include:

  • MX records – where to deliver mail for a domain
  • SPF records – which servers are allowed to send mail for a domain
  • DKIM records – public keys used to verify message integrity
  • DMARC records – policy rules for authentication failures

If DNS is misconfigured, mail may be rejected before content is even considered.

depending on what you choose, the email provider might automatically generate these records for you and all you need to do is plug them into your registrar or web hosting provider

use dmarcian or easydmarc if you really wanna learn the ins and outs of dmarc services, email visibility and protection.

4. Recipient Mail Server

This is the server run by the recipient’s provider (Gmail, Outlook, Yahoo, corporate email, etc.).

Its responsibilities:

  • Accept incoming SMTP connections
  • Validate sender authenticity
  • Apply spam and abuse detection
  • Decide whether to accept, reject, or quarantine the message

This is where most delivery failures happen.

5. End User (Inbox)

The final consumer interacts only with the result:

  • Inbox
  • Spam folder
  • Or no message at all

By this point, all technical decisions have already been made.

How your emails end up in the users inbox in the first place

Before continuing on too far w/ sending and receiving emails, it's important to understand some basics about email in general.

Think of deliverability as a three-legged stool:

  • Authentication - DNS
  • Reputation or behavior over time
  • Content & engagement signals

When sending emails, you need to take into account a lot of factors like reputation, spam (maybe add a cpl others here) etc in order to keep email inbox placement high

No email provider can guarantee inbox placement, but using any email provider + correct DNS + sane sending behavior is absolutely sufficient to avoid spam in practice for transactional email.

Authentication and Trust Mechanisms

In order to be able to send email from an application using a particular domain, you must control the DNS for that domain.

These are mandatory, non-negotiable and usually the real bottleneck. If any of them are missing or wrong, your email is either no sent or it will hit spam.

For each sending domain, the following DNS records must exist:

MX (Mail Exchange)

MX answers the question:

“Where should email for this domain be delivered?”

When someone sends an email to @yourdomain.com, the recipient’s mail server:

  • Looks up the domain’s MX records
  • Finds the mail servers responsible for receiving mail
  • Delivers the message to the lowest-priority available server

MX records define:

  • Which servers receive inbound email
  • Failover order (priority values)
  • Whether your domain can receive mail at all

No MX records = mail bounces.

Incorrect MX records = mail disappears into the void.

MX records do not:

  • Authenticate senders
  • Validate message integrity
  • Prevent spam or spoofing

They only answer where mail goes, not whether it should be trusted.

MX is the foundation.

SPF, DKIM, and DMARC sit on top of it.

If MX is wrong, nothing else matters.

SPF (Sender Policy Framework)

SPF answers the question:

“Is this server allowed to send email on behalf of this domain?”

The recipient server:

  • Looks up the domain’s SPF record
  • Checks the sending IP
  • Passes or fails the check

SPF does not validate message content.

Failing SPF = spam or outright rejection.

DKIM (DomainKeys Identified Mail)

DKIM answers:

“Was this message modified after it was sent?”

The sending server:

  • Cryptographically signs parts of the message
  • Adds a DKIM signature header

The recipient:

  • Fetches the public key from DNS
  • Verifies the signature

This ensures message integrity and domain alignment.

Proves the email wasn’t altered

Massive positive signal to Gmail, Outlook, Yahoo

This is one of the biggest factors

No DKIM = you’re playing on hard mode.

DMARC (Domain-based Message Authentication, Reporting, and Conformance)

DMARC ties SPF and DKIM together and defines policy. Tells inboxes how to treat failures.

DMARC tells recipient servers:

  • How to handle failures (none, quarantine, reject)
  • Where to send aggregate and forensic reports
  • Which domain alignment rules apply

DMARC is critical for preventing spoofing and phishing.DMARC isn’t required to send, but it dramatically improves trust.

Handling Inbox Reputation and Warming Up Your Sending

Authentication proves who you are. Reputation decides where your email lands.

You can have perfect SPF, DKIM, and DMARC and still go straight to spam if inbox providers don’t trust your sending behavior. Authentication is table stakes. Reputation is the game.

Inbox providers continuously evaluate whether you behave like a real application—or like a spammer who just learned DNS.

What Inbox Providers Actually Judge

Inbox providers don’t look at one thing. They look at patterns over time.

They evaluate:

  • The reputation of your sending domain
  • The reputation of the IP mail comes from
  • How users interact with your messages
  • How often messages bounce or get reported
  • Whether your sending volume looks human or automated
  • Whether your content patterns change suddenly

A single bad signal won’t kill you. A pattern of bad signals will.

This is why even “technically correct” email setups can fail in production.

Why Warm-Up Exists at All

Warm-up is not ceremony. It’s trust-building.

When a brand-new domain starts sending email, inbox providers assume neutral intent, not good intent. You haven’t earned trust yet.

If you go from zero to high volume immediately, you look exactly like:

  • A compromised domain
  • A freshly spun-up spam operation
  • A phishing campaign

Warm-up is how you prove, gradually, that you’re none of those things.

It’s volume plus behavior, over time.

What Providers Watch During Warm-Up

During warm-up, inbox providers watch engagement far more closely than raw volume.

Good signals:

  • Messages don’t bounce
  • Users open emails
  • Users click links
  • Emails aren’t deleted immediately
  • Volume increases smoothly day over day

Bad signals:

  • Sudden spikes in volume
  • Sending to dead or unused addresses
  • Repeated emails to the same mailbox with no interaction
  • Zero engagement across many sends
  • Spam complaints or “Report spam” clicks

Warm-up isn’t about convincing filters. It’s about convincing users, and letting inbox providers observe that.

Reputation Is Per Domain (and That’s a Feature)

Reputation is scoped to each sending domain.

This is good because:

  • One bad app won’t destroy your entire company
  • You can isolate risk between products
  • You can rotate or retire domains safely

It’s also painful because:

  • Low-volume domains take longer to build trust
  • Every new domain starts neutral, not trusted
  • Each domain needs its own warm-up curve

There’s no global “account reputation” that saves you.

Every domain earns its own reputation from scratch.

What Your Email Provider Handles (and What They Don’t)

Most modern providers do a lot right:

  • Clean infrastructure
  • Well-maintained IP pools
  • Minimal cross-contamination from shady senders

What they cannot do for you:

  • Control who you send to
  • Control your engagement rates
  • Control your sending cadence
  • Fix spammy behavior patterns

Reputation is behavioral. That part is always on you.

Domain Reputation vs IP Reputation

There are two separate reputations in play.

Domain reputation almost always applies. This is the primary signal for most application email.

IP reputation depends on your setup:

  • If you use a major provider with shared IPs, those IPs are usually pre-warmed. You mostly care about your domain.
  • If you run your own mail server or use a dedicated IP, IP warm-up becomes your responsibility too.

Most apps only need to worry about domain warm-up.

What “Good” Looks Like in Practice

With:

  • SES (or a similar provider)
  • Correct SPF, DKIM, and DMARC
  • Reasonable volume
  • Mostly transactional email

Typical outcomes look like:

  • Gmail: Inbox
  • Outlook: Inbox or Focused
  • Yahoo: Inbox
  • Corporate email: Inbox or Promotions

This is the same setup used by startups, banks, internal tools, and infrastructure platforms. There’s nothing exotic about it. Just disciplined execution.

A Practical Warm-Up Schedule

Warm-up should be boring. Predictability beats speed.

This assumes real users and real transactional email only.

Days 1–2 5–10 emails per day Password resets, signups, receipts No marketing, no blasts

Days 3–4 20–30 emails per day Same message types Spread across the day

Days 5–7 50–100 emails per day Still transactional No bursts or cron spikes

Week 2 200–500 emails per day

Week 3+ Gradually ramp to normal volume

If your app only sends ~50 emails a day total, you’re effectively always warm. No special handling needed.

How Warm-Up Gets Ruined

The fastest ways to sabotage yourself:

  • Running tests in production
  • Sending batches of “test emails” to yourself
  • Warming multiple domains simultaneously
  • Bursty jobs that send everything at once
  • Perfectly timed daily blasts that scream automation

Inbox providers love consistency. They hate surprises.

How You Know It’s Working

Healthy signals:

  • Emails consistently land in inbox
  • No SES bounce or complaint alerts
  • No scary Gmail warnings
  • DMARC reports show passes

If you see:

  • Sudden spam placement
  • Throttling or soft bounces
  • Deliverability instability

Slow down immediately. Reputation recovers slowly, but it does recover if you stop digging.

Warm up isn’t about speed.

It’s about proving, quietly and repeatedly, that your app behaves like a real system sending real email to real people.

Content and engagement signals

To be honest, your content could matter more than the email provider you choose to use.

All the right DNS records and perfect Reputation won’t save you if your emails start to look like this:

🚨 ACT NOW 🚨

FREE FREE FREE

Click here immediately!!!

Things that will get you flagged

  • Spammy content
  • Sending to yourself repeatedly
  • Sending to dead addresses
  • Sudden volume spikes
  • Using throwaway inboxes
  • No unsubscribe link, even for “transactional” email if it looks promo-ish

Things that help inboxing

  • Low initial volume
  • Consistent sending pattern
  • Mostly transactional content
  • Real user interaction (opens, clicks)
  • Clean HTML (no spammy phrases)
  • Content Still Matters, But Less Than People Think

But for normal app emails like:

  • Password reset
  • Magic links
  • Receipts
  • Notifications

...content is usually not the problem.

I mentioned above but sending test emails to yourself over and over can hurt reputation if you do it in production outside of a sandbox.

with all that in mind, how are you suppoed to even test your email sending works and what the emails look like before you send them to real customers without getting penalized? lets go into this below

Send development emails without spending money

Before you ever worry about sending emails “in the wild,” you should get ruthless about cost control. During early development, most emails exist for one reason only: to verify that something works. Password resets, invites, confirmations, alerts, all of which usually go straight to you and then straight to the trash.

Paying for those emails is unnecessary. Worse, it’s a habit that quietly leaks money and can even harm your real sending domain if you’re not careful.

For development and testing, where you don’t care about real delivery and don’t want to spam actual inboxes, the right move is to send emails locally and virtually.

Use a local / virtual email tester

The simplest approach is to run a local SMTP “catcher.” Your app thinks it’s sending real email, but nothing ever leaves your machine.

Instead:

  • Emails are captured locally and can view in a browser somewhere like http://localhost:8025
  • You get a web UI to inspect them
  • No inboxes, no API keys, no billing, no setup friction

No logins. No credentials. No cleanup.

This is ideal when:

  • You want to capture emails from any code path
  • You don’t need real inbox delivery
  • You want to inspect headers, bodies, and templates
  • You want zero cost during development

MailHog is a popular option here. It runs locally, captures all SMTP traffic, and gives you a clean UI to review messages. This is what I use for local development.

Papercut is another solid alternative. It serves the same purpose and works well across platforms. If MailHog isn’t your thing, Papercut fills the same role with almost no mental overhead.

Both tools let you fully exercise your email logic without:

  • Paying for sends
  • Polluting real inboxes
  • Risking domain reputation

Cloud sandboxes (when local isn’t an option)

If self-hosting a dev email tool is a non-starter, many cloud email providers offer sandbox or test modes where messages don’t actually reach real recipients.

These can be useful, but they come with tradeoffs:

  • Sending limits are common
  • Behavior may differ from real SMTP delivery
  • You’re still coupled to a vendor early
  • Some features are disabled or simulated

They’re fine in a pinch, but for day-to-day development, local capture tools are usually simpler, cheaper, and more predictable.

Building an email sender interface

At some point, your app will need to send real emails. The mistake founders make is baking that decision directly into their application logic.

Instead, build a thin email-sending interface that lets you swap implementations based on environment:

  • Local development → local SMTP catcher
  • Staging / production → real email provider

Your app shouldn’t care how an email is delivered, only that an email was requested.

This gives you:

  • A clean seam between business logic and delivery
  • Zero accidental sends during development
  • No damage to your real sending domain
  • Easy switching between environments (local, staging, prod)

This boundary is important.

Email delivery is an implementation detail, not application logic. Treat it that way.

This is exactly how mature SaaS platforms operate:

  • One interface
  • Multiple implementations
  • Environment decides which one runs

You save money during development, avoid reputation penalties on your real domain, and keep your system flexible as you scale.

Practical, Affordable Approaches to Email — and How to Choose a Provider

By this point, I've shown you how email actually works: sending, receiving, DNS, SPF/DKIM/DMARC, reputation, and even how to safely develop and test email locally.

Now comes the part founders usually care about most:

How much does this cost, and which provider should I actually use?

The good news: sending email is cheap.
The bad news: the operational trade-offs between providers are what trip people up.

Let’s bring everything together.

The Big Picture: What You’re Paying For

Email providers typically charge based on a mix of:

  • Emails sent (per 1,000 or via monthly tiers)
  • Features (dashboards, analytics, templates, deliverability tools)
  • Operational convenience (UI, per-app separation, domain management)
  • Support & polish, not raw infrastructure

At the infrastructure level, email is a solved problem. What you’re really choosing is how much time and friction you want to trade for money.

Transactional Email Providers Compared

Below are the most common options I've found that founders evaluate for transactional email.

Postmark

Best for: High-quality transactional email with minimal fuss.

Postmark is opinionated and intentionally narrow in scope: it does transactional email extremely well.

Strengths

  • Excellent deliverability reputation
  • Clean per-app separation
  • Purpose-built for transactional email (not marketing)
  • Simple mental model

Trade-offs

  • No free tier
  • More expensive than infrastructure-level options
  • Less flexible for unusual setups or very high volume

If email is mission-critical (password resets, invoices, alerts) and you want it to just work, Postmark is often worth the premium.

SendGrid

Best for: Teams that want dashboards, analytics, and marketing-style tooling.

SendGrid is a full-featured platform that spans transactional and marketing email.

Strengths

  • Free tier (100 emails/day)
  • Polished UI and analytics
  • Templates, tracking, and deliverability tooling
  • Well-known and widely supported

Trade-offs

  • Pricing is plan-based, not purely pay-as-you-go
  • More expensive per email for transactional-only use cases
  • Feature set can feel heavy if you just need “send an email”

SendGrid makes sense if email is a business function, not just an infrastructure detail.

Mailgun

Best for: Developers who want flexibility without AWS complexity.

Mailgun sits nicely between SES and SendGrid.

Strengths

  • Developer-friendly APIs
  • Good domain management
  • Flexible pricing options
  • Better tooling than SES without full enterprise overhead

Trade-offs

  • More expensive than SES (often ~8×–10× per email)
  • Tiered pricing can add up
  • Some advanced features cost extra

Mailgun is often chosen when SES feels too raw, but SendGrid feels like overkill.

Amazon SES

Best for: Founders who care about cost, scale, and control.

Amazon SES is not flashy. It’s cheap, reliable, and brutally honest about what it is: infrastructure.

How SES Pricing Works

  • Sending: ~$0.10 per 1,000 emails
  • Data transfer: ~$0.12 per GB (usually negligible)
  • No monthly minimums
  • No per-domain fees

SES charges only for usage. If you send nothing, you pay nothing.

Domain & Identity Flexibility

SES lets you send from:

  • Verified domains (e.g. example.com)
  • Verified email addresses (e.g. no-reply@example.com)

You can verify:

  • 1 domain
  • 10 domains
  • 100+ domains

All at no additional cost.

If you verify a single domain, you can send from unlimited addresses under it:

Why SES Is So Cheap

Because SES doesn’t optimize for:

  • Per-app dashboards
  • Non-technical onboarding
  • Opinionated workflows

It assumes you know what you’re doing or are willing to learn.

When SES Starts to Feel Painful

SES usually breaks down organizationally, not technically:

  • Many low-volume domains
  • Non-technical clients who need DNS help
  • Desire for per-app dashboards or reporting
  • Ops time becomes more expensive than infrastructure

That’s when teams migrate away from SES. Not because it can’t scale, but because time becomes more valuable than money.

Cost Comparison: What This Looks Like in Practice

📊 Basic Pricing (Transactional Email)

ProviderPricing ModelApprox. Cost per 1,000 EmailsFree Tier / Trial
Amazon SESPay-as-you-go~$0.103,000/month (first year, eligible accounts)
MailgunUsage or tiered~$0.80 (Flex pricing)Limited trial
SendGridMonthly plans~$0.40–$0.90 (effective)100/day free

Example Monthly Costs

Small Volume (10,000 emails/month)

  • SES: ~$1
  • Mailgun: ~$8+
  • SendGrid: ~$19.95 (plan minimum)

Medium Volume (100,000/month)

  • SES: ~$10
  • Mailgun: ~$80
  • SendGrid: ~$89.95

High Volume

SES continues scaling linearly at ~$0.10/1,000.
Mailgun and SendGrid scale via increasingly expensive tiers.

So… Which One Should You Choose?

Here’s the practical decision table most founders eventually arrive at:

Your GoalBest Choice
Absolute lowest cost at any scaleAmazon SES
Developer-friendly APIs with toolingMailgun
Dashboards, analytics, and marketing featuresSendGrid
Best-in-class transactional deliverabilityPostmark

The Founder Takeaway

Email isn’t expensive. Poor understanding is.

Once you understand:

  • DNS and authentication
  • Reputation and deliverability
  • Volume vs. consistency
  • Operational overhead

…the choice becomes obvious.

Most early stage founders should:

  • Start with SES if they’re technical and cost-sensitive
  • Move to Mailgun, SendGrid, or Postmark when ops time outweighs savings

Email is infrastructure until it becomes product-critical. Choose accordingly.

Final Takeaways: How Founders Should Think About Email

If there’s one mental model to keep, it’s this:

Think of email as:

  • A global trust network
  • With DNS as identity
  • SMTP as transport
  • Reputation as currency
  • And inbox placement as the only metric that actually matters

Sending email isn’t just “sending a message.”
It’s participating in a long-running, adversarial system designed to stop abuse at massive scale. In that system, consistency and correctness matter far more than clever code.

What’s Really Happening When Your App Sends an Email

Every time your application sends an email, you are:

  • Asserting an identity via DNS
  • Asking multiple independent systems to trust that identity
  • Passing through filters explicitly designed to block you
  • Competing for attention in an overcrowded inbox

Your email either earns trust over time or it doesn’t get delivered at all.

This is why email problems often look random until you understand the mechanics underneath.

Email Is a Product Concern, Not Just an Engineering Detail

To build a reliable email system, you have to think like both a developer and DevOps:

  • Infrastructure choices affect deliverability
  • Operational mistakes compound over time
  • Early shortcuts can permanently damage reputation

Email is one of the few systems where early mistakes are expensive and hard to undo.

Non-Negotiables for Founders

If you remember nothing else, remember these:

Get Identity Right First

  • Set up SPF, DKIM, and DMARC (even p=none is better than nothing)
  • Treat DNS as part of your application, not a one-time task
  • One clean domain is better than many poorly managed ones

Keep Email Transactional

  • Transactional ≠ marketing
  • Avoid unnecessary HTML bloat
  • Send emails users expect and trigger themselves

Respect Volume and Warm-Up

  • Ramp sending volume gradually
  • Don’t spin up cold domains and blast immediately
  • Reputation is earned, not configured

Separate Environments Strictly

  • Dev and test traffic should never hit live providers
  • Use MailHog or Mailtrap locally for free, safe testing
  • Use provider sandboxes to verify integrations before launch
  • Never “test by emailing yourself” in production

Avoid Accidental Costs and Damage

  • Use environment switching or feature flags
  • Make it impossible for dev/test code to send real email by accident
  • Protect both your wallet and your domain reputation

The Bottom Line

Email works remarkably well when you respect how it works.

Founders who treat email as “just another API” often pay for it later with:

  • Spam placement
  • Blocked domains
  • Lost trust
  • Hidden operational costs

Founders who understand the system can:

  • Send at scale for pennies
  • Maintain strong deliverability
  • Choose providers intentionally
  • And build trust with users from day one

Email isn’t magic, but it is a system that rewards understanding.