Résumé quotidien des candidats

Intermédiaire

Ceci est unAI Summarization, Multimodal AIworkflow d'automatisation du domainecontenant 10 nœuds.Utilise principalement des nœuds comme Code, Gmail, ScheduleTrigger, ChainLlm, LmChatGoogleGemini. Résumé quotidien des candidats par poste, extrait avec l'IA Gemini pour les recruteurs

Prérequis
  • Compte Google et informations d'identification Gmail API
  • Clé API Google Gemini
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "id": "MGgeJBbeovHVQAbq",
  "meta": {
    "instanceId": "14e4c77104722ab186539dfea5182e419aecc83d85963fe13f6de862c875ebfa",
    "templateCredsSetupCompleted": true
  },
  "name": "Daily-Applicant-Digest",
  "tags": [],
  "nodes": [
    {
      "id": "75fe46c9-d9eb-455e-8f9d-7384c4a1d172",
      "name": "Déclencheur Planifié",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -340,
        -80
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 6
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "ba41cb19-9463-4c8a-a94d-a7d579346b1e",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        120,
        120
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-1.5-flash"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "VbpO5dd6r2AhD52y",
          "name": "Google Gemini(PaLM) Api account 2"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9e2ef974-5183-4e7d-9cd2-8f3872bd0a66",
      "name": "Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -520,
        -360
      ],
      "parameters": {
        "width": 1720,
        "height": 680,
        "content": "## Send daily applicant digest by role from Gmail to hiring managers with Google Gemini"
      },
      "typeVersion": 1
    },
    {
      "id": "4648ef51-49af-40f8-9c82-490c5965e5be",
      "name": "fetch_applicant_emails",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -120,
        -80
      ],
      "webhookId": "342f1447-19e1-4639-ae6e-a39fc1131b7c",
      "parameters": {
        "filters": {
          "q": "label: applicant newer_than:1d is:unread"
        },
        "operation": "getAll"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "Kb30iigFce7pjkMZ",
          "name": "Gmail account 5"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "f479ae8a-490b-4b08-9fe3-dbe6a26b2320",
      "name": "readAll_applicant_emails",
      "type": "n8n-nodes-base.gmail",
      "position": [
        120,
        -280
      ],
      "webhookId": "801858f2-9076-47a1-88eb-c8c1c930102d",
      "parameters": {
        "messageId": "={{ $json.id }}",
        "operation": "markAsRead"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "Kb30iigFce7pjkMZ",
          "name": "Gmail account 5"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "2a8e9656-df75-439f-ac16-ba608b29c87d",
      "name": "Extraire les Détails des Candidats",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        100,
        -80
      ],
      "parameters": {
        "text": "=You are an assistant that extracts job applicant information from emails.\n\nExtract the following fields and return ONLY valid JSON with these keys:\n- name\n- email\n- phone\n- role\n- years_of_experience\n- top_skills\n- location\n- notice_period\n- summary\n\nApplicant email:\n\"\"\"\n{{$json.snippet }}\n\"\"\"\n",
        "batching": {},
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "3937cc5c-ea58-4b5d-b22d-591f8097481f",
      "name": "Assigner les Emails des Responsables",
      "type": "n8n-nodes-base.code",
      "position": [
        480,
        -80
      ],
      "parameters": {
        "jsCode": "function stripMarkdownJson(input) {\n  let str = (input || '').trim();\n\n  // Remove the ```json at the start and ```\n  // This regex removes triple backticks and the 'json' keyword at the start\n  str = str.replace(/^```json\\s*/, '');  // Remove starting ```\n  str = str.replace(/```$/, '');          // Remove ending ```\n  \n  return str.trim();\n}\n\nfunction normalizeRole(role) {\n  return (role || '').trim().toLowerCase();\n}\n\nconst roleToManagerEmail = {\n  'java team lead': 'javatl@mailinator.com',\n  'python developer': 'pythontl@mailinator.com',\n  'frontend developer': 'frontendtl@mailinator.com',\n  // add other roles as needed\n};\n\nconst fallbackManagerEmail = 'fallback@mailinator.com';\n\nreturn items.map(item => {\n  const raw = item.json.text || '';\n  const jsonStr = stripMarkdownJson(raw);\n\n  let parsed;\n  try {\n    parsed = JSON.parse(jsonStr);\n  } catch (e) {\n    item.json.error = `JSON parse failed: ${e.message}`;\n    return item;\n  }\n\n  // Merge the parsed JSON fields into the current item\n  Object.assign(item.json, parsed);\n\n  // Normalize role and assign manager email\n  const normalizedRole = normalizeRole(item.json.role);\n  const managerEmail = Object.prototype.hasOwnProperty.call(roleToManagerEmail, normalizedRole)\n    ? roleToManagerEmail[normalizedRole]\n    : fallbackManagerEmail;\n\n  item.json.managerEmail = managerEmail;\n\n  return item;\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5943f68f-a39f-4532-a437-732d98d53079",
      "name": "Grouper et Construire les Tableaux HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        700,
        -80
      ],
      "parameters": {
        "jsCode": "function escapeHtml(text) {\n  if (!text) return '';\n  return text\n    .replace(/&/g, \"&amp;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\")\n    .replace(/\"/g, \"&quot;\")\n    .replace(/'/g, \"&#039;\");\n}\n\n// Group applicants by managerEmail, then by role\nconst groupedByManager = {};\n\n// Step 1: Group items\nitems.forEach(item => {\n  const applicant = item.json;\n  const managerEmail = applicant.managerEmail || 'unknown@fallback.com';\n  const role = applicant.role || 'Unknown Role';\n\n  if (!groupedByManager[managerEmail]) {\n    groupedByManager[managerEmail] = {};\n  }\n  if (!groupedByManager[managerEmail][role]) {\n    groupedByManager[managerEmail][role] = [];\n  }\n  \n  groupedByManager[managerEmail][role].push(applicant);\n});\n\n// Step 2: Build HTML per manager with tables per role\nconst output = [];\n\nfor (const [managerEmail, roles] of Object.entries(groupedByManager)) {\n\n  let emailHtml = `<h2>Today's New Applicants</h2>`;\n\n  for (const [role, applicants] of Object.entries(roles)) {\n    emailHtml += `<h3>Role: ${escapeHtml(role)}</h3>`;\n    \n    // Build table header\n    emailHtml += `\n    <table border=\"1\" cellpadding=\"5\" cellspacing=\"0\" style=\"border-collapse:collapse; width: 100%;\">\n      <thead style=\"background-color:#f0f0f0;\">\n        <tr>\n          <th>Name</th>\n          <th>Email</th>\n          <th>Phone</th>\n          <th>Years of Experience</th>\n          <th>Top Skills</th>\n          <th>Location</th>\n          <th>Notice Period</th>\n          <th>Summary</th>\n        </tr>\n      </thead>\n      <tbody>\n    `;\n\n    // Add each applicant as a row\n    applicants.forEach(app => {\n      emailHtml += `\n        <tr>\n          <td>${escapeHtml(app.name)}</td>\n          <td><a href=\"mailto:${escapeHtml(app.email)}\">${escapeHtml(app.email)}</a></td>\n          <td>${escapeHtml(app.phone)}</td>\n          <td>${escapeHtml(app.years_of_experience?.toString())}</td>\n          <td>${Array.isArray(app.top_skills) ? escapeHtml(app.top_skills.join(', ')) : escapeHtml(app.top_skills)}</td>\n          <td>${escapeHtml(app.location)}</td>\n          <td>${escapeHtml(app.notice_period)}</td>\n          <td>${escapeHtml(app.summary)}</td>\n        </tr>\n      `;\n    });\n\n    emailHtml += `</tbody></table><br/>`;\n  }\n\n  // Push one item per manager, as output for the next step (email sending)\n  output.push({\n    json: {\n      managerEmail,\n      html: emailHtml\n    }\n  });\n}\n\nreturn output;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "9509d5c2-f66f-4294-9432-0b2587283b7a",
      "name": "Envoyer le Résumé aux Responsables",
      "type": "n8n-nodes-base.gmail",
      "position": [
        900,
        -80
      ],
      "webhookId": "7fe812db-f512-4e0d-b4e5-f577fad2511c",
      "parameters": {
        "sendTo": "={{ $json.managerEmail }}",
        "message": "={{ $json.html }}",
        "options": {},
        "subject": "=Today's Applicants Digest – {{ $now.format('MM-DD') }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "Kb30iigFce7pjkMZ",
          "name": "Gmail account 5"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "17486203-2374-43f0-88eb-80500108d770",
      "name": "Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -520,
        360
      ],
      "parameters": {
        "width": 1720,
        "height": 780,
        "content": "## Workflow Overview: Send daily applicant digest by role from Gmail to hiring managers with Google Gemini\n\n**Purpose:**\nAutomatically fetches new job application emails labeled applicants, extracts structured applicant details using OpenAI, groups candidates by role and manager, then sends a daily HTML summary email to each hiring manager.\n\nDaily Applicant Digest Workflow – Node Overview\n\n**1. Daily Trigger (6PM IST)**\n\nStarts the workflow every day at 18:00 (Asia/Kolkata timezone).\n\n**2. Fetch Applicant Emails**\n\nRetrieves all new application emails labeled applicants from the last 24 hours.\n\n**3. Read All Emails**\n\nRead each email’s labeled applicants which we retrieves\n\n**4. Extract Applicant Details**\n\nUses OpenAI to extract and structure applicant info (name, email, role, skills, etc.) in JSON format.\n\n**5. Assign Manager Emails**\n\nMaps each applicant’s role to a hiring manager’s email address.\n\nUses a fallback email if the role does not match any manager.\n\n**6. Group & Build HTML Tables**\n\nGroups applicants by manager and role.\n\nBuilds a clear, formatted HTML table for each group, summarizing all applicants.\n\n**7. Send Digest to Managers**\n\nSends one HTML summary email per manager, listing all relevant new applicants for the day.\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "67d27489-333a-4e73-8d9c-1af780d66304",
  "connections": {
    "75fe46c9-d9eb-455e-8f9d-7384c4a1d172": {
      "main": [
        [
          {
            "node": "4648ef51-49af-40f8-9c82-490c5965e5be",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3937cc5c-ea58-4b5d-b22d-591f8097481f": {
      "main": [
        [
          {
            "node": "5943f68f-a39f-4532-a437-732d98d53079",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4648ef51-49af-40f8-9c82-490c5965e5be": {
      "main": [
        [
          {
            "node": "2a8e9656-df75-439f-ac16-ba608b29c87d",
            "type": "main",
            "index": 0
          },
          {
            "node": "f479ae8a-490b-4b08-9fe3-dbe6a26b2320",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ba41cb19-9463-4c8a-a94d-a7d579346b1e": {
      "ai_languageModel": [
        [
          {
            "node": "2a8e9656-df75-439f-ac16-ba608b29c87d",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "2a8e9656-df75-439f-ac16-ba608b29c87d": {
      "main": [
        [
          {
            "node": "3937cc5c-ea58-4b5d-b22d-591f8097481f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5943f68f-a39f-4532-a437-732d98d53079": {
      "main": [
        [
          {
            "node": "9509d5c2-f66f-4294-9432-0b2587283b7a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Intermédiaire - Résumé IA, IA Multimodale

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Intermédiaire
Nombre de nœuds10
Catégorie2
Types de nœuds6
Description de la difficulté

Adapté aux utilisateurs expérimentés, avec des workflows de complexité moyenne contenant 6-15 nœuds

Auteur
WeblineIndia

WeblineIndia

@weblineindia

A Leading Software Engineering, Consulting & Outsourcing Services Company in USA & India serving Clients Globally since 1999.

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34