{
  "id": "m9FbgwXPaHnLxSVc",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Draft and send personalized B2B cold outreach emails using Gemini AI and n8n Data Table",
  "tags": [],
  "nodes": [
    {
      "id": "90b1f7e9-1b9e-47aa-a6fb-0b2a712add23",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -16,
        1184
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "5fe491f5-05b0-4728-80e9-a7c3a5a3e3f3",
      "name": "Set Context",
      "type": "n8n-nodes-base.set",
      "position": [
        192,
        1184
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-001",
              "name": "sender_company_name",
              "type": "string",
              "value": "GenStaff"
            },
            {
              "id": "cfg-002",
              "name": "sender_company_solution",
              "type": "string",
              "value": "We provide AI-powered staffing and automation solutions that help businesses scale their operations without scaling headcount."
            },
            {
              "id": "cfg-003",
              "name": "sender_name",
              "type": "string",
              "value": "Jay Nguyen"
            },
            {
              "id": "cfg-004",
              "name": "sender_email",
              "type": "string",
              "value": "user@example.com"
            },
            {
              "id": "cfg-005",
              "name": "data_table_id",
              "type": "string",
              "value": "YOUR_DATA_TABLE_ID_HERE"
            },
            {
              "id": "cfg-006",
              "name": "email_max_words",
              "type": "number",
              "value": 120
            },
            {
              "id": "cfg-007",
              "name": "rate_limit_seconds",
              "type": "number",
              "value": 3
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "30f0daa7-03b0-46fb-82f2-1a7cb20a73f6",
      "name": "Get Pending Leads",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        416,
        1184
      ],
      "parameters": {
        "operation": "getAll",
        "dataTableId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Context').item.json.data_table_id }}"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "305fd949-7e70-47b5-8241-c80d341b1d63",
      "name": "Validate Email Format",
      "type": "n8n-nodes-base.if",
      "position": [
        640,
        1184
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "email-regex-001",
              "operator": {
                "type": "string",
                "operation": "regex"
              },
              "leftValue": "={{ $('Get Pending Leads').item.json.email }}",
              "rightValue": "/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "d56fdd05-3d2e-4f5c-9672-2578361bd962",
      "name": "Mark as INVALID_EMAIL",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        864,
        1280
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "INVALID_EMAIL",
            "updated_at": "={{ $now.toFormat('dd/MM/yyyy HH:mm') }}"
          },
          "schema": [
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false
            },
            {
              "id": "updated_at",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "updated_at",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyValue": "={{ $('Get Pending Leads').item.json.id }}"
            }
          ]
        },
        "options": {},
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Context').item.json.data_table_id }}"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "6b50877c-3fb6-4728-a5fc-119b53e4f070",
      "name": "Fetch Lead Website",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        864,
        1088
      ],
      "parameters": {
        "url": "={{ $('Get Pending Leads').item.json.website }}",
        "options": {
          "timeout": 10000,
          "response": {
            "response": {
              "responseFormat": "text"
            }
          }
        }
      },
      "typeVersion": 4.4,
      "continueOnFail": true
    },
    {
      "id": "b6ca2125-e7ab-4dfd-a6e3-3667447fb6fc",
      "name": "Strip HTML Tags",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        1088
      ],
      "parameters": {
        "jsCode": "const item = $input.first();\nconst html = item.json.data || item.json.body || '';\n\n// Remove scripts, styles, and all HTML tags\nlet cleaned = html\n  .replace(/<script[\\s\\S]*?<\\/script>/gi, '')\n  .replace(/<style[\\s\\S]*?<\\/style>/gi, '')\n  .replace(/<[^>]+>/g, ' ')\n  .replace(/\\s+/g, ' ')\n  .trim();\n\n// Limit to 2000 chars to avoid LLM token overflow\nif (cleaned.length > 2000) {\n  cleaned = cleaned.substring(0, 2000) + '...';\n}\n\nitem.json.website_content = cleaned;\nreturn [item];"
      },
      "typeVersion": 2
    },
    {
      "id": "0ae1c6f7-1655-4d2f-ba4c-a2563ce5c930",
      "name": "AI Outreach Writer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1312,
        1088
      ],
      "parameters": {
        "text": "=Generate a personalized B2B cold outreach email for the following lead.\n\n**Lead Information:**\n- First Name: {{ $('Validate Email Format').item.json.first_name }}\n- Last Name: {{ $('Validate Email Format').item.json.last_name }}\n- Company: {{ $('Validate Email Format').item.json.company_name }}\n- Website: {{ $('Validate Email Format').item.json.website }}\n- Website Content Summary: {{ $('Strip HTML Tags').item.json.website_content }}\n\n**Our Company:**\n- Name: {{ $('Set Context').item.json.sender_company_name }}\n- Solution: {{ $('Set Context').item.json.sender_company_solution }}\n- Sender Name: {{ $('Set Context').item.json.sender_name }}\n\n**Constraints:**\n- Maximum {{ $('Set Context').item.json.email_max_words }} words total\n- Professional yet friendly tone\n- End with: \"Looking forward to hearing from you!\"",
        "options": {
          "systemMessage": "=You are a senior B2B marketing strategist with 20+ years of experience writing cold outreach emails that achieve above-average reply rates.\n\nYour task: Write a highly personalized cold outreach email based on the provided lead's company website and our solution.\n\nWriting rules:\n1. Opening line MUST reference something specific about the lead's business (from their website content)\n2. Bridge to our solution naturally \u2014 show alignment, not a hard sell\n3. Keep the CTA soft: suggest a quick call or reply, not a commitment\n4. No generic phrases like \"I hope this email finds you well\"\n5. Total email body must be under {{ $('Set Context').item.json.email_max_words }} words\n\nReturn ONLY a valid JSON object. No markdown fences, no preamble:\n{\n  \"subject\": \"string \u2014 compelling subject line under 60 chars\",\n  \"greeting\": \"string \u2014 e.g. Hi [FirstName],\",\n  \"opening_line\": \"string \u2014 personalized first sentence referencing their business\",\n  \"main_body\": \"string \u2014 2-3 sentences introducing our solution and value prop\",\n  \"ending\": \"string \u2014 soft CTA + sign-off including sender name\"\n}"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3.1
    },
    {
      "id": "161c5365-ae92-434b-ad57-ffc53b076b09",
      "name": "Google Gemini Flash",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1264,
        1520
      ],
      "parameters": {
        "options": {},
        "modelName": "=models/gemini-3.1-flash-lite"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b92550c0-a332-4c53-a888-c633099a1b70",
      "name": "Parse Email JSON",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1392,
        1312
      ],
      "parameters": {
        "autoFix": true,
        "jsonSchemaExample": "{\n  \"subject\": \"Quick idea for [Company Name]\",\n  \"greeting\": \"Hi John,\",\n  \"opening_line\": \"I noticed your team at Acme is rapidly expanding into Southeast Asia \u2014 impressive growth.\",\n  \"main_body\": \"At GenStaff, we help companies like yours scale operations with AI-powered staffing solutions, so your team can focus on strategy, not repetitive work. We've helped similar firms cut operational costs by 30% in the first quarter.\",\n  \"ending\": \"Would you be open to a 15-minute call this week? Looking forward to hearing from you!\\n\\nBest,\\nJay Nguyen\\nGenStaff \u2014 genstaff.net\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "1043e897-1008-4284-b2d1-f2732ff36ea7",
      "name": "Send Outreach Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1760,
        1088
      ],
      "parameters": {
        "sendTo": "={{ $('Validate Email Format').item.json.email }}",
        "message": "={{ $('AI Outreach Writer').item.json.output.greeting }}\n\n{{ $('AI Outreach Writer').item.json.output.opening_line }}\n\n{{ $('AI Outreach Writer').item.json.output.main_body }}\n\n{{ $('AI Outreach Writer').item.json.output.ending }}",
        "options": {
          "appendAttribution": false
        },
        "subject": "={{ $('AI Outreach Writer').item.json.output.subject }}",
        "emailType": "text",
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a7cebca7-1ede-4b2b-b8bd-02505f69fb52",
      "name": "Mark as SENT",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1984,
        1088
      ],
      "parameters": {
        "columns": {
          "value": {
            "status": "SENT",
            "sent_at": "={{ $now.toFormat('dd/MM/yyyy HH:mm') }}",
            "email_subject": "={{ $('AI Outreach Writer').item.json.output.subject }}"
          },
          "schema": [
            {
              "id": "status",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "status",
              "defaultMatch": false
            },
            {
              "id": "sent_at",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "sent_at",
              "defaultMatch": false
            },
            {
              "id": "email_subject",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "email_subject",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyValue": "={{ $('Validate Email Format').item.json.id }}"
            }
          ]
        },
        "options": {},
        "operation": "upsert",
        "dataTableId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Context').item.json.data_table_id }}"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "aca189f1-98a4-43c1-91ea-407b9ffcebca",
      "name": "Rate Limit Wait",
      "type": "n8n-nodes-base.wait",
      "position": [
        2208,
        1088
      ],
      "parameters": {
        "amount": "={{ $('Set Context').item.json.rate_limit_seconds }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "dffac66d-c599-4a2d-bc01-d185e4aab768",
      "name": "Main Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        752
      ],
      "parameters": {
        "width": 550,
        "height": 960,
        "content": "## Draft and send personalized B2B cold outreach emails using Gemini AI and n8n Data Table\n\nThis workflow automates the process of fetching pending leads, researching their company website, and generating a highly personalized cold email using **Gemini AI**. The finalized email is dispatched via **Gmail**, and the lead status is reliably tracked using **n8n Data Table**.\n\nAll runtime variables (sender info, prompt constraints, table IDs) are centralized in a single `Set Context` node for effortless customization.\n\n### How it works\n1. **Trigger:** A Schedule Trigger runs the workflow at defined intervals (e.g., every 5 minutes).\n2. **Fetch & Validate:** Pulls \"PENDING\" leads from the **n8n Data Table**. Invalid emails are immediately marked as `INVALID_EMAIL`.\n3. **AI Research:** Scrapes the lead's website, strips HTML tags, and summarizes the content to give the AI context.\n4. **Generate & Parse:** The **Gemini AI Agent** drafts a personalized email referencing the lead's business, which is strictly parsed into JSON.\n5. **Deliver & Update:** Sends the email via **Gmail**, updates the Data Table status to `SENT`, and enforces a rate limit delay to ensure high deliverability.\n\n### Setup\n* [ ] Connect your **n8n Data Table** and insert its ID into the `Set Context` node.\n* [ ] Connect the **Google Gemini** API key in the LLM node.\n* [ ] Connect your **Gmail OAuth2** credential in the Send Outreach Email node.\n* [ ] Update your company info, sender details, and AI prompt rules in `Set Context`.\n* [ ] Activate the workflow.\n\n### Customization tips\n* **Different Email Provider:** Swap the Gmail node for Outlook or an SMTP node.\n* **CRM Integration:** Replace the Data Table nodes with Hubspot or Pipedrive nodes to pull and update lead statuses directly.\n\n### LICENCE\nThis template is shared free of charge. Copyright belongs to Nguyen Thieu Toan. Any copying or modification must credit the author."
      },
      "typeVersion": 1
    },
    {
      "id": "68e9283f-8628-43f1-a9bd-0cd7db016ce9",
      "name": "Section 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -32,
        752
      ],
      "parameters": {
        "color": 7,
        "width": 848,
        "height": 580,
        "content": "## Section 1: Fetch & Validate Leads\nFetches \"PENDING\" leads from the Data Table and strictly validates the email format. Invalid emails are routed to a separate update node to prevent bounce rates."
      },
      "typeVersion": 1
    },
    {
      "id": "bde90894-2988-4735-a946-9536d6c02fd6",
      "name": "Section 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        848,
        752
      ],
      "parameters": {
        "color": 7,
        "width": 852,
        "height": 900,
        "content": "## Section 2: AI Research & Generation\nFetches the lead's website content, cleans the HTML, and uses the **Google Gemini** AI Agent to generate a highly personalized cold outreach email parsed into structured JSON."
      },
      "typeVersion": 1
    },
    {
      "id": "7436da74-ba4f-451f-9fd8-5590dc6882d3",
      "name": "Section 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1728,
        752
      ],
      "parameters": {
        "color": 7,
        "width": 668,
        "height": 580,
        "content": "## Section 3: Delivery & Status Update\nDispatches the generated email via **Gmail**, updates the lead's status to `SENT` in the Data Table, and applies a wait node to respect email sending rate limits."
      },
      "typeVersion": 1
    },
    {
      "id": "e7ebd1bd-9f55-44d1-abc0-8528686e42f0",
      "name": "Warning Setup",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        976
      ],
      "parameters": {
        "color": 3,
        "width": 272,
        "height": 180,
        "content": "## \u26a0\ufe0f Important!\n\nUpdate the `data_table_id`, sender details, and company solution inside the **Set Context** node before running."
      },
      "typeVersion": 1
    },
    {
      "id": "b6c4f194-0812-41b2-ac4d-dbd7ee8802c3",
      "name": "Author Message",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2416,
        752
      ],
      "parameters": {
        "color": 4,
        "width": 358,
        "height": 588,
        "content": "## Author Message\n\nHi! I am **Nguyen Thieu Toan (Jay Nguyen)** \u2014 a Verified n8n Creator and CEO/Founder of **GenStaff**. Thank you for using this template!\n\nThis workflow is shared with you for free. If it brings value to your work, optimizes your operations, or saves you time, you can buy me a coffee here: **[My Donate Website](https://nguyenthieutoan.com/payment/)** *(PayPal, Momo, Bank Transfer)*\n\n* Website: [nguyenthieutoan.com](https://nguyenthieutoan.com)\n* Email: me@nguyenthieutoan.com\n* Company: GenStaff ([genstaff.net](https://genstaff.net))\n* Socials (Facebook / X / LinkedIn): @nguyenthieutoan\n\n*Discover more of my automation solutions:* **[Click here](https://n8n.io/creators/nguyenthieutoan/)**"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "117e4275-349c-44d5-9e46-8e8ed3e9a0e6",
  "connections": {
    "Set Context": {
      "main": [
        [
          {
            "node": "Get Pending Leads",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark as SENT": {
      "main": [
        [
          {
            "node": "Rate Limit Wait",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Strip HTML Tags": {
      "main": [
        [
          {
            "node": "AI Outreach Writer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Email JSON": {
      "ai_outputParser": [
        [
          {
            "node": "AI Outreach Writer",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Set Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Pending Leads": {
      "main": [
        [
          {
            "node": "Validate Email Format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Outreach Writer": {
      "main": [
        [
          {
            "node": "Send Outreach Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Lead Website": {
      "main": [
        [
          {
            "node": "Strip HTML Tags",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Flash": {
      "ai_languageModel": [
        [
          {
            "node": "AI Outreach Writer",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "Parse Email JSON",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Send Outreach Email": {
      "main": [
        [
          {
            "node": "Mark as SENT",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Email Format": {
      "main": [
        [
          {
            "node": "Fetch Lead Website",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Mark as INVALID_EMAIL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}