AutomationFlowsEmail & Gmail › Search Gmail Messages with n8n Workflow

Search Gmail Messages with n8n Workflow

Original n8n title: Gmail.search_messages

gmail.search_messages. Uses executeWorkflowTrigger, gmail. Event-driven trigger; 5 nodes.

Event trigger★★★★☆ complexity5 nodesExecute Workflow TriggerGmail
Email & Gmail Trigger: Event Nodes: 5 Complexity: ★★★★☆ Added:

This workflow follows the Execute Workflow Trigger → Gmail recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "gmail.search_messages",
  "nodes": [
    {
      "parameters": {},
      "id": "execute-workflow-trigger",
      "name": "Execute Workflow Trigger",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "typeVersion": 1,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// Input validation and cache key generation - handles flat, nested, or wrapped (subInput)\nconst root = $json ?? {};                       // n8n runs Code per item, so $json is the item\nconst input = root.subInput ?? root;            // support accidental wrap: { subInput: {...} }\n\nconst query = input.query ?? input.params?.query;\nconst pageSize = input.pageSize ?? input.maxResults ?? input.params?.pageSize ?? input.params?.maxResults ?? 10;\nconst userId = input.userId ?? input.params?.userId ?? 'me';\nconst pageToken = input.pageToken ?? input.params?.pageToken;\nconst connectionId = input.connectionId;\nconst requestId = input.requestId ?? input.params?.requestId ?? null;\nconst tenantId = input.tenantId ?? input.params?.tenantId;\n\n// Validate required fields\nif (!query) throw new Error('query field is required');\nif (!connectionId) throw new Error('connectionId field is required');\nif (pageSize && (pageSize < 1 || pageSize > 100)) throw new Error('pageSize must be between 1 and 100');\n\nconst normalizedQuery = String(query).trim();\nif (!normalizedQuery) throw new Error('query cannot be empty');\n\n// Generate cache key (include query + pageToken)\nconst selectiveInputs = { query: normalizedQuery, pageSize, pageToken: pageToken || null, userId };\nfunction simpleHash(str) { let h=0; for (let i=0;i<str.length;i++){ const c=str.charCodeAt(i); h=((h<<5)-h)+c; h|=0;} return Math.abs(h).toString(36); }\nconst inputHash = simpleHash(JSON.stringify(selectiveInputs));\nconst cacheKey = `gmail.search_messages:${inputHash}`;\n\nreturn {\n  json: {\n    userId,\n    tenantId,\n    requestId,\n    connectionId,\n    query: normalizedQuery,\n    pageSize,\n    pageToken,\n    cacheKey,\n    cacheTtl: 300,\n    originalInput: selectiveInputs\n  }\n};"
      },
      "id": "input-validation",
      "name": "Input Validation & Cache Key",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ]
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "resource": "message",
        "operation": "getAll",
        "userId": "={{ $json.userId }}",
        "filters": {
          "q": "={{ $json.query }}",
          "maxResults": "={{ $json.pageSize }}",
          "pageToken": "={{ $json.pageToken }}"
        }
      },
      "id": "gmail-search",
      "name": "Gmail Search Messages",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        680,
        300
      ],
      "credentials": {
        "gmailOAuth2": "<your credential>"
      }
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "resource": "message",
        "operation": "get",
        "messageId": "={{ $json.id }}",
        "userId": "={{ $node[\"Input Validation & Cache Key\"].json.userId }}",
        "format": "metadata",
        "additionalFields": {
          "metadataHeaders": [
            "From",
            "To",
            "Subject",
            "Date"
          ]
        }
      },
      "id": "gmail-get-message",
      "name": "Gmail Get Message Details",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2,
      "position": [
        1120,
        300
      ],
      "credentials": {
        "gmailOAuth2": "<your credential>"
      }
    },
    {
      "parameters": {
        "jsCode": "// Process Gmail API response and format results\nconst items = $input.all();\nconst validationData = $node[\"Input Validation & Cache Key\"].json;\nconst searchData = $node[\"Gmail Search Messages\"].json;\n\n// Transform Gmail messages to our standard format\nfunction transformMessage(gmailMessage) {\n  const headers = gmailMessage.payload?.headers || [];\n  \n  function getHeader(name) {\n    const header = headers.find(h => h.name.toLowerCase() === name.toLowerCase());\n    return header ? header.value : '';\n  }\n  \n  return {\n    id: gmailMessage.id,\n    threadId: gmailMessage.threadId,\n    snippet: gmailMessage.snippet || '',\n    from: getHeader('From'),\n    subject: getHeader('Subject'),\n    date: getHeader('Date'),\n    unread: gmailMessage.labelIds?.includes('UNREAD') || false,\n    labels: gmailMessage.labelIds || []\n  };\n}\n\n// Transform all messages\nconst transformedMessages = items.map(item => transformMessage(item.json));\n\n// Extract pagination info\nconst nextPageToken = searchData?.nextPageToken ?? null;\nconst totalCount = searchData?.resultSizeEstimate ?? transformedMessages.length;\n\nconst responseData = {\n  messages: transformedMessages,\n  totalCount: totalCount,\n  query: validationData.query,\n  pageSize: validationData.pageSize,\n  nextPageToken: nextPageToken\n};\n\nreturn {\n  json: {\n    ok: true,\n    brick: 'gmail.search_messages',\n    brickVersion: 'v1',\n    timestamp: new Date().toISOString(),\n    requestId: validationData.requestId,\n    cached: false,\n    data: responseData\n  }\n};"
      },
      "id": "process-response",
      "name": "Process Gmail Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1340,
        300
      ]
    }
  ],
  "connections": {
    "Execute Workflow Trigger": {
      "main": [
        [
          {
            "node": "Input Validation & Cache Key",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Input Validation & Cache Key": {
      "main": [
        [
          {
            "node": "Gmail Search Messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail Search Messages": {
      "main": [
        [
          {
            "node": "Gmail Get Message Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail Get Message Details": {
      "main": [
        [
          {
            "node": "Process Gmail Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "1",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "gmail-search-messages-v1"
}

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

gmail.search_messages. Uses executeWorkflowTrigger, gmail. Event-driven trigger; 5 nodes.

Source: https://github.com/SammyTourani/Pulse/blob/09d51f209c603477a489582b13f5c08d9a0af370/flows/bricks/gmail/gmail.search_messages.json — original creator credit. Request a take-down →

More Email & Gmail workflows → · Browse all categories →

Related workflows

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

Email & Gmail

Splitout Code. Uses manualTrigger, httpRequest, stickyNote, splitOut. Event-driven trigger; 46 nodes.

HTTP Request, Execute Workflow Trigger, Gmail +1
Email & Gmail

Automate CSV imports into HubSpot without the mess. Powered by n8n. Supercharged by Pollup AI.

HTTP Request, Execute Workflow Trigger, Gmail +1
Email & Gmail

Echo Brand Voice Analysis (Processor) - TASK-074 Dec 10 Fix. Uses formTrigger, httpRequest, executeWorkflowTrigger, moveBinaryData. Event-driven trigger; 40 nodes.

Form Trigger, HTTP Request, Execute Workflow Trigger +2
Email & Gmail

Code Filter. Uses googleSheets, gmail, stickyNote, executeWorkflowTrigger. Event-driven trigger; 32 nodes.

Google Sheets, Gmail, Execute Workflow Trigger
Email & Gmail

This n8n workflow enables teams to automate and standardize multi-step onboarding or messaging workflows using Google Sheets, Forms, Gmail, and dynamic logic powered by Code and Switch nodes. It ensur

Google Sheets, Form, Execute Workflow Trigger +2