{
  "id": "xeTX0nJdkctSWcIt",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Gmail AI Auto Reply with Duplicate Prevention",
  "tags": [],
  "nodes": [
    {
      "id": "893a885d-8c20-4a31-9a2e-06c844f69cdc",
      "name": "Config - Rules & Thresholds",
      "type": "n8n-nodes-base.set",
      "position": [
        208,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "646e1b67-c0be-4e37-a91a-ed5fdcb83994",
              "name": "ignoreListIncludes",
              "type": "string",
              "value": "unsubscribe|newsletter|no-reply|noreply|notification|do-not-reply|marketing|promo|promotion"
            },
            {
              "id": "374b7547-c972-4315-b1ad-5db8e60da712",
              "name": "ignoreSubjectIncludes",
              "type": "string",
              "value": "sale|discount|coupon|points|promotion|campaign|special offer|deal|new arrivals|update|digest|weekly|daily|newsletter"
            },
            {
              "id": "ee58befb-be0a-469b-81ee-47cb39682dc8",
              "name": "ignoreLabelsIncludes",
              "type": "string",
              "value": "CATEGORY_PROMOTIONS|CATEGORY_SOCIAL"
            },
            {
              "id": "8d1a5a95-b87b-4e17-90fe-ddd22abe6b89",
              "name": "importantReplyHistoryDays",
              "type": "number",
              "value": 365
            },
            {
              "id": "49a07c51-1840-43b9-b22b-8d3664781a9b",
              "name": "aiRunIfUncertain",
              "type": "boolean",
              "value": true
            },
            {
              "id": "2f09cb3b-e835-4a2b-9214-b9369b8a162f",
              "name": "urgentScoreThreshold",
              "type": "number",
              "value": 80
            },
            {
              "id": "a673ab59-3647-4379-82f9-94174a137da0",
              "name": "importantScoreThreshold",
              "type": "number",
              "value": 60
            },
            {
              "id": "cf509a5d-169e-4d6b-a32d-390372770e02",
              "name": "alertEmailTo",
              "type": "string",
              "value": "user@example.com"
            },
            {
              "id": "e85bd045-5951-4873-9fe2-f91515251bfb",
              "name": "alertEmailSubjectPrefix",
              "type": "string",
              "value": "[IMPORTANT INBOX]"
            },
            {
              "id": "1d21a25c-381a-4f82-a7b9-711b237264da",
              "name": "sheetName",
              "type": "string",
              "value": "inbox_audit_log"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "acabf18f-19f9-4040-a7fc-05221afdc25b",
      "name": "Gmail Trigger - New Emails",
      "type": "n8n-nodes-base.gmailTrigger",
      "position": [
        -32,
        0
      ],
      "parameters": {
        "filters": {},
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        }
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "0b4cc9ec-addd-4126-a80c-ecbe61e9415b",
      "name": "Normalize - Email Payload",
      "type": "n8n-nodes-base.set",
      "position": [
        416,
        0
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "2200c448-701b-404d-af7d-de5cc9da554c",
              "name": "Normalize - Email Payload",
              "type": "string",
              "value": "=={{ $json.id }}"
            },
            {
              "id": "56a0a6cb-0c79-4cf9-9ac5-56ad3bfe29be",
              "name": "from_raw",
              "type": "string",
              "value": "=={{ $json.from }}\n"
            },
            {
              "id": "f4277f7f-913f-40cd-985c-c653e6422e65",
              "name": "from_lower",
              "type": "string",
              "value": "=={{ ($json.from || '').toLowerCase() }}\n"
            },
            {
              "id": "ae4d8b6c-cda4-4b8f-8b54-7d6532e8cbc5",
              "name": "subject_raw",
              "type": "string",
              "value": "=={{ $json.subject }}\n"
            },
            {
              "id": "deb5f8b2-4344-45bb-9337-d78540c9f581",
              "name": "subject_lower",
              "type": "string",
              "value": "=={{ ($json.subject || '').toLowerCase() }}\n"
            },
            {
              "id": "49c18d22-ea3a-44e6-830c-406e7ae5b0ad",
              "name": "body_raw",
              "type": "string",
              "value": "=={{ $json.textPlain || $json.snippet || '' }}\n"
            },
            {
              "id": "73afe23f-1120-408e-bfa7-4252dda50193",
              "name": "body_lower",
              "type": "string",
              "value": "=={{ ($json.textPlain || $json.snippet || '').toLowerCase() }}\n"
            },
            {
              "id": "fca3b7f4-055d-414d-a876-96f3833eab78",
              "name": "labels",
              "type": "string",
              "value": "=={{ ($json.labelIds || []).join('|') }}\n"
            },
            {
              "id": "62b28045-2c9c-4322-999e-f6b7fae8f5ba",
              "name": "",
              "type": "string",
              "value": ""
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "42341e74-8229-46c6-b555-6116b9622d55",
      "name": "IF - Ignore Filter",
      "type": "n8n-nodes-base.if",
      "position": [
        704,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "aebf7615-593a-475f-ac8f-8ff3a0c3441f",
              "operator": {
                "type": "string",
                "operation": "regex"
              },
              "leftValue": "={{ $json.from_lower }}",
              "rightValue": "={{ \"(?:^|[^a-z0-9])(unsubscribe|newsletter|no-reply|noreply|notification|do-not-reply|marketing|promo|promotion)(?:[^a-z0-9]|$)\" }}\n"
            },
            {
              "id": "76487191-ceef-415a-982c-478f1aafb8d8",
              "operator": {
                "type": "string",
                "operation": "regex"
              },
              "leftValue": "={{ $json.subject_lower }}",
              "rightValue": "={{ \"(sale|discount|coupon|points|promotion|campaign|special\\\\s+offer|deal|new\\\\s+arrivals|update|digest|weekly|daily|newsletter)\" }}\n"
            },
            {
              "id": "eb67d60d-66c7-4b57-8ac9-e3fec08e6f56",
              "operator": {
                "type": "string",
                "operation": "regex"
              },
              "leftValue": "={{ $json.labels }}",
              "rightValue": "={{ \"(CATEGORY_PROMOTIONS|CATEGORY_SOCIAL)\" }}\n"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "c8d00799-0002-435d-8a85-fc9d9beed94c",
      "name": "Code - Extract Sender Email",
      "type": "n8n-nodes-base.code",
      "position": [
        1072,
        0
      ],
      "parameters": {
        "jsCode": "const fromRaw = $json.from_raw || $json.from || '';\nconst m = fromRaw.match(/<([^>]+)>/);\nconst email = (m ? m[1] : fromRaw).trim().toLowerCase();\n\nreturn [{\n  ...$json,\n  sender_email: email,\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "3aeda011-622c-43bd-9fbe-962c886c95a5",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1280,
        0
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.sender_email }}",
              "lookupColumn": "sender_email"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1KNCipEl77X5zbINaBPHhBDvWBdr3yE3C8-H-sPvx6N4/edit#gid=0",
          "cachedResultName": "\u30b7\u30fc\u30c81"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1KNCipEl77X5zbINaBPHhBDvWBdr3yE3C8-H-sPvx6N4",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1KNCipEl77X5zbINaBPHhBDvWBdr3yE3C8-H-sPvx6N4/edit?usp=drivesdk",
          "cachedResultName": "reply_history"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d6280885-198d-4a07-af2d-bc5052c5749e",
      "name": "IF - Found in Reply History?",
      "type": "n8n-nodes-base.if",
      "position": [
        1504,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "384a7902-1045-4752-9935-19bc3f047bf4",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $input.all().length > 0 }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "ae24178d-8250-4e58-a8e4-7c5373575ddd",
      "name": "Gmail - Search Sent to Sender",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1776,
        0
      ],
      "parameters": {
        "limit": 20,
        "filters": {
          "q": "={{ \"in:sent to:\" + $json.sender_email + \" newer_than:\" + $json.importantReplyHistoryDays + \"d\" }}"
        },
        "operation": "getAll"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a34766da-013a-44b8-b451-13c167b0208a",
      "name": "IF - Sent history exists?",
      "type": "n8n-nodes-base.if",
      "position": [
        1984,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "83a8a44a-ca7a-42e4-ae9a-5ce47bfc51ad",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $items().length > 0 }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "206ef0f7-568b-4de5-b3ba-f534d0ac89f7",
      "name": "Reply to a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2592,
        0
      ],
      "parameters": {
        "message": "={{$json.text}}",
        "options": {},
        "emailType": "text",
        "messageId": "={{$json.id}}",
        "operation": "reply"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "026d4ffd-62b8-404b-bc74-49c4bb8629c1",
      "name": "Message a model",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        2272,
        0
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "GPT-4O-MINI"
        },
        "options": {},
        "responses": {
          "values": [
            {
              "content": "=Write a polite and natural English email reply to the following message.\n\nRules:\n- Do not guess missing information.\n- Be clear and concise.\n- Sound human, not automated.\n- Under 120 words.\n- End with one clear next action.\n\nSubject:\n{{$json.subject}}\n\nEmail body:\n{{$json.text || $json.snippet}}\n"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "9e2685f7-3bc9-4101-ac77-1cee9a52e6bf",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        -320
      ],
      "parameters": {
        "color": 4,
        "width": 528,
        "content": "## Overview \u2013 Workflow Purpose\nThis workflow automatically replies to important incoming Gmail messages.\nIt avoids duplicate replies by checking both a Google Sheet reply history\nand recent sent emails in Gmail before responding.\nOnly emails that pass all filters receive an AI-generated English reply.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "e761d851-fb8a-4f0a-a824-7aff61ffa6b7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 320,
        "content": "## Step 1 \u2013 Email Intake & Normalization\nReceive new Gmail emails, load global rules and thresholds,\nand normalize email data into a consistent structure\nfor stable downstream processing.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9aa34137-388d-4534-9ce7-1b64ac058be1",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        576,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 320,
        "content": "## Step 2 \u2013 Ignore Unwanted Emails\nFilter out newsletters, promotions, and irrelevant emails.\nMessages that match ignore rules are stopped immediately."
      },
      "typeVersion": 1
    },
    {
      "id": "5b8def90-a228-4cb4-9880-2bef56e1848b",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        992,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 688,
        "height": 320,
        "content": "## Step 3 \u2013 Reply History Check (Google Sheet)\nExtract the sender\u2019s email address and check\nwhether it already exists in the Google Sheet reply history.\nIf found, no reply is sent."
      },
      "typeVersion": 1
    },
    {
      "id": "c2c19b15-0ed4-46e9-b096-ca2337f36de9",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1696,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 496,
        "height": 320,
        "content": "## Step 4 \u2013 Recent Sent Email Check (Gmail)\nSearch Gmail for recently sent messages to the same sender.\nIf a recent reply exists within the defined time window,\nthe workflow stops to prevent duplicate replies."
      },
      "typeVersion": 1
    },
    {
      "id": "84b668cb-d1cf-47f7-8a25-92bf5fe39024",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2208,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 320,
        "content": "## Step 5 \u2013 AI Reply Generation & Sending\nGenerate a clear English reply using AI\nand send it as a reply to the original Gmail message.\nThis step runs only when no duplicate reply is detected."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "9a4b856f-b905-42de-b159-86ea65d504b6",
  "connections": {
    "Message a model": {
      "main": [
        [
          {
            "node": "Reply to a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Ignore Filter": {
      "main": [
        [],
        [
          {
            "node": "Code - Extract Sender Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get row(s) in sheet": {
      "main": [
        [
          {
            "node": "IF - Found in Reply History?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Sent history exists?": {
      "main": [
        [],
        [
          {
            "node": "Message a model",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize - Email Payload": {
      "main": [
        [
          {
            "node": "IF - Ignore Filter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail Trigger - New Emails": {
      "main": [
        [
          {
            "node": "Config - Rules & Thresholds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Extract Sender Email": {
      "main": [
        [
          {
            "node": "Get row(s) in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Config - Rules & Thresholds": {
      "main": [
        [
          {
            "node": "Normalize - Email Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Found in Reply History?": {
      "main": [
        [],
        [
          {
            "node": "Gmail - Search Sent to Sender",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail - Search Sent to Sender": {
      "main": [
        [
          {
            "node": "IF - Sent history exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}