{
  "id": "7pODvUSdP3WtnM5C",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Detect duplicate candidates by email/phone from Gmail to Slack using Google Sheets",
  "tags": [],
  "nodes": [
    {
      "id": "37e5642a-4a66-4f51-9747-fca065dc2899",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -260,
        -80
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "97acb6ce-48ce-4fd1-8cd9-d47be97871e5",
      "name": "Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -40,
        -80
      ],
      "parameters": {
        "filters": {
          "labelIds": [
            "Label_469123395284839348"
          ],
          "receivedAfter": "={{ $json.timestamp.toDateTime().minus(10,'min') }}"
        },
        "operation": "getAll"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "268e1fc2-a421-44f5-ba62-8a075ade25ca",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        180,
        -80
      ],
      "parameters": {
        "jsCode": "const email = $input.first().json;\n\nconst snippet = email.snippet || '';\nconst from = email.From || '';\n\n// Use regex to extract values from snippet\nconst nameMatch = snippet.match(/Name:\\s*(.+?)\\s*Email:/i);\nconst emailMatch = snippet.match(/Email:\\s*(\\S+)/i);\nconst phoneMatch = snippet.match(/Phone:\\s*(\\d{10,})/i);\nconst roleMatch = snippet.match(/Role:\\s*(.+?)\\s*Total Experience:/i);\nconst experienceMatch = snippet.match(/Total Experience:\\s*(\\d+)/i);\nconst recruiterMatch = snippet.match(/Recruiter:\\s*(.+?)\\s*Resume/i);\nconst resumeUrlMatch = snippet.match(/Resume URL:\\s*(.+?)(?:\\s|$)/i);\n\n// Extract sender email from From field\nconst fromEmailMatch = from.match(/<(.+?)>/);\nconst sourceEmail = fromEmailMatch ? fromEmailMatch[1] : from;\n\nreturn [\n  {\n    json: {\n      candidate_name: nameMatch?.[1]?.trim() || '',\n      candidate_email: emailMatch?.[1]?.trim() || '',\n      candidate_phone: phoneMatch?.[1]?.trim() || '',\n      role_applied: roleMatch?.[1]?.trim() || '',\n      years_of_experience: experienceMatch?.[1]?.trim() || '',\n      recruiter: recruiterMatch?.[1]?.trim() || '',\n      resume_url: resumeUrlMatch?.[1]?.trim() || '',\n      source_email: sourceEmail\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "6db8693c-bb2f-4d74-a7a7-dc13b135faa4",
      "name": "Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1060,
        20
      ],
      "parameters": {
        "columns": {
          "value": {
            "recruiter": "={{ $json.recruiter }}",
            "resume_url": "={{ $json.resume_url }}",
            "role_applied": "={{ $json.role_applied }}",
            "source_email": "={{ $json.source_email }}",
            "candidate_name": "={{ $json.candidate_name }}",
            "candidate_email": "={{ $json.candidate_email }}",
            "candidate_phone": "={{ $json.candidate_phone }}",
            "years_of_experience": "={{ $json.years_of_experience }}"
          },
          "schema": [
            {
              "id": "candidate_name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "candidate_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "candidate_email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "candidate_email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "candidate_phone",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "candidate_phone",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "role_applied",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "role_applied",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "years_of_experience",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "years_of_experience",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "role_applied",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "role_applied",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recruiter",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "recruiter",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "resume_url",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "resume_url",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "source_email",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "source_email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "candidate_email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1OrKgeY6j5AuaAeglrEU9PsehYkJlrK9hmUgh6_-x0EY",
          "cachedResultUrl": "",
          "cachedResultName": "Candidates"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "12002fc1-3c77-430f-b2e4-cfc6cb9c70b9",
      "name": "Google Sheets1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        400,
        -80
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1OrKgeY6j5AuaAeglrEU9PsehYkJlrK9hmUgh6_-x0EY",
          "cachedResultUrl": "",
          "cachedResultName": "Candidates"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "545d43a4-51e6-4966-a889-9cba847dd3c8",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        840,
        -80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "47596994-d10a-4a3b-b695-ff3cfc154374",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.isDuplicate }}",
              "rightValue": "={{ $json.candidate_email }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "9fa103e5-9d30-495b-9729-a7355cbdd518",
      "name": "Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        1060,
        -180
      ],
      "parameters": {
        "text": "=User  {{ $json.candidate_name }} has already applied for {{ $json.role_applied }}",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "select": "user",
        "otherOptions": {}
      },
      "typeVersion": 2.3
    },
    {
      "id": "d4ecbae6-c89f-4d03-a4fe-5d02e89f31d2",
      "name": "Code1",
      "type": "n8n-nodes-base.code",
      "onError": "continueRegularOutput",
      "position": [
        620,
        -80
      ],
      "parameters": {
        "jsCode": "const candidate =  $(\"Code\").all()[0].json;\nconst sheetRows = $('Google Sheets1').all();\n\nconst emailToCheck = candidate.candidate_email?.toLowerCase().trim();\n\n// Check if candidate_email already exists\nconst isDuplicate = sheetRows.some(row => {\n  return row.json.candidate_email?.toLowerCase().trim() === emailToCheck;\n});\n\nreturn [\n  {\n    json: {\n      ...candidate,\n      isDuplicate\n    }\n  }\n];\n"
      },
      "executeOnce": false,
      "retryOnFail": false,
      "typeVersion": 2
    },
    {
      "id": "c11aa74d-77ba-4711-b923-00c0dcd2ae96",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        -240
      ],
      "parameters": {
        "width": 1600,
        "height": 440,
        "content": "## Detect duplicate candidates by email/phone from Gmail to Slack using Google Sheets"
      },
      "typeVersion": 1
    },
    {
      "id": "cda5c54b-8456-4c6e-a127-d03f5d823c74",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        220
      ],
      "parameters": {
        "width": 1600,
        "height": 680,
        "content": "\n##  **Workflow: Detect Duplicate Candidates from Gmail \u2192 Google Sheets / Slack**\n\n###  Purpose:\n\nAutomatically process new job application emails to detect duplicates and act accordingly.\n\n###  **Core Logic (Key Points):**\n\n1. **Trigger the workflow** every few minutes to check for new applicant emails labeled `applicant`.\n\n2. **Fetch recent Gmail messages**, extract structured candidate information (name, email, phone, role, etc.).\n\n3. **Compare the extracted email** with existing entries in a Google Sheet.\n\n4. **If the candidate email already exists**:\n\n   *  Send a **Slack alert** that this user already applied.\n\n5. **If the candidate is new**:\n\n   *  Append their data into the **Google Sheet**.\n\n###  Outcome:\n\n* Prevents duplicate processing of candidate applications.\n* Ensures clean, deduplicated records in Google Sheets.\n* Notifies via Slack if someone reapplies.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "bb149ecc-e9cb-4d56-af0c-211a58939fce",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Slack",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Google Sheets1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets1": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}