← All Productivity Workflows
BillionVerifyGmail

Extract web page data from Gmail links and save to Google Sheets

Pull contacts, verify each address with BillionVerify, and continue to Gmail — only deliverable addresses get through.

Why verify before the send

Sending to invalid, risky, catch-all, or disposable addresses spikes your bounce rate and erodes sender reputation. A verification gate before the Gmail step removes that risk automatically — only deliverable addresses continue, the rest are flagged.

The workflow

BillionVerify — verification sits right before the send.

When clicking ‘Test workflow’
+8
n8n steps

Node by node

  1. 1
    When clicking ‘Test workflow’Trigger· n8n

    Starts the workflow — on a schedule, a webhook, or manually while you test.

  2. 2
    Verify Email (BillionVerify)Verify· billionverify

    The BillionVerify node verifies the address — status (valid / invalid / risky / catch-all / role / disposable), is_deliverable, and a confidence score — before anything is sent.

  3. 3
    IF deliverableLogic· n8n

    Branches on the verification result: only deliverable addresses continue to the send; the rest are skipped and flagged.

  4. 4
    Search EmailsSend· n8n

    Sends only to verified, deliverable addresses. Swap in your own provider node if you send elsewhere.

  5. 5
    search for an element in the email bodySource· n8n

    Provides or transforms the contact data flowing through the workflow.

  6. 6
    open the linkSource· n8n

    Provides or transforms the contact data flowing through the workflow.

  7. 7
    capture dataSource· n8n

    Provides or transforms the contact data flowing through the workflow.

  8. 8
    processes informationSource· n8n

    Provides or transforms the contact data flowing through the workflow.

  9. 9
    set variablesSource· n8n

    Provides or transforms the contact data flowing through the workflow.

  10. 10
    Save data in spreadsheetSource· n8n

    Provides or transforms the contact data flowing through the workflow.

Workflow JSON

Copy or download this workflow, then import it in n8n (Workflows → Import from File / Paste). Install the BillionVerify community node first, then add your API key credential.

