This workflow corresponds to n8n.io template #12750 — we link there as the canonical source.
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 →
{
"nodes": [
{
"id": "ea803d08-d03d-4bae-b1a1-00845dedc9d0",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-880,
-496
],
"parameters": {
"color": 7,
"width": 2224,
"height": 400,
"content": "## 1) Generate warmup conversations (daily)\nCreates friendly conversation JSON and saves it to `warmup_conversations`.\n"
},
"typeVersion": 1
},
{
"id": "1eb066c2-6f60-478a-864c-e4fe3562c150",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-896,
-16
],
"parameters": {
"color": 7,
"width": 2240,
"height": 672,
"content": "## 2) Build warmup queue (daily)\nPairs inboxes + assigns messages into `warmup_queue`.\n"
},
"typeVersion": 1
},
{
"id": "7e835764-6937-44aa-ade3-56aceed17c8e",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-928,
720
],
"parameters": {
"color": 7,
"width": 3168,
"height": 736,
"content": "## 3) Send warmup messages (hourly)\nAssigns random send times and sends/replies via Gmail.\n"
},
"typeVersion": 1
},
{
"id": "a5067261-6354-434f-b42b-341502ed37fc",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1376,
-496
],
"parameters": {
"color": 7,
"width": 1072,
"height": 1152,
"content": "## 4) Mark warmup emails as read (hourly)\nRemoves UNREAD and updates `marked_read` in queue.\n"
},
"typeVersion": 1
},
{
"id": "4e97ce7d-6c01-41b0-9717-62aff4240536",
"name": "generate warmup conversations",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-688,
-320
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 6
}
]
}
},
"typeVersion": 1.2
},
{
"id": "a36062d6-2e20-4d39-b92c-fdcd7f731de8",
"name": "Get warmup accounts (cold_email_accounts)",
"type": "n8n-nodes-base.dataTable",
"position": [
-400,
-320
],
"parameters": {
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "mqNBBTqxgRm7R9v0",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
"cachedResultName": "cold_email_accounts"
}
},
"typeVersion": 1.1
},
{
"id": "8e24409c-2c25-42f8-af46-993b196f30de",
"name": "Build conversation generation loop",
"type": "n8n-nodes-base.code",
"position": [
-144,
-320
],
"parameters": {
"jsCode": "let daily_limit = $input.first().json.warmup_daily_limit\n\nlet simArray = []\nfor (let i = 0; i < daily_limit; i++) {\n simArray.push({\n index: i+1\n })\n}\n\nreturn simArray"
},
"typeVersion": 2
},
{
"id": "52c5312c-215c-4e20-8b83-3323f44187d4",
"name": "Loop: generate conversations",
"type": "n8n-nodes-base.splitInBatches",
"position": [
176,
-320
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "3ce03cdc-2f71-4aa3-a5bf-b098f5934c71",
"name": "Generate conversations (OpenAI)",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
400,
-400
],
"parameters": {
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {
"textFormat": {
"textOptions": {
"type": "json_object"
}
}
},
"responses": {
"values": [
{
"role": "system",
"content": "Generate a natural, friendly email conversation between two people.\n\nRequirements:\n- Include 2 to 3 messages total always.\n- Alternate between Person A and Person B.\n- Each message MUST be self-contained as a standalone email.\n- Do NOT reference previous messages.\n- No signatures, no links, no phone numbers.\n- Tone: casual, friendly, human.\n- Add light variety like greetings, emojis, small talk, scheduling questions, etc.\n- No sales content.\n- Keep it neutral.\n- Do NOT include spammy words (\u201cfree\u201d, \u201cbuy\u201d, \u201cdiscount\u201d, etc.)\n- Output ONLY as JSON formatlike:\n\n{\nconversations: [\n { \"sender\": \"A\", \"subject\": \"Hello!\", \"body\": \"Message text...\" },\n { \"sender\": \"B\", \"subject\": \"Re: Hello!\", \"body\": \"Message text...\" },\n ...\n]\n}\n"
},
{
"role": "system",
"content": "[\n {\n \"sender\": \"A\",\n \"subject\": \"Quick check-in\",\n \"body\": \"Hi! Just wanted to say hello and see how things are going on your side.\"\n },\n {\n \"sender\": \"B\",\n \"subject\": \"Re: Quick check-in\",\n \"body\": \"Hey! Things are pretty smooth so far. Just juggling some small tasks today.\"\n }\n]\n"
},
{
"role": "system",
"content": "[\n {\n \"sender\": \"A\",\n \"subject\": \"Hello!\",\n \"body\": \"Hey! Just touching base hope you're doing well today.\"\n },\n {\n \"sender\": \"B\",\n \"subject\": \"Re: Hello!\",\n \"body\": \"Hi! Doing alright. Was just organizing my week. How about you?\"\n }\n]\n"
},
{
"role": "system",
"content": "[\n {\n \"sender\": \"A\",\n \"subject\": \"Hey\",\n \"body\": \"Morning! Random thought do you drink coffee or tea? I'm trying to switch \ud83e\udd23\"\n },\n {\n \"sender\": \"B\",\n \"subject\": \"Re: Hey\",\n \"body\": \"Hahaha I\u2019m team coffee all the way But I\u2019ve been trying tea lately too.\"\n }\n]\n"
},
{
"role": "system",
"content": "[\n {\n \"sender\": \"A\",\n \"subject\": \"Checking in\",\n \"body\": \"Hi there, hope your day is going well so far.\"\n },\n {\n \"sender\": \"B\",\n \"subject\": \"Re: Checking in\",\n \"body\": \"Hello! Everything is going okay here, just catching up on tasks. How about yourself?\"\n },\n {\n \"sender\": \"A\",\n \"subject\": \"Re: Checking in\",\n \"body\": \"Pretty similar doing some small cleanups and planning out the rest of the week.\"\n }\n]\n"
}
]
},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "c5874af0-4e83-4919-a40a-eb251c429647",
"name": "Format conversations for Data Table",
"type": "n8n-nodes-base.code",
"position": [
752,
-400
],
"parameters": {
"jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nfor (const item of $input.all()) {\n let conversation = item.json.output[0].content[0].text.conversations\n item.json.conversation_string = JSON.stringify(conversation);\n}\n\nreturn $input.all();"
},
"typeVersion": 2
},
{
"id": "03282eb8-d2bc-4845-b714-0ba005401d51",
"name": "Save conversations (warmup_conversations)",
"type": "n8n-nodes-base.dataTable",
"position": [
976,
-320
],
"parameters": {
"columns": {
"value": {
"messages": "={{ $json.conversation_string }}"
},
"schema": [
{
"id": "messages",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "messages",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"messages"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "zFEHqfRDGsYVDTxX",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/zFEHqfRDGsYVDTxX",
"cachedResultName": "warmup_conversations"
}
},
"typeVersion": 1
},
{
"id": "7420f840-f366-42e3-b154-23af9c1f289d",
"name": "Daily trigger: build warmup queue",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-832,
336
],
"parameters": {
"rule": {
"interval": [
{
"triggerAtHour": 6,
"triggerAtMinute": 25
}
]
}
},
"typeVersion": 1.2
},
{
"id": "cfb4dc7d-4428-4076-b4e1-6621bab61b91",
"name": "Get warmup accounts for queue",
"type": "n8n-nodes-base.dataTable",
"position": [
-608,
336
],
"parameters": {
"limit": {},
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "mqNBBTqxgRm7R9v0",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
"cachedResultName": "cold_email_accounts"
}
},
"typeVersion": 1
},
{
"id": "a9001fc2-6e13-4349-8ad1-c34476eef65a",
"name": "Loop: build queue per inbox",
"type": "n8n-nodes-base.splitInBatches",
"position": [
-384,
336
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "4044866f-0468-440b-b9fd-ee22ab4afc0a",
"name": "Calculate daily warmup target",
"type": "n8n-nodes-base.code",
"position": [
-160,
336
],
"parameters": {
"jsCode": "const base = 5; // starting point\nconst max = 40; // max warm-up per inbox\nconst growth = 2; // +2 per day\n\nconst todayCount = Math.min(\n $json.warmup_sent_today + growth,\n max\n);\n\nreturn [{\n json: {\n ...$json,\n warmup_target_today: todayCount\n }\n}]\n"
},
"typeVersion": 2
},
{
"id": "28899f7f-ff7a-4f82-aba6-72047d5007c8",
"name": "Get recipient inboxes (excluding sender)",
"type": "n8n-nodes-base.dataTable",
"position": [
64,
432
],
"parameters": {
"limit": {},
"filters": {
"conditions": [
{
"keyName": "email",
"keyValue": "={{ $json.email }}",
"condition": "neq"
}
]
},
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "mqNBBTqxgRm7R9v0",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
"cachedResultName": "cold_email_accounts"
}
},
"typeVersion": 1
},
{
"id": "2f27a0a9-f33b-4538-bc4e-8fe89bae4118",
"name": "Pick random recipient inboxes",
"type": "n8n-nodes-base.code",
"position": [
288,
432
],
"parameters": {
"jsCode": "const sender = $(\"Calculate daily warmup target\").all()[0].json.email;\nconst target = $(\"Calculate daily warmup target\").all()[0].json.warmup_target_today;\n\n// Incoming items from Data Tables (other inboxes)\nconst recipients = $(\"Get recipient inboxes (excluding sender)\").all().map(i => i.json);\n\n// Shuffle array\nfor (let i = recipients.length - 1; i > 0; i--) {\n const j = Math.floor(Math.random() * (i + 1));\n [recipients[i], recipients[j]] = [recipients[j], recipients[i]];\n}\n\n// Pick target count, or all if fewer\nconst selected = recipients.slice(0, target);\n\nreturn selected.map(r => ({\n json: {\n inboxA: sender,\n inboxB: r.email,\n target\n }\n}));\n\n"
},
"typeVersion": 2
},
{
"id": "3e94e231-670d-49ea-98c7-1af579b2054b",
"name": "Get conversations from table",
"type": "n8n-nodes-base.dataTable",
"position": [
64,
240
],
"parameters": {
"limit": "={{ $json.warmup_daily_limit }}",
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "zFEHqfRDGsYVDTxX",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/zFEHqfRDGsYVDTxX",
"cachedResultName": "warmup_conversations"
}
},
"typeVersion": 1
},
{
"id": "41b5e014-f181-4547-9acb-74383662de41",
"name": "Parse conversation JSON",
"type": "n8n-nodes-base.code",
"position": [
288,
240
],
"parameters": {
"jsCode": "let items = $input.all()\nlet allmessages = []\nfor (let i = 0; i < items.length; i++) {\n const messages = JSON.parse(items[i].json.messages || \"[]\");\n allmessages.push({\n conversation_id: items[i].json.id,\n message: messages\n })\n}\n// return messages.map(m => ({ json: m }));\nreturn allmessages"
},
"typeVersion": 2
},
{
"id": "a8604c91-31d1-403f-bf05-2df5c1100ad1",
"name": "Merge recipients + conversations",
"type": "n8n-nodes-base.merge",
"position": [
512,
336
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.2
},
{
"id": "574c087d-c6bf-4659-9b50-8961c8522512",
"name": "Loop: match conversations to recipients",
"type": "n8n-nodes-base.splitInBatches",
"position": [
736,
336
],
"parameters": {
"options": {
"reset": true
},
"batchSize": "={{ $json.target }}"
},
"typeVersion": 3
},
{
"id": "c1afc47c-18ea-48ca-a530-a9cd7542c739",
"name": "Split conversation into scheduled messages",
"type": "n8n-nodes-base.code",
"position": [
960,
416
],
"parameters": {
"mode": "runOnceForEachItem",
"jsCode": "const message = $input.item.json.message;\nlet conversation_id = $input.item.json.conversation_id\nlet inboxA = $input.item.json.inboxA;\nlet inboxB = $input.item.json.inboxB;\n\nlet conversations = [];\nconst now = new Date();\n\nfor (let i = 0; i < message.length; i++) {\n\n // sender / receiver\n const isA = message[i].sender === \"A\";\n const sender_inbox = isA ? inboxA : inboxB;\n const receiver_inbox = isA ? inboxB : inboxA;\n\n // Calculate scheduled_date = today + i days\n const scheduledDateObj = new Date(now);\n scheduledDateObj.setDate(now.getDate() + i);\n\n const scheduledDate = scheduledDateObj.toISOString().split(\"T\")[0];\n\n conversations.push({\n sender_inbox,\n receiver_inbox,\n subject: message[i].subject,\n body: message[i].body,\n scheduled_date: scheduledDate, // ONLY DATE, no time\n scheduled_at: null, // sender engine assigns actual time later\n sent: false,\n conversation_id,\n conversation_index: i\n });\n}\n\nreturn { conversation: conversations };\n"
},
"typeVersion": 2
},
{
"id": "24442941-657d-4dd2-ba0d-d2bc3489deb6",
"name": "Flatten message list",
"type": "n8n-nodes-base.code",
"position": [
-160,
48
],
"parameters": {
"jsCode": "let conversationsArray = $input.all()\nlet conversations = []\n\nfor (let i = 0; i < conversationsArray.length; i++) {\n for (let j = 0; j < conversationsArray[i].json.conversation.length; j++) {\n conversations.push(conversationsArray[i].json.conversation[j])\n }\n}\n\nreturn conversations;"
},
"typeVersion": 2
},
{
"id": "2ccfc8d7-35a1-45c9-9bad-1b5493460a66",
"name": "Insert messages into warmup_queue",
"type": "n8n-nodes-base.dataTable",
"position": [
64,
48
],
"parameters": {
"columns": {
"value": {
"body": "={{ $json.body }}",
"sent": "={{ $json.sent }}",
"subject": "={{ $json.subject }}",
"marked_read": false,
"sender_inbox": "={{ $json.sender_inbox }}",
"receiver_inbox": "={{ $json.receiver_inbox }}",
"scheduled_date": "={{ $json.scheduled_date }}",
"conversation_id": "={{ $json.conversation_id }}",
"conversation_index": "={{ $json.conversation_index }}"
},
"schema": [
{
"id": "sender_inbox",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "sender_inbox",
"defaultMatch": false
},
{
"id": "receiver_inbox",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_inbox",
"defaultMatch": false
},
{
"id": "subject",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "subject",
"defaultMatch": false
},
{
"id": "body",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "body",
"defaultMatch": false
},
{
"id": "scheduled_date",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "scheduled_date",
"defaultMatch": false
},
{
"id": "scheduled_at",
"type": "dateTime",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "scheduled_at",
"defaultMatch": false
},
{
"id": "sent",
"type": "boolean",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "sent",
"defaultMatch": false
},
{
"id": "message_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "message_id",
"defaultMatch": false
},
{
"id": "thread_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "thread_id",
"defaultMatch": false
},
{
"id": "receiver_message_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_message_id",
"defaultMatch": false
},
{
"id": "receiver_thread_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_thread_id",
"defaultMatch": false
},
{
"id": "marked_read",
"type": "boolean",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "marked_read",
"defaultMatch": false
},
{
"id": "conversation_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "conversation_id",
"defaultMatch": false
},
{
"id": "conversation_index",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "conversation_index",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "JOPX8e7E4d6cjAWa",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
"cachedResultName": "warmup_queue"
}
},
"typeVersion": 1
},
{
"id": "c833ce57-1ea1-4f95-b215-f346a42f0eb4",
"name": "Hourly trigger: send scheduled warmup emails",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
-768,
1024
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours"
}
]
}
},
"typeVersion": 1.2
},
{
"id": "808504b6-3b21-40e4-9fe3-a3c540680738",
"name": "Get today unsent warmups",
"type": "n8n-nodes-base.dataTable",
"position": [
-560,
1024
],
"parameters": {
"limit": {},
"filters": {
"conditions": [
{
"keyName": "scheduled_date",
"keyValue": "={{ $now.format('yyyy-MM-dd') }}"
},
{
"keyName": "sent",
"condition": "isFalse"
}
]
},
"matchType": "allConditions",
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "JOPX8e7E4d6cjAWa",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
"cachedResultName": "warmup_queue"
}
},
"typeVersion": 1
},
{
"id": "5c1d8c50-4b08-4d68-9119-2743836a747e",
"name": "Assign random send time (IST window)",
"type": "n8n-nodes-base.code",
"position": [
-160,
912
],
"parameters": {
"jsCode": "const startHour = 8; // daily window start\nconst endHour = 22; // daily window end\n\nfunction createISTDate(hour, minute = 0) {\n const now = new Date();\n \n // Convert today's date to IST\n const ist = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n hour,\n minute,\n 0,\n 0\n );\n\n // IST \u2192 UTC\n const utc = new Date(ist.getTime() - (5.5 * 60 * 60 * 1000));\n return utc;\n}\n\nfunction randomTimeInWindow(startHour, endHour) {\n const now = new Date();\n \n const start = createISTDate(startHour);\n const end = createISTDate(endHour);\n \n // Random time between start and end\n const randomMs = start.getTime() + Math.random() * (end.getTime() - start.getTime());\n\n return new Date(randomMs);\n}\n\n\n// These come from DB fetch via n8n\nlet warmups = $input.all(); \n\nlet updatedRows = [];\n\nfor (let item of warmups) {\n let row = item.json;\n\n // Assign a random timestamp ONLY if it's scheduled for today and not assigned yet\n if (!row.scheduled_at) {\n row.scheduled_at = randomTimeInWindow(startHour, endHour).toISOString();\n }\n\n updatedRows.push(row);\n}\n\nreturn updatedRows;\n"
},
"typeVersion": 2
},
{
"id": "5ec0eb3e-9a32-4330-99d4-72caddd3d9aa",
"name": "Update scheduled_at in queue",
"type": "n8n-nodes-base.dataTable",
"position": [
32,
912
],
"parameters": {
"columns": {
"value": {
"sent": false,
"marked_read": false,
"scheduled_at": "={{ $json.scheduled_at }}"
},
"schema": [
{
"id": "sender_inbox",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "sender_inbox",
"defaultMatch": false
},
{
"id": "receiver_inbox",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_inbox",
"defaultMatch": false
},
{
"id": "subject",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "subject",
"defaultMatch": false
},
{
"id": "body",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "body",
"defaultMatch": false
},
{
"id": "scheduled_date",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "scheduled_date",
"defaultMatch": false
},
{
"id": "scheduled_at",
"type": "dateTime",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "scheduled_at",
"defaultMatch": false
},
{
"id": "sent",
"type": "boolean",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "sent",
"defaultMatch": false
},
{
"id": "message_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "message_id",
"defaultMatch": false
},
{
"id": "thread_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "thread_id",
"defaultMatch": false
},
{
"id": "receiver_message_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_message_id",
"defaultMatch": false
},
{
"id": "receiver_thread_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_thread_id",
"defaultMatch": false
},
{
"id": "marked_read",
"type": "boolean",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "marked_read",
"defaultMatch": false
},
{
"id": "conversation_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "conversation_id",
"defaultMatch": false
},
{
"id": "conversation_index",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "conversation_index",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"filters": {
"conditions": [
{
"keyValue": "={{ $json.id }}"
}
]
},
"options": {},
"operation": "update",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "JOPX8e7E4d6cjAWa",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
"cachedResultName": "warmup_queue"
}
},
"typeVersion": 1
},
{
"id": "d89a6fff-dd14-4dfc-939c-f327fb3021f2",
"name": "If scheduled_at is empty",
"type": "n8n-nodes-base.if",
"position": [
-368,
1024
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "4801ab32-3dde-4236-8c5e-16b8c574ae58",
"operator": {
"type": "dateTime",
"operation": "empty",
"singleValue": true
},
"leftValue": "={{ $json.scheduled_at }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "80391bba-e8c0-438c-80b3-133959eda31e",
"name": "Filter messages due now",
"type": "n8n-nodes-base.code",
"position": [
208,
1056
],
"parameters": {
"jsCode": "const now = new Date();\nlet due = [];\n\nfor (let item of $input.all()) {\n const row = item.json;\n if (row.scheduled_at && new Date(row.scheduled_at) <= now) {\n due.push(row);\n }\n}\n\nreturn due;\n"
},
"typeVersion": 2
},
{
"id": "be7d31d6-2ab9-47d0-be06-833715ea2a54",
"name": "Get accounts (for credentials)",
"type": "n8n-nodes-base.dataTable",
"position": [
208,
1216
],
"parameters": {
"operation": "get",
"returnAll": true,
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "mqNBBTqxgRm7R9v0",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
"cachedResultName": "cold_email_accounts"
}
},
"typeVersion": 1
},
{
"id": "b2d8d6b1-9568-482a-9875-9596f9ffdac1",
"name": "Merge queue with account credentials",
"type": "n8n-nodes-base.merge",
"position": [
400,
1072
],
"parameters": {
"mode": "combine",
"options": {
"clashHandling": {
"values": {
"resolveClash": "preferInput1"
}
}
},
"advanced": true,
"mergeByFields": {
"values": [
{
"field1": "sender_inbox",
"field2": "email"
}
]
}
},
"typeVersion": 3.2
},
{
"id": "d133bd11-328d-49f7-a3da-d8ef3f599e90",
"name": "Loop: send warmup message",
"type": "n8n-nodes-base.splitInBatches",
"position": [
592,
1072
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "4ed85c55-ae2e-4c74-aecd-88be839f8b8d",
"name": "If first message in thread",
"type": "n8n-nodes-base.if",
"position": [
832,
1088
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "11280a4c-bb8c-424b-8531-1bc3435d52a2",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $json.conversation_index }}",
"rightValue": "0"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "2d0f3169-f438-4c23-b19e-eb423e62671a",
"name": "Send Gmail message (new thread)",
"type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
"position": [
1136,
992
],
"parameters": {
"nodeJson": "={\n \"nodes\": [\n {\n \"parameters\": {\n \"sendTo\": \"={{ $json.receiver_inbox }}\",\n \"subject\": \"={{ $json.subject }}\",\n \"emailType\": \"text\",\n \"message\": \"={{ $json.body }}\",\n \"options\": {\n \"appendAttribution\": false\n }\n },\n \"type\": \"n8n-nodes-base.gmail\",\n \"typeVersion\": 2.1,\n \"position\": [\n 1920,\n 2544\n ],\n \"id\": \"90be2479-0140-4ca1-b1fa-55d4339f48a8\",\n \"name\": \"Send a message\",\n \"webhookId\": \"98b6ca9f-c412-4aae-a114-9938a3ba94e5\",\n \"credentials\": {\n \"gmailOAuth2\": {\n \"id\": \"mhyVQDjPrVLEOGCr\",\n \"name\": \"jatin.k@get\"\n }\n }\n }\n ],\n \"connections\": {\n \"Send a message\": {\n \"main\": [\n []\n ]\n }\n },\n \"pinData\": {},\n \"meta\": {\n \"templateCredsSetupCompleted\": true,\n \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n }\n}",
"credentialsId": "={{ $json.cred_id }}"
},
"typeVersion": 1
},
{
"id": "610d87c3-dd31-4051-9f34-44c4cc81b483",
"name": "Get previous message (thread context)",
"type": "n8n-nodes-base.dataTable",
"position": [
1040,
1152
],
"parameters": {
"filters": {
"conditions": [
{
"keyValue": "={{ $json.id - 1 }}"
}
]
},
"matchType": "allConditions",
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "JOPX8e7E4d6cjAWa",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
"cachedResultName": "warmup_queue"
}
},
"typeVersion": 1
},
{
"id": "e8bb9300-ad97-40fe-9661-339f0bca742e",
"name": "Reply in existing Gmail thread",
"type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
"position": [
1232,
1152
],
"parameters": {
"nodeJson": "={\n \"nodes\": [\n {\n \"parameters\": {\n \"resource\": \"thread\",\n \"operation\": \"reply\",\n \"threadId\": \"={{ $json.receiver_thread_id }}\",\n \"messageId\": \"={{ $json.receiver_thread_id }}\",\n \"message\": \"={{ $('If first message in thread').item.json.body }}\",\n \"options\": {}\n },\n \"type\": \"n8n-nodes-base.gmail\",\n \"typeVersion\": 2.1,\n \"position\": [\n 1920,\n 2736\n ],\n \"id\": \"d09a475e-785d-4311-b877-9fd665fbfa76\",\n \"name\": \"Reply to a message\",\n \"webhookId\": \"aeface07-8c1d-471c-84cb-c7b796a734f6\",\n \"credentials\": {\n \"gmailOAuth2\": {\n \"id\": \"mhyVQDjPrVLEOGCr\",\n \"name\": \"jatin.k@get\"\n }\n },\n \"onError\": \"continueErrorOutput\"\n }\n ],\n \"connections\": {\n \"Reply to a message\": {\n \"main\": [\n [],\n []\n ]\n }\n },\n \"pinData\": {},\n \"meta\": {\n \"templateCredsSetupCompleted\": true,\n \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n }\n}",
"credentialsId": "={{ $('If first message in thread').item.json.cred_id }}"
},
"typeVersion": 1
},
{
"id": "193aaa95-df1f-4446-bae1-cdaf3fca7db9",
"name": "Label sent warmup email",
"type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
"position": [
1472,
1072
],
"parameters": {
"nodeJson": "={\n \"nodes\": [\n {\n \"parameters\": {\n \"operation\": \"addLabels\",\n \"messageId\": \"={{ $json.id }}\",\n \"labelIds\": [\n \"IMPORTANT\",\n \"Label_1\"\n ]\n },\n \"type\": \"n8n-nodes-base.gmail\",\n \"typeVersion\": 2.1,\n \"position\": [\n 2144,\n 2640\n ],\n \"id\": \"8b7b1177-9588-41c5-bf26-90f969722730\",\n \"name\": \"Add label to message2\",\n \"webhookId\": \"892a0e29-d34a-4aba-a61b-f58f3c6cbeef\",\n \"credentials\": {\n \"gmailOAuth2\": {\n \"id\": \"mhyVQDjPrVLEOGCr\",\n \"name\": \"jatin.k@get\"\n }\n }\n }\n ],\n \"connections\": {\n \"Add label to message2\": {\n \"main\": [\n []\n ]\n }\n },\n \"pinData\": {},\n \"meta\": {\n \"templateCredsSetupCompleted\": true,\n \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n }\n}",
"credentialsId": "={{ $('If first message in thread').item.json.cred_id }}"
},
"typeVersion": 1
},
{
"id": "893a4bcf-2ffd-4e22-8b00-2e83af877181",
"name": "Update queue: sent + message/thread IDs",
"type": "n8n-nodes-base.dataTable",
"position": [
1760,
1072
],
"parameters": {
"columns": {
"value": {
"sent": true,
"thread_id": "={{ $json.threadId }}",
"message_id": "={{ $json.id }}",
"marked_read": false
},
"schema": [
{
"id": "sender_inbox",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "sender_inbox",
"defaultMatch": false
},
{
"id": "receiver_inbox",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_inbox",
"defaultMatch": false
},
{
"id": "subject",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "subject",
"defaultMatch": false
},
{
"id": "body",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "body",
"defaultMatch": false
},
{
"id": "scheduled_date",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "scheduled_date",
"defaultMatch": false
},
{
"id": "scheduled_at",
"type": "dateTime",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "scheduled_at",
"defaultMatch": false
},
{
"id": "sent",
"type": "boolean",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "sent",
"defaultMatch": false
},
{
"id": "message_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "message_id",
"defaultMatch": false
},
{
"id": "thread_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "thread_id",
"defaultMatch": false
},
{
"id": "receiver_message_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_message_id",
"defaultMatch": false
},
{
"id": "receiver_thread_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_thread_id",
"defaultMatch": false
},
{
"id": "marked_read",
"type": "boolean",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "marked_read",
"defaultMatch": false
},
{
"id": "conversation_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "conversation_id",
"defaultMatch": false
},
{
"id": "conversation_index",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "conversation_index",
"defaultMatch": false
},
{
"id": "status",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "status",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"filters": {
"conditions": [
{
"keyValue": "={{ $('Loop: send warmup message').item.json.id }}"
}
]
},
"options": {},
"operation": "update",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "JOPX8e7E4d6cjAWa",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
"cachedResultName": "warmup_queue"
}
},
"typeVersion": 1
},
{
"id": "82e1e8cd-49b9-45ee-bd97-be8dc5bf7a76",
"name": "Hourly trigger: mark warmups as read",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
1408,
-320
],
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"triggerAtMinute": 25
}
]
}
},
"typeVersion": 1.2
},
{
"id": "1f6525ab-531c-417b-9a19-fec4e87234ce",
"name": "Get sent warmups to mark read",
"type": "n8n-nodes-base.dataTable",
"position": [
1760,
-416
],
"parameters": {
"limit": {},
"filters": {
"conditions": [
{
"keyName": "sent",
"condition": "isTrue"
},
{
"keyName": "marked_read",
"condition": "isFalse"
},
{
"keyName": "scheduled_at",
"keyValue": "={{ DateTime.now().setZone('Asia/Kolkata').toISO() }}",
"condition": "lt"
}
]
},
"matchType": "allConditions",
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "JOPX8e7E4d6cjAWa",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
"cachedResultName": "warmup_queue"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "d5bff093-3664-41c9-bd36-f61de7f601cf",
"name": "Loop: mark warmups read",
"type": "n8n-nodes-base.splitInBatches",
"position": [
1488,
16
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "bf1eee80-b7a4-40f8-840f-ff3cd5970257",
"name": "If warmup row exists",
"type": "n8n-nodes-base.if",
"position": [
1872,
32
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "3b61da83-92fd-42fa-a1b2-8fc743061594",
"operator": {
"type": "object",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "5f6a72fe-ccd2-41b2-ba3a-bb297f5a9230",
"name": "Fetch unread messages from sender",
"type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
"position": [
1696,
32
],
"parameters": {
"nodeJson": "={\n \"nodes\": [\n {\n \"parameters\": {\n \"operation\": \"getAll\",\n \"filters\": {\n \"readStatus\": \"unread\",\n \"sender\": \"={{ $json.sender_inbox }}\"\n }\n },\n \"type\": \"n8n-nodes-base.gmail\",\n \"typeVersion\": 2.1,\n \"position\": [\n -1024,\n 672\n ],\n \"id\": \"f3019944-af88-44b1-a81e-da273831ec8e\",\n \"name\": \"Get many messages9\",\n \"webhookId\": \"f70a494c-722f-4e93-adb3-a77f52ef946a\",\n \"alwaysOutputData\": true,\n \"credentials\": {\n \"gmailOAuth2\": {\n \"id\": \"mhyVQDjPrVLEOGCr\",\n \"name\": \"jatin.k@get\"\n }\n }\n }\n ],\n \"connections\": {\n \"Get many messages9\": {\n \"main\": [\n []\n ]\n }\n },\n \"pinData\": {},\n \"meta\": {\n \"templateCredsSetupCompleted\": true,\n \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n }\n}",
"credentialsId": "={{ $json.cred_id }}"
},
"typeVersion": 1
},
{
"id": "9d08d6e0-f602-4982-bda4-d16d418c7661",
"name": "Get accounts (for receiver creds)",
"type": "n8n-nodes-base.dataTable",
"position": [
1760,
-240
],
"parameters": {
"limit": {},
"operation": "get",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "mqNBBTqxgRm7R9v0",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/mqNBBTqxgRm7R9v0",
"cachedResultName": "cold_email_accounts"
}
},
"typeVersion": 1
},
{
"id": "e48b6981-84c8-4771-b717-78a128c782ac",
"name": "Merge receiver inbox credentials",
"type": "n8n-nodes-base.merge",
"position": [
2144,
-336
],
"parameters": {
"mode": "combine",
"options": {},
"advanced": true,
"mergeByFields": {
"values": [
{
"field1": "receiver_inbox",
"field2": "email"
}
]
}
},
"typeVersion": 3.2
},
{
"id": "4834504f-ca2c-43d5-9854-5aa405e5a16e",
"name": "Label warmup message (receiver)",
"type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
"position": [
2064,
-64
],
"parameters": {
"nodeJson": "={\n \"nodes\": [\n {\n \"parameters\": {\n \"operation\": \"addLabels\",\n \"messageId\": \"={{ $json.id }}\",\n \"labelIds\": [\n \"IMPORTANT\",\n \"Label_1\"\n ]\n },\n \"type\": \"n8n-nodes-base.gmail\",\n \"typeVersion\": 2.1,\n \"position\": [\n -432,\n 688\n ],\n \"id\": \"3a58c9b3-9f7d-476d-afb6-6d7439569396\",\n \"name\": \"Add label to message9\",\n \"webhookId\": \"70ea19d6-af1d-48f9-9e41-ce508fd5a069\",\n \"credentials\": {\n \"gmailOAuth2\": {\n \"id\": \"mhyVQDjPrVLEOGCr\",\n \"name\": \"jatin.k@get\"\n }\n }\n }\n ],\n \"connections\": {\n \"Add label to message9\": {\n \"main\": [\n []\n ]\n }\n },\n \"pinData\": {},\n \"meta\": {\n \"templateCredsSetupCompleted\": true,\n \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n }\n}",
"credentialsId": "={{ $('Loop Over Items5').item.json.cred_id }}"
},
"typeVersion": 1
},
{
"id": "589ae7f2-936a-47da-b11a-37d3e1b39cf0",
"name": "Remove UNREAD label (mark read)",
"type": "n8n-nodes-run-node-with-credentials-x.runNodeWithCredentialsX",
"position": [
2240,
-64
],
"parameters": {
"nodeJson": "={\n \"nodes\": [\n {\n \"parameters\": {\n \"operation\": \"removeLabels\",\n \"messageId\": \"={{ $json.id }}\",\n \"labelIds\": [\n \"UNREAD\"\n ]\n },\n \"type\": \"n8n-nodes-base.gmail\",\n \"typeVersion\": 2.1,\n \"position\": [\n -208,\n 688\n ],\n \"id\": \"ea9d7630-707e-413b-bfd3-9d4aed0d696a\",\n \"name\": \"Remove label from message9\",\n \"webhookId\": \"d7b034cd-dfb1-48cb-897b-b4f8a3def8f9\",\n \"credentials\": {\n \"gmailOAuth2\": {\n \"id\": \"mhyVQDjPrVLEOGCr\",\n \"name\": \"jatin.k@get\"\n }\n }\n }\n ],\n \"connections\": {\n \"Remove label from message9\": {\n \"main\": [\n []\n ]\n }\n },\n \"pinData\": {},\n \"meta\": {\n \"templateCredsSetupCompleted\": true,\n \"instanceId\": \"f5d0c13b222abccfa4b21baa9b6cd543e62d86b4c7c9b6917990da9dc767ae69\"\n }\n}",
"credentialsId": "={{ $('Loop Over Items5').item.json.cred_id }}"
},
"typeVersion": 1
},
{
"id": "58afed9d-4db3-4a4f-b8a4-027d28d7a13c",
"name": "Update queue: marked_read = true",
"type": "n8n-nodes-base.dataTable",
"position": [
2240,
368
],
"parameters": {
"columns": {
"value": {
"sent": true,
"marked_read": true,
"receiver_thread_id": "={{ $json.threadId }}",
"receiver_message_id": "={{ $json.id }}"
},
"schema": [
{
"id": "sender_inbox",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "sender_inbox",
"defaultMatch": false
},
{
"id": "receiver_inbox",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_inbox",
"defaultMatch": false
},
{
"id": "subject",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "subject",
"defaultMatch": false
},
{
"id": "body",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "body",
"defaultMatch": false
},
{
"id": "scheduled_at",
"type": "dateTime",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "scheduled_at",
"defaultMatch": false
},
{
"id": "sent",
"type": "boolean",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "sent",
"defaultMatch": false
},
{
"id": "message_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "message_id",
"defaultMatch": false
},
{
"id": "thread_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "thread_id",
"defaultMatch": false
},
{
"id": "receiver_message_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_message_id",
"defaultMatch": false
},
{
"id": "receiver_thread_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "receiver_thread_id",
"defaultMatch": false
},
{
"id": "marked_read",
"type": "boolean",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "marked_read",
"defaultMatch": false
},
{
"id": "conversation_id",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "conversation_id",
"defaultMatch": false
},
{
"id": "conversation_index",
"type": "string",
"display": true,
"removed": false,
"readOnly": false,
"required": false,
"displayName": "conversation_index",
"defaultMatch": false
}
],
"mappingMode": "defineBelow",
"matchingColumns": [],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"filters": {
"conditions": [
{
"keyValue": "={{ $('Loop: mark warmups read').item.json.id }}"
}
]
},
"options": {},
"operation": "update",
"dataTableId": {
"__rl": true,
"mode": "list",
"value": "JOPX8e7E4d6cjAWa",
"cachedResultUrl": "/projects/gWyT6ct8nsEBW0XK/datatables/JOPX8e7E4d6cjAWa",
"cachedResultName": "warmup_queue"
}
},
"typeVersion": 1
},
{
"id": "afa63fe5-da49-46c1-b446-6b4fdf71c904",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1696,
-496
],
"parameters": {
"width": 720,
"height": 448,
"content": "## How it works\nThis workflow warms up Gmail inboxes by sending natural, non-sales email conversations between your own inboxes. It generates friendly multi-message conversations using OpenAI, stores them in `warmup_conversations`, builds a daily send plan in `warmup_queue`, and assigns randomized send times within a safe daily window. Messages are sent using the correct Gmail OAuth credential for each inbox, replies happen in the same thread, and warmup emails are automatically marked as read to mimic human inbox activity.\n\n## Setup steps\n1) Create 3 Data Tables: `cold_email_accounts`, `warmup_conversations`, `warmup_queue`\n2) Add at least 2 inboxes to `cold_email_accounts` with `email`, `cred_id`, and `warmup_daily_limit`\n3) Create one Gmail OAuth2 credential per inbox and paste the credential ID into `cred_id`\n4) Add your OpenAI API credential to the OpenAI node\n5) Enable schedule triggers and execute once to test\n"
},
"typeVersion": 1
}
],
"connections": {
"Flatten message list": {
"main": [
[
{
"node": "Insert messages into warmup_queue",
"type": "main",
"index": 0
}
]
]
},
"If warmup row exists": {
"main": [
[
{
"node": "Label warmup message (receiver)",
"type": "main",
"index": 0
}
],
[
{
"node": "Loop: mark warmups read",
"type": "main",
"index": 0
}
]
]
},
"Filter messages due now": {
"main": [
[
{
"node": "Merge queue with account credentials",
"type": "main",
"index": 0
}
]
]
},
"Label sent warmup email": {
"main": [
[
{
"node": "Update queue: sent + message/thread IDs",
"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.
openAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Automatically warm up multiple Gmail inboxes with human-like email conversations, smart scheduling, and auto read/reply, powered by n8n Data Tables.
Source: https://n8n.io/workflows/12750/ — 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.
This workflow monitors a Discord channel on a schedule and processes recent messages automatically. Each message is checked against a data table to prevent duplicate processing. New messages are analy
This template is perfect for TikTok creators, content marketers, and social media teams who want to turn viral comments into engaging short-form videos without manually scripting, recording, or editin
This template lets you poll multiple Gmail accounts from a single workflow using n8n’s credential-aware execution. Instead of creating separate workflows for every inbox, this setup loops through all
AI Institutional Stock Valuation Engine with Risk Scoring & Scenario Targets
Overview This is a production-grade, fully automated stock analysis system built entirely in n8n. It combines institutional-level financial analysis, dual AI model consensus, and a self-improving back