This workflow corresponds to n8n.io template #17126 — we link there as the canonical source.
This workflow follows the Chainllm → Gmail recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "gS5iqNgP6cxdagf6",
"meta": {
"builderVariant": "mcp",
"aiBuilderAssisted": true
},
"name": "Find and verify business emails then draft AI icebreakers in Google Sheets",
"tags": [],
"nodes": [
{
"id": "02c42d42-7fc7-4d18-8bf3-6aadd35e78f9",
"name": "Run email enrichment",
"type": "n8n-nodes-base.manualTrigger",
"position": [
352,
-288
],
"parameters": {},
"typeVersion": 1
},
{
"id": "8f72beff-8460-428e-9377-7469efeb2485",
"name": "Configuration",
"type": "n8n-nodes-base.set",
"position": [
528,
-288
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "c1",
"name": "scrapercity_finder_url",
"type": "string",
"value": "https://app.scrapercity.com/api/v1/email-finder"
},
{
"id": "c2",
"name": "scrapercity_status_url",
"type": "string",
"value": "https://app.scrapercity.com/api/v1/scrape/status/"
},
{
"id": "c3",
"name": "scrapercity_download_url",
"type": "string",
"value": "https://app.scrapercity.com/api/downloads/"
},
{
"id": "c4",
"name": "poll_wait_seconds",
"type": "number",
"value": 30
},
{
"id": "c5",
"name": "max_status_checks",
"type": "number",
"value": 20
},
{
"id": "c6",
"name": "ai_model",
"type": "string",
"value": "gpt-4o-mini"
},
{
"id": "c7",
"name": "icebreaker_language",
"type": "string",
"value": "English"
},
{
"id": "c8",
"name": "your_offer",
"type": "string",
"value": "AI automation that saves teams hours of manual work every week"
},
{
"id": "c9",
"name": "notify_email",
"type": "string",
"value": "you@example.com"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "5cec08cc-4b2a-4223-8ead-08cc408b2e4a",
"name": "Get contacts from Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
784,
-288
],
"parameters": {
"sheetName": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultName": "contacts"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultName": "Select your input spreadsheet"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "57aea303-d10d-4ba3-b4ac-5bee94d0cc30",
"name": "Build contacts payload",
"type": "n8n-nodes-base.aggregate",
"position": [
1040,
-288
],
"parameters": {
"include": "specifiedFields",
"options": {},
"aggregate": "aggregateAllItemData",
"fieldsToInclude": "firstName, lastName, domain",
"destinationFieldName": "contacts"
},
"typeVersion": 1
},
{
"id": "9ac3d760-7d21-4fc1-9711-1fefa687b09b",
"name": "Submit to ScraperCity",
"type": "n8n-nodes-base.httpRequest",
"position": [
1328,
-288
],
"parameters": {
"url": "={{ $('Configuration').item.json.scrapercity_finder_url }}",
"method": "POST",
"options": {},
"jsonBody": "={{ { \"contacts\": $json.contacts } }}",
"sendBody": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.4
},
{
"id": "6fb9f182-f659-4e4f-9f00-e96c9317443f",
"name": "Wait before status check",
"type": "n8n-nodes-base.wait",
"position": [
1536,
-288
],
"parameters": {
"amount": "={{ $('Configuration').item.json.poll_wait_seconds }}"
},
"typeVersion": 1.1
},
{
"id": "6ffe8942-59b6-44ee-9caa-8eed4987b069",
"name": "Check job status",
"type": "n8n-nodes-base.httpRequest",
"position": [
1728,
-288
],
"parameters": {
"url": "={{ $('Configuration').item.json.scrapercity_status_url }}{{ $('Submit to ScraperCity').item.json.runId }}",
"options": {},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.4
},
{
"id": "3799a51a-f00f-436b-957b-65a8bb3f03e8",
"name": "Route by job status",
"type": "n8n-nodes-base.switch",
"position": [
1904,
-304
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "completed",
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "SUCCEEDED"
}
]
},
"renameOutput": true
},
{
"outputKey": "stopped",
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "or",
"conditions": [
{
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.status }}",
"rightValue": "FAILED"
},
{
"operator": {
"type": "number",
"operation": "gte"
},
"leftValue": "={{ $runIndex }}",
"rightValue": "={{ $('Configuration').item.json.max_status_checks }}"
}
]
},
"renameOutput": true
}
]
},
"options": {
"fallbackOutput": "extra",
"renameFallbackOutput": "still processing"
}
},
"typeVersion": 3.4
},
{
"id": "a50d98f0-125e-4804-987c-29674cf58c63",
"name": "Download results",
"type": "n8n-nodes-base.httpRequest",
"position": [
2480,
-320
],
"parameters": {
"url": "={{ $('Configuration').item.json.scrapercity_download_url }}{{ $('Submit to ScraperCity').item.json.runId }}",
"options": {
"response": {
"response": {
"responseFormat": "file"
}
}
},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"typeVersion": 4.4
},
{
"id": "7b0e656f-5c0b-4f7b-85dd-e3900e4fdb17",
"name": "Extract results from CSV",
"type": "n8n-nodes-base.extractFromFile",
"position": [
2672,
-320
],
"parameters": {
"options": {
"headerRow": true
}
},
"typeVersion": 1.1
},
{
"id": "a5e8fcc1-1af7-4c40-893a-eada476a3019",
"name": "Normalize result fields",
"type": "n8n-nodes-base.code",
"notes": "Code node used to map ScraperCity CSV headers onto a stable schema so downstream nodes are deterministic.",
"position": [
2896,
-320
],
"parameters": {
"jsCode": "const pick = (obj, keys) => {\n for (const k of Object.keys(obj)) {\n if (keys.includes(String(k).toLowerCase().trim())) return obj[k];\n }\n return '';\n};\nreturn $input.all().map(({ json }) => ({\n json: {\n firstName: pick(json, ['firstname','first_name','first name','first']),\n lastName: pick(json, ['lastname','last_name','last name','last']),\n domain: pick(json, ['domain','company_domain','company domain','website']),\n email: pick(json, ['email','email_address','work_email','business_email']),\n status: pick(json, ['status','verification_status','verification','deliverability','state']),\n provider: pick(json, ['provider','mail_provider','email_provider','esp']),\n }\n}));"
},
"typeVersion": 2
},
{
"id": "84ba0631-2b1b-448a-b3eb-a7d96eb2c868",
"name": "Keep verified emails",
"type": "n8n-nodes-base.filter",
"position": [
3072,
-320
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 1,
"leftValue": "",
"caseSensitive": false,
"typeValidation": "loose"
},
"combinator": "and",
"conditions": [
{
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.email }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "05f01dd9-08bf-4ebd-bef7-6b5f3fce870f",
"name": "Generate AI icebreaker",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"position": [
2336,
208
],
"parameters": {
"text": "=You write short, personalized cold-email opening lines for B2B outreach.\nWrite ONE opening line (max 30 words), in {{ $('Configuration').item.json.icebreaker_language }}, for this prospect:\n- Name: {{ $('Keep verified emails').item.json.firstName }} {{ $('Keep verified emails').item.json.lastName }}\n- Company domain: {{ $('Keep verified emails').item.json.domain }}\nWhat I offer: {{ $('Configuration').item.json.your_offer }}\nRules: sound human and specific, reference their company, no greeting, no emojis. Output only the sentence.",
"batching": {},
"promptType": "define"
},
"typeVersion": 1.9
},
{
"id": "66e41ae6-b996-466a-806a-0a361cf5e1ff",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
2336,
368
],
"parameters": {
"model": {
"__rl": true,
"mode": "id",
"value": "={{ $('Configuration').item.json.ai_model }}"
},
"options": {},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "6fa4c708-bbee-4be4-bd18-e36c2d6dee03",
"name": "Save enriched leads to Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
2656,
224
],
"parameters": {
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultName": "leads"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "",
"cachedResultName": "Select your output spreadsheet"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.7
},
{
"id": "943f5b79-6041-480f-8a7c-6f3be5fb2b80",
"name": "Send run summary email",
"type": "n8n-nodes-base.gmail",
"position": [
2864,
224
],
"parameters": {
"sendTo": "={{ $('Configuration').item.json.notify_email }}",
"message": "=Your ScraperCity email enrichment run finished.\n\nContacts submitted: {{ $('Build contacts payload').item.json.contacts.length }}\nVerified emails found: {{ $('Keep verified emails').all().length }}\n\nThe enriched leads (email + verification status + AI icebreaker) were written to your Google Sheet.",
"options": {},
"subject": "=Email enrichment done - {{ $('Keep verified emails').all().length }} verified leads",
"emailType": "text"
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"executeOnce": true,
"typeVersion": 2.2
},
{
"id": "4253b1ad-d575-45cd-b73c-891d3b9964ef",
"name": "Stop - job failed or timed out",
"type": "n8n-nodes-base.noOp",
"position": [
2192,
-288
],
"parameters": {},
"typeVersion": 1
},
{
"id": "d70325ee-0bec-4d93-b22e-490422bd57ca",
"name": "Sticky Note 1d8f3145",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
-528
],
"parameters": {
"color": 4,
"width": 640,
"height": 1528,
"content": "# Find and verify business emails then draft AI icebreakers in Google Sheets\n# [Open full documentation on Notion](https://automatisation.notion.site/Course-Find-and-verify-business-emails-then-draft-AI-icebreakers-in-Google-Sheets-39d3d6550fd9810b8200d55f10e2a1c5)\n\n## How it works\nReads contacts (first name, last name, company domain) from Google Sheets, sends them to the ScraperCity Email Finder API, polls until done, keeps only verified emails, drafts a personalized opening line per contact with OpenAI, writes everything back to Sheets and emails a summary.\n\n## Setup\n1. Create a ScraperCity account and copy your API key.\n2. Create an HTTP Header Auth credential named ScraperCity API Key (Name Authorization, Value Bearer YOUR_KEY) and select it on the 3 ScraperCity HTTP nodes.\n3. Set your values in Configuration.\n4. Pick input and output spreadsheets.\n\n## Requirements\n- ScraperCity account with Email Finder credits\n- OpenAI credential (OpenAi account)\n- Google Sheets + Gmail credentials\n- Input columns: firstName, lastName, domain\n\n## Customization\n- Swap Manual Trigger for a Schedule Trigger.\n- Adjust poll_wait_seconds / max_status_checks.\n- Edit the icebreaker prompt.\n\nNeed help customizing?\nContact me for consulting and support : [Linkedin](https://www.linkedin.com/in/doctor-firass/)\n\n# MY NEW YOUTUBE CHANNEL\n[Subscribe to my new YouTube channel](https://www.youtube.com/@DrFiras_AI).\n\n[](https://www.youtube.com/@DrFiras_AI)"
},
"typeVersion": 1
},
{
"id": "cd65b7bc-47c2-41e1-b3fe-8cbd052cfca2",
"name": "Sticky Note 8c780143",
"type": "n8n-nodes-base.stickyNote",
"position": [
704,
-480
],
"parameters": {
"color": 7,
"width": 480,
"height": 360,
"content": "## 1. Input & configuration\nAll adjustable settings live in Configuration. Contacts are read from your Google Sheet."
},
"typeVersion": 1
},
{
"id": "64d22967-7bdd-46d6-92bb-b197bc63766d",
"name": "Sticky Note 816d1cf9",
"type": "n8n-nodes-base.stickyNote",
"position": [
1232,
-592
],
"parameters": {
"color": 7,
"width": 920,
"height": 520,
"content": "## 2. Find emails with ScraperCity\nSubmit contacts, poll status until SUCCEEDED (or stop on FAILED / timeout)."
},
"typeVersion": 1
},
{
"id": "a142b4a6-c6f6-4793-95ce-3d0b8c65b282",
"name": "Sticky Note 31d256a6",
"type": "n8n-nodes-base.stickyNote",
"position": [
2336,
-576
],
"parameters": {
"color": 7,
"width": 900,
"height": 500,
"content": "## 3. Clean & filter\nDownload the CSV, normalize columns, keep only verified emails."
},
"typeVersion": 1
},
{
"id": "dcb4ae04-22dd-4da4-8f9f-95dc19810995",
"name": "Sticky Note 23c083aa",
"type": "n8n-nodes-base.stickyNote",
"position": [
2320,
48
],
"parameters": {
"color": 7,
"width": 260,
"height": 500,
"content": "## 4. AI personalization\nOne personalized opening line per verified contact."
},
"typeVersion": 1
},
{
"id": "26a99151-5ac7-43e1-973e-36291cf1b41f",
"name": "Sticky Note 035a826e",
"type": "n8n-nodes-base.stickyNote",
"position": [
2608,
48
],
"parameters": {
"color": 7,
"width": 480,
"height": 500,
"content": "## 5. Save & notify\nWrite enriched leads to Sheets and email a run summary."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"availableInMCP": true,
"executionOrder": "v1"
},
"versionId": "aabf972b-b4f1-4077-9b8d-3104e45e361a",
"nodeGroups": [],
"connections": {
"Configuration": {
"main": [
[
{
"node": "Get contacts from Sheet",
"type": "main",
"index": 0
}
]
]
},
"Check job status": {
"main": [
[
{
"node": "Route by job status",
"type": "main",
"index": 0
}
]
]
},
"Download results": {
"main": [
[
{
"node": "Extract results from CSV",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "Generate AI icebreaker",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Route by job status": {
"main": [
[
{
"node": "Download results",
"type": "main",
"index": 0
}
],
[
{
"node": "Stop - job failed or timed out",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait before status check",
"type": "main",
"index": 0
}
]
]
},
"Keep verified emails": {
"main": [
[
{
"node": "Generate AI icebreaker",
"type": "main",
"index": 0
}
]
]
},
"Run email enrichment": {
"main": [
[
{
"node": "Configuration",
"type": "main",
"index": 0
}
]
]
},
"Submit to ScraperCity": {
"main": [
[
{
"node": "Wait before status check",
"type": "main",
"index": 0
}
]
]
},
"Build contacts payload": {
"main": [
[
{
"node": "Submit to ScraperCity",
"type": "main",
"index": 0
}
]
]
},
"Generate AI icebreaker": {
"main": [
[
{
"node": "Save enriched leads to Sheet",
"type": "main",
"index": 0
}
]
]
},
"Get contacts from Sheet": {
"main": [
[
{
"node": "Build contacts payload",
"type": "main",
"index": 0
}
]
]
},
"Normalize result fields": {
"main": [
[
{
"node": "Keep verified emails",
"type": "main",
"index": 0
}
]
]
},
"Extract results from CSV": {
"main": [
[
{
"node": "Normalize result fields",
"type": "main",
"index": 0
}
]
]
},
"Wait before status check": {
"main": [
[
{
"node": "Check job status",
"type": "main",
"index": 0
}
]
]
},
"Save enriched leads to Sheet": {
"main": [
[
{
"node": "Send run summary email",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googleSheetsOAuth2ApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow reads contacts from Google Sheets, finds and verifies their business emails via the ScraperCity Email Finder API, generates a short personalized icebreaker with OpenAI, appends the enriched leads to another Google Sheet, and emails a run summary via Gmail. Starts…
Source: https://n8n.io/workflows/17126/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
The workflow runs every hour with a randomized delay of 5–20 minutes to help distribute load. It records the exact date and time a lead is emailed so you can track outreach. Follow-ups are automatical
This workflow is perfect for graphic designers, creative agencies, marketing teams, or freelancers who regularly use AI-generated images in their projects. It's specifically beneficial for teams that
n8n Graphic Design Team. Uses googleSheets, googleDrive, httpRequest, outputParserStructured. Event-driven trigger; 37 nodes.
What this workflow does:
This n8n template automates targeted lead discovery, AI-driven data structuring, and personalized cold-email sending at controlled intervals. It’s ideal for sales teams, founders, and agencies that wa