8
n8n 中文网amn8n.com

每日申请人摘要

中级

这是一个AI Summarization, Multimodal AI领域的自动化工作流,包含 10 个节点。主要使用 Code, Gmail, ScheduleTrigger, ChainLlm, LmChatGoogleGemini 等节点。 使用Gemini AI提取的按职位分类每日申请人摘要,供招聘经理使用

前置要求
  • Google 账号和 Gmail API 凭证
  • Google Gemini API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "MGgeJBbeovHVQAbq",
  "meta": {
    "instanceId": "14e4c77104722ab186539dfea5182e419aecc83d85963fe13f6de862c875ebfa",
    "templateCredsSetupCompleted": true
  },
  "name": "每日申请人摘要",
  "tags": [],
  "nodes": [
    {
      "id": "75fe46c9-d9eb-455e-8f9d-7384c4a1d172",
      "name": "计划触发器",
      "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聊天模型",
      "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": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -520,
        -360
      ],
      "parameters": {
        "width": 1720,
        "height": 680,
        "content": "## 使用 Google Gemini 将按角色分类的每日申请人摘要从 Gmail 发送给招聘经理"
      },
      "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": "提取申请人详细信息",
      "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": "分配经理邮箱",
      "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": "分组并构建 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": "向经理发送摘要",
      "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": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -520,
        360
      ],
      "parameters": {
        "width": 1720,
        "height": 780,
        "content": "## 工作流概述:使用 Google Gemini 将按角色分类的每日申请人摘要从 Gmail 发送给招聘经理"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "67d27489-333a-4e73-8d9c-1af780d66304",
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "fetch_applicant_emails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Assign Manager Emails": {
      "main": [
        [
          {
            "node": "Group & Build HTML Tables",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fetch_applicant_emails": {
      "main": [
        [
          {
            "node": "Extract Applicant Details",
            "type": "main",
            "index": 0
          },
          {
            "node": "readAll_applicant_emails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Extract Applicant Details",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Extract Applicant Details": {
      "main": [
        [
          {
            "node": "Assign Manager Emails",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Group & Build HTML Tables": {
      "main": [
        [
          {
            "node": "Send Digest to Managers",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

中级 - AI 摘要总结, 多模态 AI

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
中级
节点数量10
分类2
节点类型6
难度说明

适合有一定经验的用户,包含 6-15 个节点的中等复杂度工作流

作者
WeblineIndia

WeblineIndia

@weblineindia

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

外部链接
在 n8n.io 查看

分享此工作流