Email deliverability at scale: SPF, DKIM, DMARC, and 17 years of Exchange
A practitioner's guide to email infrastructure for B2B — SPF/DKIM/DMARC, Exchange to Microsoft 365 migration, anti-spam architecture, and the deliverability lessons that decide whether your sales emails land in inbox or spam.
If you run B2B at any scale, email deliverability is more important than anything you'll write in your campaigns. A 40% reply rate on emails that hit spam folders gets you exactly zero meetings. I learned this the slow way over 17 years running email for a 1,500-person company and then rebuilding it again for GrowMore Solutions, our automation + outbound business.
This is the practitioner's playbook. Not "what is SPF" — every blog has that — but the actual order in which to build, what breaks, and what 99% of teams skip.
The 3-layer mental model
Every email you send passes three gates:
- Authentication — does the receiving server believe the sender is who they claim to be? (SPF, DKIM, DMARC)
- Reputation — does the receiving server's filter trust this sending IP and domain? (IP warm-up, bounce rates, complaint rates, feedback loops)
- Content — does the filter think the email looks like spam? (subject lines, link patterns, image-to-text ratio, attachments)
You can write the best subject line ever and still hit spam if layer 1 or layer 2 fails. Most teams skip layers 1 and 2 entirely and then blame the copy.
Layer 1 — Authentication (the table stakes)
SPF — "who can send mail for my domain?"
SPF is a TXT record listing the IPs / hostnames authorized to send mail for your domain. Example:
v=spf1 include:_spf.google.com include:spf.mailgun.org ip4:203.0.113.42 -all
Three things you must get right:
-allnot~allat the end.~allis "soft fail" (suspect but accept).-allis "hard fail" (reject). Use-allonce you're confident. It's the modern standard.- Watch the 10 DNS-lookup limit. SPF allows max 10
include/a/mx/existslookups. Hit that and SPF fails, which is worse than no SPF. SaaS tools like Mailgun, SendGrid, Microsoft 365 each count as 1+. Flatten using tools like dmarcian's SPF flattening service if you go over. - One SPF record per domain. Two TXT records starting with
v=spf1will invalidate each other. Common bug: marketing team adds one, IT adds another, both fail.
DKIM — "this email wasn't tampered with"
DKIM signs every outgoing email with a private key. The receiver fetches your public key from DNS and verifies the signature.
selector._domainkey.yourdomain.com TXT "v=DKIM1; k=rsa; p=MIGfMA0G..."
Key practitioner notes:
- Rotate keys yearly. Use a selector convention like
s2026aands2026bso you can roll without breaking. - 2048-bit keys, not 1024. Microsoft 365 and Google Workspace both moved to 2048 by default. 1024 still works but is deprecated.
- Every sending service signs separately. Microsoft 365 signs with selector
selector1/selector2. Mailgun signs with their selector. Set up DKIM for each independently.
DMARC — "what should receivers do if SPF or DKIM fails?"
DMARC is the policy layer. It tells receiving servers what to do with mail that fails alignment, and (crucially) where to send reports.
_dmarc.yourdomain.com TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com; ruf=mailto:dmarc@yourdomain.com; pct=100; adkim=s; aspf=s"
The right deployment order:
- Start with
p=none— collect reports for 4–6 weeks. You'll discover senders you didn't know about (third-party tools, ex-employees' SaaS apps, etc.) - Move to
p=quarantine— failed mail goes to spam. Monitor reports. Fix any legitimate senders. - Move to
p=reject— failed mail bounces. You should be confident at this point.
I see teams jump straight to p=reject and immediately blackhole their own newsletter. Don't.
Pipe reports into a parser — dmarcian, Postmark DMARC Digests, or roll your own. Without reports DMARC is just a placebo.
Layer 2 — Reputation (where most outbound dies)
Authentication done right means receiving servers can trust you. Reputation determines if they do.
IP warm-up — the most-skipped step
A brand-new sending IP with no history is treated as suspicious. Microsoft 365, Google Workspace, and major filters apply progressively higher trust as the IP demonstrates good behavior over time.
The right warm-up schedule for a new outbound sending IP:
| Day | Volume cap | Notes | |---|---|---| | 1–3 | 20 emails/day | To engaged, opted-in recipients only | | 4–7 | 50 | | | 8–14 | 100 | | | 15–21 | 200 | Open rates should be 50%+ | | 22–30 | 400 | | | Day 30+ | 500–1000/inbox/day | Final steady state |
Going faster gets you flagged. We run this exact ramp at GrowMore Solutions for every new client inbox; bypassing it is the #1 reason teams complain about "Smartlead deliverability."
Bounce rate
If >3% of your emails bounce, mailbox providers throttle you. Real cleanup:
- Pre-send verification — use Neverbounce, ZeroBounce, or Bouncer to clean lists before sending. Catches the catch-alls and typos that won't show in standard validation.
- Suppress hard bounces immediately. Anything in your sending platform that hard-bounced should be permanently suppressed across all campaigns. Many teams suppress in one campaign and forget the global suppression list.
- Re-engage cold lists carefully. Lists older than 6 months need a re-engagement campaign at low volume before any cold send.
Complaint rate
Above 0.1% complaint rate (recipients clicking "this is spam") and you're in trouble fast. Mitigations:
- Honor unsubscribes within seconds, not days. And in every email, not just the campaign that received the request.
- Use List-Unsubscribe headers (
List-Unsubscribe: <mailto:unsub@...>, <https://...>) so one-click unsubscribe works in Gmail / Outlook. - Make unsubscribe one-click. Don't ask for a reason, don't ask to log in.
Feedback loops (FBLs)
Microsoft has Smart Network Data Services (SNDS) and Junk Mail Reporting Program (JMRP). Google has Postmaster Tools. Yahoo has Complaint Feedback Loop. Sign up for all of them with your sending domains; they'll tell you what's happening on the receiving side.
Layer 3 — Content (the part everyone obsesses over)
Less than 20% of deliverability is content, but it matters. Quick list:
- Subject lines. Avoid ALL CAPS, multiple exclamation marks, "Re:" / "Fwd:" prefixes you didn't earn, and aggressive promo language ("FREE", "Act now", "Limited time").
- Text-to-link ratio. A 100-word email with 5 links looks like a campaign. A 100-word email with 1 link looks like a person.
- Don't include unsubscribe links in the body of plain-text-style cold emails. It signals "this is bulk." (For commercial emails to consumers in the US, an unsubscribe is required by CAN-SPAM — but in B2B-to-B2B, a clear opt-out instruction in the signature works and looks more human.)
- Avoid tracking pixels and click-tracking on cold outbound. Or use them sparingly. Heavy tracking is a signal to filters.
Exchange to Microsoft 365 migration
I've migrated Exchange to Exchange Online four times across three companies. The pattern that works:
1. Pre-migration assessment (week 1)
- Run Microsoft's IDFix tool against Active Directory — catch duplicate email aliases, invalid characters
- Map every distribution list, shared mailbox, public folder, retention policy, transport rule
- Test client connectivity from sample users (Outlook, OWA, mobile)
- Inventory third-party integrations: any app sending via SMTP, anything reading mail via IMAP
2. Hybrid setup (weeks 2–3)
- Deploy Azure AD Connect — sync AD identities to Microsoft 365 (don't use cloud-only IDs unless you're greenfield)
- Configure Exchange hybrid via Hybrid Configuration Wizard
- Set up mail flow routing — start with on-prem-centric (all mail flows through on-prem), move to cloud-centric (mail flows through M365) after migration completes
- Configure free/busy federation so calendar sharing works during migration
3. Mailbox migration (weeks 4–8)
- Batch mailboxes by department or function, 50–200 per batch
- Migrate during off-hours — 2 GB mailbox can take 30 min to several hours depending on link speed
- Set MX records to point to M365 only after 90%+ of mailboxes are migrated
- Decommission on-prem Exchange last — keep the management server alive for ~6 months in case you need to make AD-side changes
4. Post-migration hardening (week 9+)
- Conditional Access policies — MFA mandatory, block legacy protocols (POP, IMAP, SMTP basic auth)
- Block legacy authentication entirely. This is the #1 attack vector for Microsoft 365 takeovers.
- Defender for Office 365 — anti-phishing, safe links, safe attachments
- DLP policies — prevent credit card / SSN / API key leakage in outbound mail
- Retention policies — preservation locks for compliance
What I'd change if I were starting today
If I were building email infrastructure for a B2B company from scratch in 2026:
- Skip on-prem entirely. Microsoft 365 from day one, or Google Workspace. The ops overhead of self-hosted Exchange is not worth it.
- Separate sending domains. Your corporate domain for corporate mail (
cpchander.com). A separate domain for outbound (getcpchander.com). A separate domain for transactional (mail.cpchander.com). Reputation is per-domain — protect the corporate one. - DMARC
p=rejectwithin 90 days. Phishing your own brand is a real cost. Get to reject fast. - One sending platform per use case, not five. Marketing (one tool), outbound sales (one tool), transactional (one tool). Don't sprawl.
- Pay for DMARC reporting — dmarcian or similar. The free path leaves you blind.
Use cases — what email infrastructure actually does for the business
Use case 1 — Surviving the COVID transition (Exchange hybrid + Microsoft 365)
When 1,200 employees moved to working from home in March 2020 (the full transition playbook), Exchange hybrid mode was a non-event. Outlook on every laptop connected over the internet to Exchange Online; archive-tier mail still sat on the on-prem Exchange and was accessible via Outlook Cached Mode. Mobile users on iPhones/Androids picked up via ActiveSync without any reconfiguration. A migration that had felt like over-investment three years earlier turned out to be the reason email kept working seamlessly through a crisis.
Use case 2 — Recovering from a phishing-led brand-spoofing incident
In 2018 we detected that our brand was being spoofed in phishing emails sent to client contacts — "from" our domain, asking for invoice payment changes. Without DMARC enforcement, the receiving mail servers happily delivered these to our clients' inboxes. The fix:
- Within 48 hours: deployed DMARC
p=nonewithruareporting - Two weeks later: analyzed reports, identified ~12 legitimate senders we'd missed in SPF
- Six weeks after that: moved DMARC to
p=quarantine - Three months in: moved to
p=reject
Result: brand-spoofing volume dropped to effectively zero. Three client-impacting phishing events in the prior year became zero in the year after. DMARC saved us from reputational damage that no amount of post-incident apology could have fully repaired.
Use case 3 — Outbound deliverability for a high-volume agency client
For a B2B SaaS client running cold outbound, deliverability had been at ~12% inbox placement. We took over their email infrastructure:
- Set up two new sending domains (one per ICP) with proper SPF/DKIM/DMARC
- Configured 30 inboxes per domain, each starting at 20 emails/day, scaling per the warm-up schedule
- Migrated their sending platform to Smartlead with proper EHLO/PTR records
- Implemented Postmark DMARC monitoring with daily report parsing
- Added a Mailgun fallback for transactional traffic
Within 90 days inbox placement was at ~88%. Reply rates 4x'd. Their pipeline doubled in a quarter without changing the copy. Deliverability is a technical problem, not a marketing problem.
Use case 4 — A vendor portal exposing client emails
In 2019 a vendor portal had a bug where invoice notifications were spoofing our domain. Without DMARC, those emails would have hit our clients' inboxes and our brand reputation would have taken the hit. With DMARC p=quarantine active, the receiving filters caught it, and our DMARC report identified the vendor's IPs within 24 hours. We notified the vendor, who fixed the bug in 48 hours. Without DMARC reporting we'd have never known. With it, we caught a security incident before it became a client issue.
Use case 5 — Exchange to Microsoft 365 migration (the playbook in production)
We ran the Exchange-to-M365 migration during a 12-week window in 2019. Concrete numbers:
- 1,500 mailboxes, average size 4 GB, total ~6 TB
- Migration batches of 100–150 mailboxes per week
- Pre-migration cleanup removed ~800 GB of duplicate/legacy data
- Three batches required rollback and re-runs for permission inheritance issues
- Zero client-facing email outage during the migration
- ~30% of users adopted Teams within 90 days of M365 access
The migration was uneventful because we'd spent weeks on the assessment. The hours invested before cutover are the hours not spent firefighting after.
The takeaway
Email deliverability is infrastructure first, copy second. Authentication done right, reputation built carefully, content tuned. Get the first two right and the third becomes a knob you can turn. Skip them and no copy in the world will save you.
If you're running outbound and your reply rates are under 2%, it's almost never the copy. It's the deliverability foundation.