利用 LLM 自动分类Gmail邮件汇总
作者:matrix 被围观: 10 次 发布时间:2025-04-30 分类:零零星星 | 无评论 »
我邮箱订阅了很多博客或者 dev 相关的通知,偶尔看看的话还是有很多未读导致邮件堆积。但又不想退订 🙄 咋整
有邮件汇总服务就完美了,能自动分类和汇总, 标记已读和label。
zapier
zapier
的自动化工作流配置可以达到效果,类似当年的 IFTTT
, 现在他们都主要针对付费用户提供服务
我是等最后配置好了才发现使用的组件服务需要收费 😆 换其他
Google Apps script
https://script.google.com
Google的服务有很多,Apps script针对Google内部的各种服务集成的不错。
Apps script可以编写自定义脚本完成我需要的功能,语法是JavaScript。
新建项目
main.gs
// LLM配置
const OPENAI_API_URL = "https://openrouter.ai/api/v1/chat/completions"; // 使用 OpenRouter API URL
const OPENAI_API_KEY = "sk-XXXXXXXXXXXX"; // API 密钥
const OPENAI_MODEL = "openai/gpt-4o-mini" //使用模型 准确率来说gpt-4o不错,deepseek v3也可以
// 汇总任务配置
const TASK_NAME = "daily.dev" //任务名称 作为汇总邮件标题的一部分
const QUERY = "informer@daily.dev is:unread" //邮件查询条件(Gmail搜索框中的查询文本)is:unread 表示查询未读邮件
const LABEL_NAME = "[script.google]AI汇总" //汇总的分类名
const MAX_EMAILS_PER_BATCH = 5; // 每次最多汇总邮件数 5
const MAX_EMAILS_BATCH = 10; // 本次任务最多处理邮件数 10
const TIME_ZONE = "GMT+8"
// 查询未读邮件并处理
function main() {
try {
let threads = GmailApp.search(QUERY); // 查询未读邮件
if (threads.length === 0) {
Logger.log("没有未读邮件。");
return;
}
threads = threads.slice(0, MAX_EMAILS_BATCH);
//限制汇总邮件数
chunkArray(threads,MAX_EMAILS_PER_BATCH).forEach(limitedThreads => {
// 2. 获取邮件内容
let emailContents = [];
limitedThreads.forEach(thread => {
const messages = thread.getMessages();
messages.forEach(message => {
const subject = message.getSubject();
const body = message.getPlainBody();
const messageId = message.getId(); // 获取邮件的唯一 ID
const threadId = message.getThread().getId(); // 获取邮件线程的 ID
const emailLink = `https://mail.google.com/mail/u/0/#all/${threadId}`;
emailContents.push(`<email><title>${subject}</title><content>${body}</content><link>${emailLink}</link></email>`);
});
});
// 3. 调用 OpenRouter 的 AI 接口
const aiResponse = callOpenAiAPI(emailContents.join("\n\n"));
// 4. 发送汇总邮件
let matches = aiResponse.match(/<content>([\s\S]+)<\/content>/);
if(!matches || matches.length < 1){
Logger.log("无内容: " + matches);
return ;
}
sendSummaryEmail(matches[1]);
// 5. 标记邮件为特定分类(标签)
limitedThreads.forEach(thread => {
// 获取或创建标签
const labelName = LABEL_NAME; // 替换为你想要的标签名称
let label = GmailApp.getUserLabelByName(labelName);
if (!label) {
label = GmailApp.createLabel(labelName); // 如果标签不存在,则创建
}
// 将标签应用到邮件线程
label.addToThread(thread);
thread.markRead();//标记已读
});
})
} catch (error) {
Logger.log("发生错误: " + error.message);
}
}
function chunkArray(array, size) {
const result = [];
for (let i = 0; i < array.length; i += size) {
result.push(array.slice(i, i + size));
}
return result;
}
// 调用 OpenRouter API
function callOpenAiAPI(content) {
const prompts = `{邮件内容}是邮件提取工具生成的多封邮件的混合文本,你需要将其整理汇总为指定格式的HTML代码 参考{输出格式}。
## 规则
- 提取每封邮件的所有关键信息和链接
- 去除多余的广告或者软件下载链接等干扰
- 链接 必定存在, 如果链接没有合适匹配,则使用邮件链接
- 标题 必定存在,英文标题翻译为中文
{输出格式}:
\`\`\`
<content>
<p><a href="{链接}">1. {标题}</a></p>
<p><a href="{链接}">2. {标题}</a></p>
...
</content>
\`\`\`
{邮件内容}:
\`\`\`
${content}
\`\`\`
`;
const payload = {
model: OPENAI_MODEL,
prompt: prompts,
// max_tokens: 500
};
console.log(prompts);
const options = {
method: "POST",
contentType: "application/json",
headers: {
Authorization: `Bearer ${OPENAI_API_KEY}`
},
payload: JSON.stringify(payload)
};
const response = UrlFetchApp.fetch(OPENAI_API_URL, options);
console.log(response.getContentText());
const json = JSON.parse(response.getContentText());
return json.choices[0].text.trim(); // 根据 api 的返回格式调整
}
function getActiveUserEmail() {
var email = Session.getActiveUser().getEmail();
Logger.log("Active User Email: " + email);
return email;
}
// 发送汇总邮件
function sendSummaryEmail(summary) {
const recipient = getActiveUserEmail();
const today = new Date();
const yesterdayDate = new Date();
yesterdayDate.setDate(today.getDate() - 1); // 设置为前一天日期
const formattedDate = Utilities.formatDate(yesterdayDate, TIME_ZONE, "yyyy-MM-dd"); // 格式化日期
// 设置邮件主题,包含查询关键字和当前日期
const subject = `[${TASK_NAME}]邮件汇总 - ${formattedDate}`;
const body = `${summary}`;
GmailApp.sendEmail(recipient,subject,body,{htmlBody: body});
}
说明:
我使用的 OpenRouter 服务,你完全可以更换为国内任何 ai 服务商
代码顶部配置项OPENAI_API_URL
,OPENAI_API_KEY
,OPENAI_MODEL
表示大模型服务商信息
QUERY
配置邮件搜索条件,也就是 Gmail 输入框的文本
LABEL_NAME
标记已读后需要移动到的分类名
测试运行
第一次运行会有 Google 应用的授权提示,允许即可。因为是自部署应用所以不会授权给外部。
点击顶部的运行
或者调试
来测试,必须确保执行入口方法为 main
最后发送的汇总邮件样式很简单 可以自己调整。
定时执行
找到左侧菜单中「触发器」,添加每天执行的定时规则
配置完成,每天凌晨30分左右 Google 会自动发送汇总邮件,并且把已经处理的邮件标记已读。
参考:
https://developers.google.com/apps-script/reference/Gmail/gmail-app?hl=zh-cn#createdraftrecipient,-subject,-body