All Tools View Categories Blog About Contact Privacy

How to Write Cold Emails That Actually Get Replies (Complete Guide)

How to Write Cold Emails That Actually Get Replies (Complete Guide)

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.

TL;DR — Cold Emails That Get Replies:
  • 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.

Cold email anatomy subject opener value CTA under 100 words

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)

Subject lines do and avoid spam triggers

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

Personalize real signal vs merge tag generic

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)

Verify MX SMTP catch-all disposable bounce deliverability

Send to invalid → bounce → ESP (Gmail) sees 5% bounce → throttles → spam folder → domain blacklisted via Google Postmaster reputation. Verifier checks per address:

  1. MX record exists? Domain has mail server? No MX → invalid.
  2. SMTP handshake? RCPT TO: without sending → 250 ok vs 550 no such user.
  3. Catch-all? Domain accepts any address → risky (may be invalid but accepts). Mark risky.
  4. 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)

Follow-up sequence day 0 3 7 14 bump breakup
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

Pitfalls spam triggers legal metrics open reply bounce
PitfallFix
All caps, FREE!!!, 3 linksLower case, 1 link max, no image
No physical addressFooter: "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 interestB2B 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:

  1. LinkedIn: recent post or comment → "Saw your post on pricing tiers — smart freemium math on annual vs monthly."
  2. Company: pricing page (tiers = freemium insight), hiring page (hiring 3 SDRs → need pipeline), launch (Product Hunt), tech stack (BuiltWith shows Stripe → billing pain).
  3. 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 ~all authorizes sender IP via DNS — see Google SPF.
  • DKIM: sign with private key — header DKIM-Signature proves domain signed.
  • DMARC: v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com tells 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.

Verify Flow — Before First Send:
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)

MetricGoodTellsFix if Bad
Open35-50%Subject + repSubject <50, no spam, warm domain
Reply8-12%Value + targetingValue line + similar proof, one signal
Bounce<2%List qualityVerify list before send
Spam <0.1%<0.1%Relevance + opt-outAdd "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.

Cold Email vs Newsletter — Legal Different:

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

MistakeFix
200-word essayCut to 75-100 words — mobile 2 scrolls max
3 links + image1 link max, plain text, no image for cold
No physical addressFooter with address per CAN-SPAM
Blast 1K/day new domainWarm 50→500/day over 4 weeks, verify first
Generic openerOne 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% openv2 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.