Cold email is email to someone with no prior relationship — 35% open and 8% reply is great, but 50% bounce kills your domain. This complete guide shows the 4-part anatomy that fits mobile (subject <50 chars + opener + value + CTA under 100 words), one real personalization line that beats merge-tag spam, why verify first, and a 4-touch follow-up that triples replies — with deliverability plain text vs HTML.
- Anatomy (under 100 words): Subject <50 chars + Opener 1 line real personalization + Value 1-2 lines you-focused + CTA low friction + PS proof. Example: "quick idea for Acme" → "Saw your post on pricing tiers — smart freemium take." → "Noticed Acme drives 20K visits but demo 1.2% — we helped [Similar] lift to 2.8% in 14 days." → "Worth a 15-min chat Tuesday 10am? If not, who owns this?"
- Personalize: One real signal (LinkedIn post, hiring page, pricing, launch, mutual) in 2 min — not
Hi {{FirstName}}, I see you are CEO at {{Company}}generic → delete. - Verify first: Check MX exists? SMTP handshake? Catch-all? Disposable? Bounce >5% → blacklisted. Verify list via our email verifier (MX/SMTP/catch-all → valid/risky/invalid → suppress risky/invalid before send → 5% → 0.5% bounce) and warm SPF+DKIM+DMARC.
- Follow-ups ×3: Day 0 value, Day 3 bump "any thoughts?" 7 words, Day 7 new value (case), Day 14 breakup "closing file" — each 2-3 lines, new angle. 80% of replies come after follow-up.
- Deliverability: Plain text beats HTML for cold (no image/link overload), warm domain, no FREE!!! spam triggers, thread vs new test. Target open 35-50% good, reply 8-12% great, bounce <2%, spam <0.1%.
What Is a Cold Email — Permission vs Spam Boundary
Cold email is unsolicited but targeted B2B outreach to a person with no prior opt-in, unlike newsletter opt-in. Legal via CAN-SPAM (US, FTC) if no deceit, truthful From/Subject, physical address, clear opt-out, and honor within 10 days; GDPR needs legitimate interest + DPA and easy unsubscribe, per GDPR email. It's sales, not spam, when relevant, researched, and low volume — blasting 10K generic is spam. See FTC CAN-SPAM Guide.
Benchmarks: open 35-50% good (subject + sender rep), reply 8-12% great (value+target), bounce must be <2% (verify), spam complaint <0.1% (Google Postmaster). If bounce >5%, stop — domain reputation tanks.
Why 100 Words Max
Mobile preview shows subject + ~40 chars + 2 lines (≈30 words) before scroll — 100 words fits 2 scrolls. Longer → skim → delete. 75-100 words is sweet spot per Lavender 2024 data (reply 12% at 50-100 vs 6% at 200).
Anatomy — Subject, Opener, Value, CTA (Example Ready to Send)
Subject: quick idea for Acme # <50, lower case, no spam
Hi {{Name}},
Saw your post on pricing tiers — smart take on freemium. (1 line, real signal)
Noticed {{Company}} drives ~20K visits/mo (Similarweb) but demo 1.2% — we helped [Similar SaaS] lift demo to 2.8% in 14 days by adding one pricing calculator. (1-2 lines, you-focused, proof type)
Worth a 15-min chat Tuesday 10am PT? If not, who owns pricing conversion? (low friction + alternative)
— {{Your Name}}
P.S. Case: [Similar] +1.6% in 2 weeks — happy to share tear-down.
Why it works: subject curiosity + company, opener proves research, value is metric + similar proof (not "we are leading"), CTA is yes/no with time and escape hatch "who owns this?" → reply even if not interested. PS proof add without clutter — many read PS before body.
Thread vs New Follow-Up
Thread keeps context (shows original), new may dodge spam filter if thread flagged — test 50/50 per campaign.
Subject Lines — 35% Open Starts Here (<50 Chars, No Spam)
Do: lower case, <50 chars (mobile shows ~40), company or name, question or idea — quick idea for Acme (22 chars), pricing tiers — question (28), intro: {{Name}} / {{Company}} (personal). Add Re: only if true reply — fake Re: is deceit per CAN-SPAM.
Avoid: All caps ACT NOW, FREE!!! 100% Guarantee, 3 links, image-only, misleading Re:/Fwd:. Spam filters score via SpamAssassin. A/B test: 50/50 quick idea for Acme vs Acme + [Similar] case → measure open 35% vs 42% → keep winner via Litmus preview.
Preview Text
Second line after subject in inbox — set first 40 chars of body as preview: opener line is preview. So opener is subject's partner — don't waste with "Hope you are well".
Personalize — One Real Line Beats Merge Tag Spam
Bad: Hi {{FirstName}}, I see you are CEO at {{Company}} — we help CEOs like you... → template detected, delete. Good: Saw your post on pricing tiers — smart freemium take, especially the annual vs monthly math. → took 2 min to find signal, proves research, reply.
Signal sources in 2 min: recent LinkedIn post or comment, podcast quote, hiring page (hiring SDRs → need pipeline), pricing page (freemium tiers), recent launch (Product Hunt), mutual connection (intro via X), or tech stack (BuiltWith shows Stripe). One specific signal beats three generic merges. Scale: research 20 high-value accounts deeply, not 1K shallow.
Scale Without Spam
Template 80% (value+CTA) + 20% custom opener. Tool fills opener per lead from Sheet column opener. Don't automate opener via AI generic — "I love your innovative company" is detectable.
Verify First — MX, SMTP, Catch-All, Disposable (Bounce Kills Domain)
Send to invalid → bounce → ESP (Gmail) sees 5% bounce → throttles → spam folder → domain blacklisted via Google Postmaster reputation. Verifier checks per address:
- MX record exists? Domain has mail server? No MX → invalid.
- SMTP handshake?
RCPT TO:without sending →250 okvs550 no such user. - Catch-all? Domain accepts any address → risky (may be invalid but accepts). Mark risky.
- Disposable?
tempmail.com→ disposable → risky.
Upload CSV → tool returns valid/risky/invalid → suppress risky+invalid before send → list 5% bounce → 0.5% after. Our email verifier does MX/SMTP/catch-all/disposable → valid/risky/invalid. Do this before first send, not after bounce.
Deliverability Stack
SPF (v=spf1 include:_spf.google.com), DKIM (sign), DMARC (p=quarantine) via DNS — warm domain 2 weeks with small sends (50/day → 500/day). Plain text beats HTML for cold (no image, no link overload — 1 link max). Warm-up via gradual volume, not blast.
Follow-Ups — 80% of Replies Come After Follow-Up (4-Touch Sequence)
Day 0: Email 1 — value as above
Day 3: Subject: Re: quick idea for Acme
Body: Any thoughts, {{Name}}?
— 7-word bump often beats rewrite (Wainer 2023: bump reply 18%)
Day 7: New value
Subject: {{Company}} + [Similar] pricing tear-down
Body: Loom 1-min tear-down of pricing page — 2 tweaks.
Link: https://loom.com/...
Day 14: Breakup
Subject: Closing file on Acme?
Body: {{Name}}, should I close file on Acme? If pricing not priority now, who owns it for later? (permission to exit → reply even if no)
Each 2-3 lines, new angle, no "just following up" alone (adds no value). Thread vs new: thread keeps context (shows original), new may dodge thread filter — test 50/50. Stop after 4 touches if no reply — 6th is spam. Track via sequencer (Lemlist/Instantly) with plain text.
Breakup Psychology
"Closing file" triggers loss aversion — recipient replies "not now but in 3 months" → pipeline, vs silence.
Pitfalls — Spam Triggers, Legal, and Metrics
| Pitfall | Fix |
|---|---|
| All caps, FREE!!!, 3 links | Lower case, 1 link max, no image |
| No physical address | Footer: "Acme, 123 Main St, SF, CA" per CAN-SPAM §316 |
| No opt-out | "PS. If not relevant, reply STOP and I'll close file" — honor in 10 days |
| GDPR without legit interest | B2B legit interest doc + DPA + easy unsubscribe per GDPR |
| Bounce >5% | Verify before send, suppress risky/invalid — see verifier above |
Legal: CAN-SPAM requires no header deceit, no deceptive subject, physical address, clear opt-out, honor 10 days. GDPR B2B needs legitimate interest assessment, data processing agreement, easy unsubscribe, and data retention policy. Always include: "If not relevant, reply STOP and I'll close file" — reduces spam complaints vs no opt-out (complaint <0.1% target). Metrics: open 35-50% good (subject+reputation), reply 8-12% great (value+target), bounce <2%, spam <0.1% (Postmaster). If open 15% → subject or deliverability, if reply 2% → value or targeting.
Plain Text Beats HTML for Cold
HTML with logo, banner, 3 links → spam filter + image blocked → plain text with 1 link → inbox. Save HTML for newsletter opt-in.
Research — 2 Minutes to One Real Line (Not Merge Tag)
Generic Hi {{FirstName}}, I see you are {{Title}} at {{Company}} — we help {{Industry}}... is detectable template in 340,000 inboxes daily — delete. Real signal takes 2 min per lead:
- LinkedIn: recent post or comment → "Saw your post on pricing tiers — smart freemium math on annual vs monthly."
- Company: pricing page (tiers = freemium insight), hiring page (hiring 3 SDRs → need pipeline), launch (Product Hunt), tech stack (BuiltWith shows Stripe → billing pain).
- Mutual: "Intro via {{Mutual}}?" → reply even if not interested.
One specific line beats three generic merges. Scale 20 high-value deep, not 1K shallow. Use Sheet column opener per lead, tool fills.
Example — Good vs Bad Opener
Bad: "I see you are CEO at Acme — we help CEOs like you scale." Good: "Saw Acme hired 2 SDRs last week — congrats. Many at that stage see demo queue but low conversion."
Value Proposition — You-Focused, Metric, Similar Proof
Not "We are leading AI platform..." — that's you-focused. You-focused: "Noticed Acme drives ~20K visits/mo (Similarweb) but demo 1.2% (heuristic) — we helped [Similar SaaS, 50 similar visits] lift demo to 2.8% in 14 days by adding one pricing calculator." Why it works: metric (20K, 1.2%→2.8%), similar proof (same vertical/size), time-bound (14 days) — not claim. No superlative needed. PS proof: "P.S. Case: [Similar] +1.6% in 2 weeks — tear-down: link"
How to Find Similar Proof Quickly
Case study library: vertical + size + metric. If you have no case, use teardown: "Noticed pricing page lacks annual toggle proof — adding one lifted [Public Case] 1.5% per Optimizely." Value is insight, not brag.
CTA — Low Friction Yes/No With Alternative
Bad CTA: "Are you free for a call?" → easy no, no alternative. Good CTA: "Worth a 15-min chat Tuesday 10am PT? If not, who owns pricing conversion?" → two paths to reply: yes or referral. Both count. Alternative CTA is referral, not "let me know" — "who owns this?" gets reply even if not interested.
Time: propose one time (Tuesday 10am PT) plus alternative "If not, does Thursday work?" — not "when are you free?" (open-ended).
Deliverability Stack — SPF, DKIM, DMARC, Warm-Up, Plain Text
Verify list is step 1, but stack matters:
- SPF:
v=spf1 include:_spf.google.com ~allauthorizes sender IP via DNS — see Google SPF. - DKIM: sign with private key — header
DKIM-Signatureproves domain signed. - DMARC:
v=DMARC1; p=quarantine; rua=mailto:dmarc@example.comtells receiver to quarantine fails — see DMARC. - Warm-up: new domain 50/day week1 → 100/day week2 → 500/day week4 — sudden 1K blast → spam. Use gradual.
- Plain text: cold HTML with logo/banner/3 links → spam filter (image ratio) + image blocked → plain text 1 link max → inbox per Litmus.
Check reputation via Google Postmaster and Microsoft SNDS after verify.
List Building — Where to Find Emails to Verify
Apollo, Hunter, LinkedIn Sales Navigator → export CSV → verify via verifier before sequencer. Never scrape and blast — scrape then verify then personalize. Verify step removes 5-15% invalid/disposable/catch-all → bounce down. See Hunter find.
CSV 1K emails → email verifier → valid 850 / risky 80 / invalid 70 → suppress risky+invalid → send to 850 → bounce 0.5% vs 5% before
Suppress risky+invalid — don't risk catch-all 50% bounce.
A/B Testing — Subject, Opener, Value (One Variable)
Don't test 3 variables at once — isolate. Test 50/50: Subject quick idea for Acme vs Acme + [Similar] case → open 35% vs 42% → keep winner. Next test opener Saw your post vs Saw Acme hiring 2 SDRs → reply 8% vs 12% → keep hiring signal. Next test CTA Tuesday 10am? vs Who owns this? → referral rate. One variable per 100 sends, measure via sequencer A/B. See Litmus for preview text test.
Preview Text Test
Preview is 40 chars after subject — first 40 of body. So opener is preview. Test opener as preview via subject+preview pair.
Metrics — Open, Reply, Bounce, Spam (What Each Tells)
| Metric | Good | Tells | Fix if Bad |
|---|---|---|---|
| Open | 35-50% | Subject + rep | Subject <50, no spam, warm domain |
| Reply | 8-12% | Value + targeting | Value line + similar proof, one signal |
| Bounce | <2% | List quality | Verify list before send |
| Spam <0.1% | <0.1% | Relevance + opt-out | Add "reply STOP", targeting, plain text |
If open 15% → subject or deliverability (check Postmaster, SPF). If reply 2% → value or targeting (opener generic). Track per campaign via sequencer dashboard.
Legal Deep — CAN-SPAM, GDPR Legitimate Interest, and Unsubscribe
CAN-SPAM (US, FTC): no header deceit (From: Acme <hi@acme.com> truthful), no deceptive subject (no fake Re:), physical address in footer ("Acme, 123 Main St, SF, CA 94105"), clear opt-out ("If not relevant, reply STOP and I'll close file" counts), honor within 10 business days. Penalty $50K per email. See FTC CAN-SPAM.
GDPR (EU): B2B legitimate interest requires 3-part test (purpose, necessity, balance) + Data Processing Agreement + easy unsubscribe + data retention (delete after 30 days if no reply) + record of interest assessment. B2C opt-in required. Always include physical address and opt-out per GDPR Recital 47. Add footer: "Acme, 123 Main St, SF, CA — reply STOP to opt out". Honor STOP, suppress 5 years.
Do Not Email Without Physical Address
Footer must have valid postal: "Acme, 123 Main St, San Francisco, CA 94105, USA" — PO Box ok. Free Gmail from @gmail.com without address is technically CAN-SPAM violation — use domain + address.
Newsletter opt-in: prior consent, double opt-in, list hygiene. Cold email: no prior consent, but legit interest + relevant + opt-out. Don't mix lists — cold to opted-in harms.
Common Mistakes — 5 Before You Hit Send
| Mistake | Fix |
|---|---|
| 200-word essay | Cut to 75-100 words — mobile 2 scrolls max |
| 3 links + image | 1 link max, plain text, no image for cold |
| No physical address | Footer with address per CAN-SPAM |
| Blast 1K/day new domain | Warm 50→500/day over 4 weeks, verify first |
| Generic opener | One real signal in 2 min — not {{FirstName}} merge |
From Cold to Warm — After Reply, Switch Playbook
Reply is permission — switch from cold plain text to warm: add calendar link, deck, or Loom. Don't keep cold cadence — reply should be human, not sequencer. Track via CRM (HubSpot) after reply — stop sequencer immediately on reply to avoid "just following up" after they replied.
Bonus: keep cold email templates versioned — v1 opener, v2 value → git diff shows which line lifted reply 8%→12%.
Record Keeping — Version and Validate in Sequencer
Keep templates versioned — subject-v1.txt 35% open → v2 42% open → commit message "subject: quick idea → Acme + Similar case, +7% open". Link sequencer dashboard to git — when reply dips, diff shows which opener changed. Add pre-send hook: verifier must pass (<2% invalid) before sequencer allows send — fail CI if list has >5% risky.
Use cold email checklist before send: subject <50, opener real, value one metric, CTA low friction, PS proof, plain text, 1 link, address, opt-out — then verify list.
Copy working quick idea for {{Company}} subject template — one correct reused beats four hand-typed with different spam triggers.
Validate early, fail fast before send — not after bounce when domain blacklisted.
Tip: keep cold email templates versioned — v1, v2 — so git diff shows which subject lifted open 35%→42%.
Keep one source — committed template.txt for sequencer, plain text, 1 link — choose per campaign.
Version your cold email — v1 opener, v2 value → git diff shows which line lifted reply 8%→12%.
Keep one source — committed cold-email-template.txt for sequencer — so history shows who changed what when reply dipped.
Validate early, fail fast before send — not after bounce when domain blacklisted and sequencer paused.
Keep one source — plain text template with 1 link — choose per campaign, not per send.
Version your cold email — v1, v2 — so git diff shows which subject lifted open 35%→42%.
Keep one source — committed template with opt-out — so history shows who changed what when spam dipped.
Validate early — verify list before send, not after bounce.
Frequently Asked Questions
How long should a cold email be?
75-100 words, 4 parts (subject <50 chars, opener 1 line, value 1-2 lines, CTA 1 line) + PS. Mobile shows 2 lines before scroll — 100 words fits without scroll. Longer → skim → delete.
What is a good open rate for cold email?
35-50% good (subject + sender reputation via SPF/DKIM/DMARC warm-up); cold average 20% without. Reply 8-12% great, 3-5% avg. Bounce must be <2% or domain blacklisted — verify first.
How many follow-ups should I send?
3 follow-ups over 14 days (Day 3 bump, Day 7 new value, Day 14 breakup) → 4 touches total → 80% of replies after follow-up. Stop after 4 if no reply — 6th is spam.
Should cold emails be plain text or HTML?
Plain text for cold (no image, 1 link max) → inbox vs spam. HTML with logo/banner → spam filter + image blocked. Save HTML for opt-in newsletter.
Is cold email legal under GDPR?
B2B with legitimate interest, data minimization, easy unsubscribe, DPA, and retention policy — yes per GDPR Recital 47. B2C opt-in required. Always include physical address and opt-out per CAN-SPAM.
Why did my cold email go to spam?
Top 3: bounce >5% (verify), spam triggers (All caps, FREE!!!, 3 links), missing SPF/DKIM/DMARC or new domain not warmed. Check Google Postmaster reputation, fix verify list, warm 50→500/day, use plain text.