verify-emails-in-gmail.json
{
  "name": "Extract web page data from Gmail links and save to Google Sheets + BillionVerify",
  "nodes": [
    {
      "id": "996ac1ec-c471-4734-a82c-c44c16ce74ad",
      "name": "When clicking ‘Test workflow’",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1728,
        -400
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "8473c056-35d1-4e47-96dd-e0cb30e14ad1",
      "name": "Search Emails",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -1504,
        -400
      ],
      "webhookId": "55c11b0e-7461-43de-b9d3-a3904f3dd525",
      "parameters": {
        "simple": false,
        "filters": {
          "sender": "user@example.com",
          "receivedAfter": "2025-09-30T00:00:00",
          "receivedBefore": "2025-09-22T00:00:00"
        },
        "options": {},
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "credential-id",
          "name": "gmailOAuth2 Credential"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "2c6c6140-160d-4198-a0cc-3fa17530859e",
      "name": "search for an element in the email body",
      "type": "n8n-nodes-base.html",
      "position": [
        -1280,
        -400
      ],
      "parameters": {
        "options": {},
        "operation": "extractHtmlContent",
        "dataPropertyName": "html",
        "extractionValues": {
          "values": [
            {
              "key": "dados",
              "attribute": "href",
              "cssSelector": "=a[style*=\"color: #ffffff\"]",
              "returnValue": "attribute"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "7e6693f3-0607-49a3-9725-d844a8b45319",
      "name": "open the link",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        -1072,
        -400
      ],
      "parameters": {
        "url": "={{ $json.dados }}",
        "options": {}
      },
      "retryOnFail": false,
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "4a04204c-e8dc-4865-963a-000378aa1024",
      "name": "capture data",
      "type": "n8n-nodes-base.html",
      "position": [
        -832,
        -416
      ],
      "parameters": {
        "options": {},
        "operation": "extractHtmlContent",
        "extractionValues": {
          "values": [
            {
              "key": "dtnasc",
              "cssSelector": "#lblMemberDateOfBirth"
            },
            {
              "key": "id",
              "cssSelector": "#txtCase"
            },
            {
              "key": "data_solicitacao",
              "cssSelector": "#lblCaseOpenOn"
            },
            {
              "key": "Local_pt01",
              "cssSelector": "#lblMemberFullAddress"
            },
            {
              "key": "Local_pt02",
              "cssSelector": "#lblLocationHotelName"
            },
            {
              "key": "Nome",
              "cssSelector": "#lblMemberFirstName"
            },
            {
              "key": "sobrenome",
              "cssSelector": "#lblMemberLastName"
            },
            {
              "key": "Queixa",
              "cssSelector": "#lblCaseReportedIssue"
            },
            {
              "key": "Link",
              "cssSelector": "=",
              "returnValue": "value"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a3d87c4d-1c96-461c-bc45-42e4a3c7469c",
      "name": "processes information",
      "type": "n8n-nodes-base.code",
      "position": [
        -608,
        -416
      ],
      "parameters": {
        "jsCode": "// Função para converter string \"DD/MM/YYYY HH:MM\" para objeto Date\nfunction parseDateOnly(dateTimeStr) {\n  if (!dateTimeStr) return null;\n  const parts = dateTimeStr.split(' ')[0].split('/'); // pega apenas DD/MM/YYYY\n  if (parts.length !== 3) return null;\n  const day = parseInt(parts[0], 10);\n  const month = parseInt(parts[1], 10) - 1; // meses em JS vão de 0 a 11\n  const year = parseInt(parts[2], 10);\n  return new Date(year, month, day);\n}\n\n// Função para extrair apenas o número do ID, removendo prefixos como \"Caso ID :\" ou \"Case ID :\"\nfunction extractCaseId(idStr) {\n  if (!idStr) return null;\n  return idStr.replace(/(Caso|Case)\\s*ID\\s*:\\s*/i, '').trim();\n}\n\n// Recupera todos os e-mails e links correspondentes\nconst emailItems = $('Search Emails').all();\nconst linkItems = $('search for an element in the email body').all();\n\n// Percorre todos os itens de entrada\nconst results = [];\nconst inputItems = $input.all();\n\nfor (let i = 0; i < inputItems.length; i++) {\n  const item = inputItems[i];\n  const birthDateStr = item.json.dtnasc;\n  const requestDateTimeStr = item.json.data_solicitacao;\n  const rawId = item.json.id;\n\n  // Tratamento do ID\n  const caseId = extractCaseId(rawId);\n\n  // Captura o subject e o link correspondentes (mesmo índice)\n  const emailSubject = emailItems[i]?.json?.headers?.subject || null;\n  const emailLink = linkItems[i]?.json?.dados || null;\n\n  // Determina o tipo de atendimento com base no subject\n  let attendanceType = \"PRESENCIAL\";\n  if (emailSubject && emailSubject.toLowerCase().includes(\"tele-medicine\")) {\n    attendanceType = \"TELEMEDICINA\";\n  }\n\n  // Se faltar algum dado essencial, apenas devolve o item como está\n  if (!birthDateStr || !requestDateTimeStr) {\n    results.push({\n      json: {\n        ...item.json,\n        caseId: caseId || null,\n        emailSubject: emailSubject,\n        attendanceType: attendanceType,\n        link: emailLink\n      }\n    });\n    continue;\n  }\n\n  const birthDate = parseDateOnly(birthDateStr);\n\n  // Separar data e horário\n  const [datePart, timePart] = requestDateTimeStr.split(' '); // \"DD/MM/YYYY\" e \"HH:MM\"\n  const requestDate = parseDateOnly(datePart);\n\n  if (!birthDate || !requestDate) {\n    results.push({\n      json: {\n        ...item.json,\n        caseId: caseId || null,\n        emailSubject: emailSubject,\n        attendanceType: attendanceType,\n        link: emailLink\n      }\n    });\n    continue;\n  }\n\n  // Calcula a idade\n  let age = requestDate.getFullYear() - birthDate.getFullYear();\n  const m = requestDate.getMonth() - birthDate.getMonth();\n  if (m < 0 || (m === 0 && requestDate.getDate() < birthDate.getDate())) {\n    age--;\n  }\n\n  // Retorna o item completo com todos os campos tratados\n  results.push({\n    json: {\n      ...item.json,\n      age: age,\n      requestDate: datePart,    // apenas a data\n      requestTime: timePart,    // apenas o horário\n      caseId: caseId,           // número do caso limpo\n      emailSubject: emailSubject, // texto do subject do e-mail\n      attendanceType: attendanceType, // \"TELEMEDICINA\" ou \"PRESENCIAL\"\n      link: emailLink           // link correspondente ao e-mail\n    }\n  });\n}\n\nreturn results;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "ac95be81-23fa-4833-9bbf-46a68d172a2f",
      "name": "set variables",
      "type": "n8n-nodes-base.set",
      "position": [
        -384,
        -416
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "bcf5bbaa-2930-4c59-93c3-add1b31fdb7c",
              "name": "id",
              "type": "string",
              "value": "={{ $json.caseId }}"
            },
            {
              "id": "c46a4f49-c77f-4239-83f2-1a1334bf31ae",
              "name": "Nome_Paciente",
              "type": "string",
              "value": "={{ $json.Nome }} {{ $json.sobrenome }}"
            },
            {
              "id": "a2b523a0-6d65-442f-a23a-5e2ec3e8f17f",
              "name": "Dt_solicitacao",
              "type": "string",
              "value": "={{ $json.requestDate }}"
            },
            {
              "id": "7b421b6a-99fe-479a-ac7d-c580c02f6ee0",
              "name": "Queixa",
              "type": "string",
              "value": "={{ $json.Queixa }}"
            },
            {
              "id": "11941808-a53b-4d12-aaef-910120a5b512",
              "name": "Idade",
              "type": "string",
              "value": "={{ $json.age }}"
            },
            {
              "id": "9a0ff300-33ec-4dc6-831f-e21ad8148b84",
              "name": "Local",
              "type": "string",
              "value": "={{ $json.Local_pt01 }} {{ $json.Local_pt02 }}"
            },
            {
              "id": "0133b215-4db9-47ea-a2b8-ef80a4f052fa",
              "name": "horario",
              "type": "string",
              "value": "={{ $json.requestTime }}"
            },
            {
              "id": "a42de334-56c3-4180-bc7c-d926ebd4c2b2",
              "name": "Link",
              "type": "string",
              "value": "={{ $json.link }}"
            },
            {
              "id": "85b87a31-662f-4ef4-9b73-9211b0bd9511",
              "name": "Tipo atendimento",
              "type": "string",
              "value": "={{ $json.attendanceType }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "907f9531-8fdd-4bce-9a8a-b03e7edsdsdsd202180",
      "name": "Save data in spreadsheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -144,
        -416
      ],
      "parameters": {
        "columns": {
          "value": {
            "DATA": "={{ $json.Dt_solicitacao }}",
            "LINK": "={{ $json.Link }}",
            "NOME": "={{ $json.Nome_Paciente }}",
            " CASO": "={{ $json.id }}",
            "IDADE": "={{ $json.Idade }}",
            "LOCAL": "={{ $json.Local }}",
            "QUEIXA": "={{ $json.Queixa }}",
            "HORÁRIO": "={{ $json.horario }}",
            "TIPO CONSULTA ": "={{ $json['Tipo atendimento'] }}"
          },
          "schema": [
            {
              "id": "HORÁRIO",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "HORÁRIO",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DATA",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "DATA",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "EMPRESA",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "EMPRESA",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "TIPO CONSULTA ",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "TIPO CONSULTA ",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LOCAL",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LOCAL",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "NOME",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "NOME",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": " CASO",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": " CASO",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "IDADE",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "IDADE",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "QUEIXA",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "QUEIXA",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "LINK",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "LINK",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "DIAGNOSTICO",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "DIAGNOSTICO",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "MEDICAÇÃO PRESCRITA",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "MEDICAÇÃO PRESCRITA",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "INJETAVEIS /PROCEDIMENTOS",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "INJETAVEIS /PROCEDIMENTOS",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 311390915,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bbcFz1111wO77RBr0t8hYaAEuzEsr24MJrFWuIPzoC-XMjx8/edit#gid=311390915",
          "cachedResultName": "Outubro-2025"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1bbcFzO77RBr0t8hYaAEuzEsr24MJrFWuIPzoC-XMjx8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bbcFz111O77RBr0t8hYaAEuzEsr24MJrFWuIPzoC-XMjx8/edit?usp=drivesdk",
          "cachedResultName": "NOREPLY"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "credential-id",
          "name": "googleSheetsOAuth2Api Credential"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "9fedd068-0a9b-44a1-bde1-de312dfc6ced",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1568,
        -496
      ],
      "parameters": {
        "width": 208,
        "height": 272,
        "content": "**earch for emails** received from a sender within a specific time period."
      },
      "typeVersion": 1
    },
    {
      "id": "584ddb97-097b-452c-a632-a534537965d0",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1344,
        -496
      ],
      "parameters": {
        "color": 4,
        "width": 208,
        "height": 272,
        "content": "**Search for a specific css element** in the email code"
      },
      "typeVersion": 1
    },
    {
      "id": "f1d3e50c-a187-421f-95a1-009f1f5c8f49",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1120,
        -496
      ],
      "parameters": {
        "color": 3,
        "width": 208,
        "height": 272,
        "content": "**access the link** found in the HTML body of the email"
      },
      "typeVersion": 1
    },
    {
      "id": "c434b579-5fb5-4813-9944-7af5f54101e6",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -896,
        -496
      ],
      "parameters": {
        "color": 4,
        "width": 208,
        "height": 272,
        "content": "**Search for a specific css element** in the email code"
      },
      "typeVersion": 1
    },
    {
      "id": "69282cbc-b64e-4923-b67d-f279cca4e509",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -672,
        -496
      ],
      "parameters": {
        "color": 5,
        "width": 208,
        "height": 272,
        "content": "js code to process the extracted data, **customize as you wish**"
      },
      "typeVersion": 1
    },
    {
      "id": "df2ead67-1e19-4cec-a79c-47259d756545",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -448,
        -496
      ],
      "parameters": {
        "color": 5,
        "width": 208,
        "height": 272,
        "content": "set the desired variables to save"
      },
      "typeVersion": 1
    },
    {
      "id": "2d494ae1-6ab6-473e-8252-b3837a7ea469",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        -496
      ],
      "parameters": {
        "width": 208,
        "height": 272,
        "content": "save the information to the desired Google spreadsheet."
      },
      "typeVersion": 1
    },
    {
      "parameters": {
        "operation": "verify",
        "email": "={{ $json.email || $json.Email }}",
        "additionalOptions": {}
      },
      "type": "n8n-nodes-billionverify.billionVerify",
      "typeVersion": 1,
      "position": [
        -1864,
        -400
      ],
      "name": "Verify Email (BillionVerify)",
      "credentials": {
        "billionVerifyApi": {
          "id": "",
          "name": "BillionVerify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-deliverable",
              "leftValue": "={{ $json.is_deliverable }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        -1684,
        -400
      ],
      "name": "IF deliverable"
    }
  ],
  "connections": {
    "capture data": {
      "main": [
        [
          {
            "node": "processes information",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Emails": {
      "main": [
        [
          {
            "node": "search for an element in the email body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "open the link": {
      "main": [
        [
          {
            "node": "capture data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "set variables": {
      "main": [
        [
          {
            "node": "Save data in spreadsheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "processes information": {
      "main": [
        [
          {
            "node": "set variables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking ‘Test workflow’": {
      "main": [
        [
          {
            "node": "Verify Email (BillionVerify)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "search for an element in the email body": {
      "main": [
        [
          {
            "node": "open the link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Email (BillionVerify)": {
      "main": [
        [
          {
            "node": "IF deliverable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF deliverable": {
      "main": [
        [
          {
            "node": "Search Emails",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}

When to use this

  • Cleaning a list before a Gmail send or sync.
  • Protecting Gmail deliverability and sender reputation.
  • Keeping bounce rates low so your sending is never throttled.

FAQ

Why verify before sending in Gmail?

Verifying first keeps your bounce rate low, which protects your sender reputation and your results.

How do I import this workflow?

Download the JSON, then in n8n go to Workflows → Import from File (or paste it). Install the BillionVerify community node and add your API key credential.

What happens to risky or catch-all addresses?

They are routed to the false branch and excluded from the send. You decide whether to retry, review, or drop them.

Add verification to your workflow

Create a free account, grab your API key, and stop bounces before they happen.

Get started free