AutomationFlowsData & Sheets › Email List Validation and Cleanup with Google Sheets and Verifiemail

Email List Validation and Cleanup with Google Sheets and Verifiemail

ByJitesh Dugar @jiteshdugar on n8n.io

A fully automated workflow that cleans, validates, and restructures your subscriber list using Google Sheets and VerifiEmail. Perfect for marketers, SaaS teams, or anyone maintaining an email database.

Webhook trigger★★★★☆ complexity18 nodesN8N Nodes VerifiemailGoogle Sheets
Data & Sheets Trigger: Webhook Nodes: 18 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #11017 — 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 →

Download .json
{
  "id": "",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "name": "Email Subscription Cleaner",
  "tags": [],
  "nodes": [
    {
      "id": "5d8be98a-8a42-41a7-8ec6-7c27c6e0d4ed",
      "name": "Webhook - Receive Email Batch",
      "type": "n8n-nodes-base.webhook",
      "notes": "Webhook triggers workflow whenever a new batch of emails is submitted.",
      "position": [
        -1024,
        112
      ],
      "parameters": {
        "path": "email-batch",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 1
    },
    {
      "id": "a765ac5c-eea4-40cb-95c6-301136ca2451",
      "name": "Verifi Email",
      "type": "n8n-nodes-verifiemail.verifiEmail",
      "position": [
        -192,
        112
      ],
      "parameters": {
        "email": "={{ $json.email }}"
      },
      "credentials": {
        "verifiEmailApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "dfc27fb8-83f9-4c33-93f9-72873c78a975",
      "name": "Extract Inputs",
      "type": "n8n-nodes-base.function",
      "notes": "Removes duplicate emails to avoid redundant validation.",
      "position": [
        -848,
        112
      ],
      "parameters": {
        "functionCode": "return [\n  {\n    json: {\n      listId: $json.body.list_id,\n      priority: $json.body.priority,\n      runNotes: $json.body.run_notes,\n      options: $json.body.options\n    }\n  }\n];\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e566695e-c02f-4021-961d-fe09a05b2460",
      "name": "Fetch Subscribers",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -672,
        112
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_DOCUMENT_ID/edit#gid=0",
          "cachedResultName": "YOUR_SHEET_NAME"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEETS_DOCUMENT_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_DOCUMENT_ID/edit?usp=drivesdk",
          "cachedResultName": "SubscriberList"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "f15ef094-746d-4e52-bf60-bb20939de377",
      "name": "Normalize Subscriber",
      "type": "n8n-nodes-base.code",
      "position": [
        -432,
        112
      ],
      "parameters": {
        "jsCode": "return {\n  row_number: $json.row_number,\n  email: $json.email.toLowerCase().trim(),\n  name: $json.name || \"\",\n  subscribed: $json.subscribed?.toLowerCase() === \"yes\",\n  last_activity: $json.last_activity || null,\n  tags: $json.tags || \"\",\n  notes: $json.notes || \"\"\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "d1428247-0b5c-491f-83f5-4b16b853a4e0",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        -48,
        304
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "63644ab4-5ea9-46b8-bbb5-b7678b87070a",
      "name": "Classify Email",
      "type": "n8n-nodes-base.code",
      "position": [
        96,
        112
      ],
      "parameters": {
        "jsCode": "const email = $json.email;\nconst v = $json.details;\n\n// default\nlet classification = \"good\";\nlet action = \"keep\";\n\n// Disposable \u2192 remove\nif (v.disposable === true) {\n  classification = \"disposable\";\n  action = \"remove\";\n}\n\n// Invalid or no MX \u2192 remove\nelse if ($json.valid === false || v.validMxRecord === false) {\n  classification = \"hard_bounce\";\n  action = \"remove\";\n}\n\n// Role-based emails (if you want)\nelse if (email.match(/(admin|info|support|help|team)@/i)) {\n  classification = \"role_account\";\n  action = \"tag\";\n}\n\nreturn {\n  ...$json,\n  classification,\n  action\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e679f3b6-514c-4532-8c48-a3b254029ad8",
      "name": "Should Remove?",
      "type": "n8n-nodes-base.if",
      "position": [
        352,
        112
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9a3a4803-698c-43f2-a2b5-9d950a5e8e48",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{$json.action}}",
              "rightValue": "remove"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7c930aac-e59c-4366-a5f9-c1e9fa638a18",
      "name": "Delete rows or columns from sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        576,
        16
      ],
      "parameters": {
        "operation": "delete",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_DOCUMENT_ID/edit#gid=0",
          "cachedResultName": "YOUR_SHEET_NAME"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEETS_DOCUMENT_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_DOCUMENT_ID/edit?usp=drivesdk",
          "cachedResultName": "SubscriberList"
        },
        "startIndex": "={{$json.row_number}}"
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "77f3f872-250f-4d9c-a737-b4e84d50c6b0",
      "name": "Append Clean Emails",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        576,
        192
      ],
      "parameters": {
        "columns": {
          "value": {
            "name": "={{ $('Classify Email').item.json.name }}",
            "tags": "={{ $('Classify Email').item.json.tags }}",
            "email": "={{ $('Classify Email').item.json.email }}",
            "notes": "={{ $('Classify Email').item.json.notes }}",
            "action": "={{ $('Classify Email').item.json.action }}",
            "last_activity": "={{ $('Classify Email').item.json.last_activity }}",
            "classification": "={{ $('Classify Email').item.json.classification }}"
          },
          "schema": [
            {
              "id": "name",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "last_activity",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "last_activity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "tags",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "tags",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "notes",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "notes",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "classification",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "classification",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "action",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "action",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_DOCUMENT_ID/edit#gid=YOUR_SHEET_ID",
          "cachedResultName": "clean subscriber"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEETS_DOCUMENT_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEETS_DOCUMENT_ID/edit?usp=drivesdk",
          "cachedResultName": "SubscriberList"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "331398e6-fab0-4da8-bf51-6b2af319123c",
      "name": "Success response",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        896,
        128
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"status\": \"completed\",\n  \"removed\": \"{{$json.action === 'remove'}}\",\n  \"email\": \"{{$json.email}}\",\n  \"notes\": \"cleanup done\"\n}"
      },
      "typeVersion": 1.4
    },
    {
      "id": "8367421e-030a-4b51-bc33-8e371923e034",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1408,
        -304
      ],
      "parameters": {
        "width": 288,
        "height": 256,
        "content": "## **How It Works**\n\n**EMAIL CLEANER \u2013 AUTOMATED**\n\u2022 Reads subscribers from Google Sheets\n\u2022 Normalizes + validates email\n\u2022 Flags disposable/invalid domains\n\u2022 Removes bad entries, keeps good ones\n\u2022 Writes clean list + returns JSON\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "0022bafe-53f4-4ac5-8f03-a8a04f6c231a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1376,
        0
      ],
      "parameters": {
        "height": 256,
        "content": "## **Setup**\n\n**REQUIRED CREDENTIALS**\n\u2022 Google Sheets (read/delete/append)\n\u2022 VerifiEmail API at verifi.email\n**Before running:**\n\u2022 Confirm sheet name\n\u2022 Confirm column structure\n\u2022 Update tag rules if needed\n\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "53c61121-bda7-48d5-9603-c95870f221a6",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -480,
        -64
      ],
      "parameters": {
        "color": 5,
        "width": 432,
        "height": 320,
        "content": "# **Validation**\n\n**PRE-CHECKS**\n\u2022 Normalize subscriber data\n\u2022 Validate email health (MX + disposable)\n\u2022 Mark each email with action \u2192 keep/remove\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c4742c6e-20f5-4a10-a7d8-4a19241bd72e",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        -48
      ],
      "parameters": {
        "color": 5,
        "width": 304,
        "height": 288,
        "content": "# **Classification**\n\n**LOGIC**\n\u2022 remove \u2192 disposable / invalid / role\n\u2022 keep \u2192 valid + active\n\u2022 tag \u2192 special rule (optional)"
      },
      "typeVersion": 1
    },
    {
      "id": "03d4b8e5-590a-4b46-a741-08e692a3a701",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        496,
        -176
      ],
      "parameters": {
        "color": 5,
        "width": 320,
        "height": 512,
        "content": "# **Cleanup**\n\n**ACTIONS**\n\u2022 remove \u2192 delete row\n\u2022 keep \u2192 append to CleanSubscribers\n\u2022 Preserves row_number + metadata"
      },
      "typeVersion": 1
    },
    {
      "id": "0ec235c1-9150-45b5-a22b-b8b2df96a768",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        848,
        -32
      ],
      "parameters": {
        "color": 5,
        "width": 272,
        "height": 288,
        "content": "# **Response**\n\n**WEBHOOK OUTPUT**\n\u2022 Returns: email, action, status\n\u2022 Clean JSON summary for Postman\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "1f869416-2c93-45d7-a17d-256561289c20",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1072,
        -80
      ],
      "parameters": {
        "color": 5,
        "width": 528,
        "height": 336,
        "content": "# **Intake & Extraction**\n\n\u2022 Receives cleanup request via Webhook\n\u2022 Extracts listId, priority, run notes & options\n\u2022 Loads subscriber rows from Google Sheets\n\u2022 Provides row_number, email, name, tags, activity\n\u2022 Prepares all data for validation flow\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Classify Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verifi Email": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify Email": {
      "main": [
        [
          {
            "node": "Should Remove?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Inputs": {
      "main": [
        [
          {
            "node": "Fetch Subscribers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Should Remove?": {
      "main": [
        [
          {
            "node": "Delete rows or columns from sheet",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Append Clean Emails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Subscribers": {
      "main": [
        [
          {
            "node": "Normalize Subscriber",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append Clean Emails": {
      "main": [
        [
          {
            "node": "Success response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Subscriber": {
      "main": [
        [
          {
            "node": "Verifi Email",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Webhook - Receive Email Batch": {
      "main": [
        [
          {
            "node": "Extract Inputs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Delete rows or columns from sheet": {
      "main": [
        [
          {
            "node": "Success response",
            "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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

A fully automated workflow that cleans, validates, and restructures your subscriber list using Google Sheets and VerifiEmail. Perfect for marketers, SaaS teams, or anyone maintaining an email database.

Source: https://n8n.io/workflows/11017/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

This workflow automatically cleans, validates, and standardizes any CSV file you upload. Perfect for preparing customer lists, sales leads, product catalogs, or any messy datasets before pushing them

Google Drive, Google Sheets
Data & Sheets

This n8n workflow fetches URLs from an RSS feed, checks which URLs have a valid RSS feed and if true, fetches the latest articles from those URLs. It then stores the article details, including the art

RSS Feed Read, Stop And Error, Google Sheets +1
Data & Sheets

This n8n template helps you manage and validate tokens easily using: n8n as your backend workflow engine Airtable as your lightweight token store Stores user tokens securely in Airtable with expiry or

Airtable, HTTP Request
Data & Sheets

This workflow allows you to generate QR codes (Barcodes) in bulk from a Google Sheets file and store the generated QR images automatically in Google Drive. Each QR code contains a unique identifier (i

Google Drive, HTTP Request, Google Sheets
Data & Sheets

I built this tool because we faced a real, recurring problem: managing hundreds of client projects in a weekly automated loop.

Stop And Error, Redis, Execute Workflow Trigger +2