Cold Email Lead Recovery
A two-workflow n8n system that recovers emails Apollo/Apify couldn't find and drafts personalized cold outreach for every lead.
Section One
What This Solves
A lead scrape isn't the same thing as a contactable lead. Apollo and Apify return names, titles, and companies reliably — but a working email address for every row is the exception, not the rule. Most teams either throw the emailless rows away or chase them down by hand, one LinkedIn search at a time.
This build treats "no email" as a solvable problem instead of a dead end. The base workflow (M7L3) writes a personalized cold email for every lead that already has an address. The recovery workflow (M7L4) wraps around it: any lead missing an email gets a shot at a LinkedIn URL lookup, and if that comes up empty, a company-domain lookup, before it's ever counted as a loss.
Fig. 1 — recovery chain
Start
Lead scrape
Apollo/Apify — most rows missing email
Try 1
LinkedIn lookup
Anymail Finder, only if no email
Try 2
Domain lookup
Anymail Finder, only if LinkedIn failed
Write
Draft saved
Ready for review, nothing sends itself
Why the fallback chain matters
Every lookup step only fires when the one before it fails, and each one is cheaper and less reliable than the last — LinkedIn lookup before domain lookup, both only after the free scrape data comes up short. That ordering means the system never pays for a lookup it didn't need, and no lead gets dropped just because Apollo couldn't find an address on the first pass.
Section Two
What You Need
▸ Prerequisites
- Google Sheet pointed at your Apollo/Apify export (Full Name, Email, Title, Company Domain, LinkedIn URL)
- Airtable Leads table set up with matching fields
- Anymail Finder account and API key
- Google Sheets, OpenAI, Airtable, and Anymail Finder credentials added in n8n
- Claude connected to n8n via the MCP connector
▸ The Stack
What doesn't change. Both workflows write drafts, not sends. The email that goes to a real inbox is still a human decision — this system just makes sure every lead has a personalized draft waiting, whether or not Apollo handed you a usable address to start with.
Section Three
Step-by-Step Build
01
Step One
Connect Claude to n8n
In n8n: Settings, then n8n API, create an API key. In Claude (claude.ai): Settings, Connectors, Add custom connector, name it n8n, and use your instance MCP URL: https://YOUR-INSTANCE.app.n8n.cloud/mcp-server/http with the API key. Once connected, Claude can create, edit, run, and debug workflows in your account.
02
Step Two
Two-minute prerequisites
Point a Google Sheet at your Apollo/Apify export with columns for Full Name, Email, Title, Company Domain, and LinkedIn URL. Create an Airtable base with a Leads table (Full Name, Email, Title, Outreach Message Subject, Outreach Message Email Body). Sign up for Anymail Finder and grab your API key. Add all four credentials in n8n: Google Sheets OAuth2, OpenAI, Airtable Personal Access Token, and a Header Auth credential named anymail-finder-api-key.
03
Step Three
Paste the build prompt
Open a Claude chat with the n8n connector on, paste the prompt below with your values filled in, then paste the system prompt from the following step when Claude asks for it. Watch it work — a full build takes a few minutes.
Copy this: the build prompt
Connect to my n8n and build a workflow called Cold Email Lead Recovery. My values: Google Sheet ID = [YOURS], Airtable base ID = [YOURS], Airtable table = Leads.
The system, in order:
1. Manual trigger, run on demand.
2. Get Apollo Leads: Google Sheets read of my scrape, columns Full Name, Email, Title, Company Domain, LinkedIn URL.
3. Has Email? switch:
- Has email -> skip to step 5.
- No email -> Has LinkedIn URL? switch:
- Yes -> Find Email By LinkedIn: Anymail Finder linkedin-url.json lookup. Match -> go to step 5. No match -> continue to the next branch, don't stop.
- No (or the LinkedIn lookup failed) -> Has Company Domain? filter -> Find Email By Domain: Anymail Finder person.json lookup (domain + full name). Match -> go to step 5. No match -> this lead has no path left, log it and move on.
4. Merge every branch that found an email back into one path.
5. Limit For Testing: cap the run at 5 leads while testing.
6. Loop Over Leads: one lead at a time so a bad row never blocks the batch.
7. Scrape Company Website: pull raw text off the lead's domain for context, continue on error so a dead site never kills the run.
8. Write Cold Email: an OpenAI node (GPT-4.1-mini) using the system prompt I will provide. Return strict JSON: {"subject": "...", "emailBody": "..."}, 70-100 words, always closing with my booking link.
9. A code node that parses that JSON and fails loudly if the reply isn't valid JSON.
10. Save Draft To Airtable: write Full Name, Email, Title, Outreach Message Subject, Outreach Message Email Body.
Use my existing n8n credentials for Google Sheets, OpenAI, Airtable, and the anymail-finder-api-key header credential. Remember every dynamic value in n8n needs the = expression prefix. Build it, then validate it, and tell me what you built before running anything.04
Step Four
Paste the system prompt
This is the asset. The build creates the writer node empty; this prompt is what makes every draft sound like you instead of a template. Replace the bracketed lines with your name, background, business, and audience.
Copy this: system prompt
You write cold outreach emails for [NAME], a [YOUR BACKGROUND] who runs [YOUR BUSINESS], reaching out to [YOUR AUDIENCE].
Voice: direct, practical, zero hype, no emojis, no generic flattery. Reference something specific from the company site text you're given, not just the lead's title.
Structure: one-line hook naming a specific operational reality for their business, two or three sentences connecting it to what you do, one soft ask ending in a link to a 30-minute audit call.
70 to 100 words. Return ONLY valid JSON, no markdown fences, exactly this shape:
{"subject":"...", "emailBody":"..."}
Never invent facts about the company that aren't in the site text you're given. If the site scrape failed or came back empty, write a slightly more generic version rather than guessing at specifics.Why the ban matters
"Never invent facts about the company" is the trust anchor. A wrong guess about someone's business reads as sloppy before it reads as personalized — this line is what keeps you comfortable sending a draft without fact-checking it line by line first.
05
Step Five
Test it
Paste the test prompt below. Claude runs the workflow, reads its own execution logs, and repairs whatever breaks. You never open an error message yourself.
Copy this: the test prompt
Run the workflow manually with a small batch that includes at least one lead with an email already and one without. Check the execution: if any node failed, read the error, fix the node, and run it again. Repeat until you see a draft land in Airtable for both cases. Do not activate this on a schedule; it's a run-on-demand tool. Summarize what happened at each branch.
Why this works
A draft landing in Airtable for a recovered lead IS the test passing. Everything upstream — the switch logic, the Anymail Finder credential, the writer node — had to work for that row to exist, so one visible result verifies the whole chain.
06
Step Six
Once it looks right
Raise Limit For Testing past 5 once the drafts read well, then swap in your real Apollo/Apify export. This stays a manual, run-on-demand tool by design — nothing emails anyone until you review the draft yourself.
| Lead Arrives With | What Runs | Cost | Outcome |
|---|---|---|---|
| A usable email | Base flow only — scrape, write, save | OpenAI tokens only | Draft saved |
| No email, has LinkedIn URL | Anymail Finder LinkedIn lookup, then base flow | 1 credit on verified match | Draft saved, or falls to domain lookup |
| No email, no LinkedIn, has domain | Anymail Finder domain + name lookup, then base flow | 1 credit on verified match | Draft saved, or no draft |
| No email, no LinkedIn, no domain | Nothing left to try | Free | No draft — genuinely unrecoverable |
Where this plugs in
The Airtable landing spot is deliberately swappable. Point the same "save draft" step at Instantly or SmartLead once you're ready to send straight from the workflow instead of reviewing in Airtable first — the personalization and recovery logic upstream doesn't change either way.
Section Four
Where This Goes Next
The branching design is what makes this easy to extend. Everything downstream of "lead has an email" is one shared path, so upgrades to the recovery side never touch the writing side and vice versa.
Add a third recovery tier (company switchboard, generic-alias guess) without touching the personalization logic. Swap GPT-4.1-mini for a larger model on higher-value segments only. Or connect the save step directly to a sending tool once drafts are consistently good enough to skip manual review — the same upgrade path every Soulwire build follows once it's earned the trust.
“A draft landing in Airtable for a recovered lead IS the test passing. Everything upstream had to work for that row to exist.”
— Cold Email Lead Recovery, p. 7
§ Fin.
Rather have it built for you?
This guide is one system from the Soulwire Studio workflow library. We build AI automations for businesses that run on process: intake, scheduling, proposals, compliance-heavy operations. If you'd rather spend your time closing deals than debugging lead gen, book an audit and we'll find the automation hiding in your business.

