This workflow corresponds to n8n.io template #13280 — 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 →
{
"id": "KZON3Mzef2dj29N2",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Gmail Support Emails to Zendesk Tickets with Spam & Duplicate Prevention",
"tags": [],
"nodes": [
{
"id": "3ae5ec4d-60ad-42a0-8479-2b3d20c191a9",
"name": "New Support Email Trigger",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
-160,
16
],
"parameters": {
"filters": {},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "bec74235-dabc-44a0-91e0-bc86861ff2a5",
"name": "Spam Detection & Filtering",
"type": "n8n-nodes-base.code",
"position": [
304,
16
],
"parameters": {
"jsCode": "const item = $json;\n\nconst subject = (item.subject || '').toLowerCase();\nconst body = (item.description || '').toLowerCase();\nconst email = (item.customer_email || '').toLowerCase();\n\n// Common spam keywords\nconst spamKeywords = [\n 'win money',\n 'free gift',\n 'click here',\n 'urgent action',\n 'lottery',\n 'bitcoin',\n 'crypto',\n 'investment opportunity'\n];\n\n// Suspicious email domains\nconst spamDomains = [\n 'tempmail',\n '10minutemail',\n 'mailinator',\n 'guerrillamail'\n];\n\n// Keyword match\nconst keywordSpam = spamKeywords.some(k =>\n subject.includes(k) || body.includes(k)\n);\n\n// Domain match\nconst domainSpam = spamDomains.some(d =>\n email.includes(d)\n);\n\n// Final spam decision\nconst isSpam = keywordSpam || domainSpam;\n\n// If spam \u2192 stop workflow\nif (isSpam) {\n return [];\n}\n\n// Not spam \u2192 continue\nreturn [{ json: item }];\n"
},
"typeVersion": 2
},
{
"id": "3c20ee8a-b80c-44d6-84fa-fed064265ec5",
"name": "Extract & Normalize Email Data",
"type": "n8n-nodes-base.set",
"position": [
736,
16
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b17f683e-18b3-4739-90d7-678545009274",
"name": "=customer_name",
"type": "string",
"value": "={{$json[\"From\"].split(\" <\")[0]}}"
},
{
"id": "2bc4671b-2ab3-4248-8cc2-768869bbf868",
"name": "customer_email",
"type": "string",
"value": "={{$json[\"From\"].match(/<(.+)>/)[1]}}"
},
{
"id": "20bfdc42-25c2-4ac0-b342-5fca279e33a9",
"name": "subject",
"type": "string",
"value": "={{$json[\"Subject\"]}}"
},
{
"id": "68ff09ea-01ee-4891-9d77-8c30d8ec6848",
"name": "description",
"type": "string",
"value": "={{$json[\"snippet\"]}}"
},
{
"id": "90d82dab-45dd-4e82-898b-a6cba4d0fc11",
"name": "=thread_id",
"type": "string",
"value": "={{ $json.threadId }}"
},
{
"id": "c8274cde-d223-421d-97b0-03d09a040a11",
"name": "received_at",
"type": "string",
"value": "={{$json[\"internalDate\"]}}"
},
{
"id": "68bfb284-97be-4236-bed4-095e42ddd2da",
"name": "tags",
"type": "string",
"value": "={{$json[\"snippet\"].toLowerCase().includes(\"refund\") ? [\"refund\"] : []}}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "fb6264e5-fc17-488a-8b5c-a52cc38ddccf",
"name": "Auto-Tag Ticket Based on Email Content",
"type": "n8n-nodes-base.code",
"position": [
1008,
-96
],
"parameters": {
"jsCode": "// Get email body from previous node\nconst emailBody = $json[\"description\"].toLowerCase();\n\n// Define keywords and corresponding tags\nconst keywordTags = {\n \"refund\": \"refund\",\n \"damaged\": \"damaged\",\n \"late delivery\": \"late_delivery\"\n};\n\n// Initialize tags array\nlet tags = [];\n\n// Loop through keywords and add tags if found\nfor (const keyword in keywordTags) {\n if (emailBody.includes(keyword)) {\n tags.push(keywordTags[keyword]);\n }\n}\n\n// Return updated data\nreturn [\n {\n json: {\n ...$json,\n tags\n }\n }\n];\n"
},
"typeVersion": 2
},
{
"id": "f7c03701-9a47-44d1-a1d1-4bb07bee340a",
"name": "Zendesk \u2013 Fetch Existing Tickets",
"type": "n8n-nodes-base.zendesk",
"position": [
1008,
80
],
"parameters": {
"options": {},
"operation": "getAll",
"authentication": "oAuth2"
},
"credentials": {
"zendeskOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "6481eb72-b926-4030-842a-a428d05e78f8",
"name": "Merge Email With Existing Tickets",
"type": "n8n-nodes-base.merge",
"position": [
1456,
16
],
"parameters": {},
"typeVersion": 3.2
},
{
"id": "aa789d1a-232d-458f-b75b-b3c9641843ce",
"name": "Detect Duplicate Ticket by Subject",
"type": "n8n-nodes-base.code",
"position": [
1648,
16
],
"parameters": {
"jsCode": "// Get all merged items\nconst items = $input.all();\n\n// First item is always the email\nconst email = items[0].json;\n\n// Remaining items are Zendesk tickets\nconst tickets = items.slice(1).map(i => i.json);\n\n// Safety check\nif (!email || !email.subject) {\n throw new Error('Missing email subject');\n}\n\n// Normalize function\nconst normalize = (str) =>\n str.trim().toLowerCase();\n\n// Check if subject already exists in Zendesk\nconst isDuplicate = tickets.some(ticket =>\n ticket.subject &&\n normalize(ticket.subject) === normalize(email.subject)\n);\n\n// If duplicate \u2192 stop workflow\nif (isDuplicate) {\n return [];\n}\n\n// If NOT duplicate \u2192 allow ticket creation\nreturn [\n {\n json: email\n }\n];\n"
},
"typeVersion": 2,
"alwaysOutputData": true
},
{
"id": "43b0a0d4-3dfa-4e87-9072-7476c677a857",
"name": "Is This a New Ticket?",
"type": "n8n-nodes-base.if",
"position": [
1840,
16
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ec29a493-1e47-4dd1-87a2-846d9506debb",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{$json.isEmpty()}}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.2
},
{
"id": "28ae617a-65fa-4418-bf8d-7bc8b0b21f26",
"name": "Create Zendesk Support Ticket",
"type": "n8n-nodes-base.zendesk",
"position": [
2256,
32
],
"parameters": {
"description": "={{ $json.description }}",
"authentication": "oAuth2",
"jsonParameters": true,
"additionalFieldsJson": "={\n \"subject\": \"{{ $json.subject }}\",\n \"comment\": {\n \"body\": \"{{ $json.description }}\"\n },\n \"requester\": {\n \"name\": \"{{ $json.customer_name }}\",\n \"email\": \"{{ $json.customer_email }}\"\n },\n \"tags\": \"{{ $json.tags }}\",\n \"priority\": \"high\",\n \"status\": \"open\",\n \"external_id\": \"{{ $json.thread_id }}\"\n}\n"
},
"credentials": {
"zendeskOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "e1aeb752-3e5a-4551-bf2e-c58041665ca3",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-320,
-144
],
"parameters": {
"color": 7,
"width": 432,
"height": 400,
"content": "## Incoming Support Email Trigger\nThis section listens for new customer messages sent to the support inbox. Whenever a new email arrives, the workflow automatically starts, ensuring no customer request is missed and every support inquiry enters the automation flow in real time."
},
"typeVersion": 1
},
{
"id": "dce28e0f-3cd2-4ce5-9ab4-99123d8a0a81",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
160,
-144
],
"parameters": {
"color": 7,
"width": 448,
"height": 400,
"content": "## Spam Detection & Early Filtering\nThis section checks the email subject, message content and sender domain to detect spam. Any suspicious or unwanted emails are stopped immediately, ensuring only genuine customer queries are processed and sent to Zendesk."
},
"typeVersion": 1
},
{
"id": "140ce5ba-548e-4445-a947-caa3f90c51cc",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
656,
-304
],
"parameters": {
"color": 7,
"width": 576,
"height": 560,
"content": "## Prepare Email Data & Check Existing Tickets\nThis section cleans and structures incoming email data by extracting customer details, message content and tags. It then retrieves existing Zendesk tickets to provide context, enabling accurate comparison and helping the workflow determine whether the incoming request is new or already recorded."
},
"typeVersion": 1
},
{
"id": "72c9bac5-55d5-4a3d-ae74-fbadc329a549",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1344,
-144
],
"parameters": {
"color": 7,
"width": 720,
"height": 384,
"content": "## Duplicate Detection & Validation\nIn this section, the incoming email is compared with existing Zendesk tickets. By checking normalized subjects and identifiers, the workflow determines whether the email represents a new issue or a duplicate, ensuring only valid new tickets move forward."
},
"typeVersion": 1
},
{
"id": "83d7aeb4-324c-4fef-afd8-89a0ba3e4cd2",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
2128,
-144
],
"parameters": {
"color": 7,
"width": 432,
"height": 384,
"content": "## Zendesk Ticket Creation\nThis final section creates a new support ticket in Zendesk using the cleaned and validated data. The ticket includes customer details, message content, priority, tags and external identifiers, ensuring the support team receives a complete and actionable request."
},
"typeVersion": 1
},
{
"id": "768133f1-3878-410d-afd9-72b310c06472",
"name": "Sticky Note5",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1056,
-704
],
"parameters": {
"width": 624,
"height": 720,
"content": "## How It Works\nThis workflow automatically converts customer support emails into structured Zendesk tickets while keeping the support system clean and organized. It starts when a new email arrives in the support inbox. The workflow first checks whether the email looks like spam and stops it early if it does.\n\nFor valid emails, the workflow extracts important details such as the customer\u2019s name, email address, subject, message content and email thread ID. Based on the message content, it also adds helpful tags like \u201crefund\u201d or \u201cdamaged\u201d to provide quick context for the support team.\n\nBefore creating a new ticket, the workflow checks existing Zendesk tickets to see if a similar request already exists. If a duplicate is detected, the workflow stops to avoid creating multiple tickets for the same issue. Only genuine, new support requests move forward and get created as Zendesk tickets with all required information.\n\n## Workflow Setup Steps\n\nAdd an Email or Gmail Trigger to listen for new messages in the support inbox.\n\nAdd a Spam Detection node to filter out unwanted or suspicious emails early.\n\nUse a Set node to extract and organize important email details like customer name, email, subject, message body and thread ID.\n\nAdd a Tagging node to automatically apply relevant tags based on the email content.\n\nFetch existing tickets from Zendesk to check for duplicates.\n\nMerge the email data with existing tickets and run a Duplicate Check.\n\nIf no duplicate is found, create a new ticket using the Zendesk Create Ticket node."
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "98efe619-8474-4cb6-93e6-c832172d73e4",
"connections": {
"Is This a New Ticket?": {
"main": [
[],
[
{
"node": "Create Zendesk Support Ticket",
"type": "main",
"index": 0
}
]
]
},
"New Support Email Trigger": {
"main": [
[
{
"node": "Spam Detection & Filtering",
"type": "main",
"index": 0
}
]
]
},
"Spam Detection & Filtering": {
"main": [
[
{
"node": "Extract & Normalize Email Data",
"type": "main",
"index": 0
}
]
]
},
"Extract & Normalize Email Data": {
"main": [
[
{
"node": "Auto-Tag Ticket Based on Email Content",
"type": "main",
"index": 0
},
{
"node": "Zendesk \u2013 Fetch Existing Tickets",
"type": "main",
"index": 0
}
]
]
},
"Merge Email With Existing Tickets": {
"main": [
[
{
"node": "Detect Duplicate Ticket by Subject",
"type": "main",
"index": 0
}
]
]
},
"Detect Duplicate Ticket by Subject": {
"main": [
[
{
"node": "Is This a New Ticket?",
"type": "main",
"index": 0
}
]
]
},
"Zendesk \u2013 Fetch Existing Tickets": {
"main": [
[
{
"node": "Merge Email With Existing Tickets",
"type": "main",
"index": 1
}
]
]
},
"Auto-Tag Ticket Based on Email Content": {
"main": [
[
{
"node": "Merge Email With Existing Tickets",
"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.
gmailOAuth2zendeskOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow automatically converts incoming support emails from Gmail into structured Zendesk tickets. It filters spam, extracts key customer details, auto-tags issues, prevents duplicate tickets and creates clean, actionable support tickets in Zendesk. Connect your Gmail…
Source: https://n8n.io/workflows/13280/ — 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.
Automatically convert Gmail emails and Slack messages into Zendesk support tickets with intelligent priority detection, comprehensive Google Sheets tracking, and real-time team notifications. Streamli
Turn incoming Gmail messages into Zendesk tickets and keep a synchronized log in Google Sheets. Uses Gmail as the trigger, creates Zendesk tickets, and appends or updates a central sheet for tracking.
2025-12-03 fix JS code in node
Receive any business document via email. The attachment is automatically classified (Invoice, Contract, or Purchase Order) using easybits Extractor, then routed down the correct path where a second Ex
The goal is to reduce inbox noise and automatically organize repetitive types of emails so that imprtant messages remain visible while unsolicited or promotional emails are handled automatically. When