feat: AI generates plain_text field, view full text shows readable version instead of HTML

This commit is contained in:
2026-07-14 14:37:12 +08:00
parent dd7fc61fd4
commit c3132f746a
3 changed files with 5 additions and 2 deletions

View File

@@ -16,6 +16,7 @@ SYSTEM_PROMPT = """你是一个邮件摘要助手。请分析邮件内容并以
"recipient": "收件邮箱地址", "recipient": "收件邮箱地址",
"sender": "发件人", "sender": "发件人",
"category": "normal/promotion/notification", "category": "normal/promotion/notification",
"plain_text": "邮件全文的纯文本版本去除HTML标签保留所有文字内容保持原始段落结构不删减不修改任何内容",
"summary": "50字以内的核心摘要", "summary": "50字以内的核心摘要",
"verification_code": "", "verification_code": "",
"app_name": "", "app_name": "",
@@ -35,6 +36,7 @@ SYSTEM_PROMPT = """你是一个邮件摘要助手。请分析邮件内容并以
- app_name: 仅当 category 为 "notification" 且邮件包含验证码时填写,填写发送验证码的应用/平台名称如「GitHub」「微信」「Kraken」。非验证码邮件留空字符串 - app_name: 仅当 category 为 "notification" 且邮件包含验证码时填写,填写发送验证码的应用/平台名称如「GitHub」「微信」「Kraken」。非验证码邮件留空字符串
- links: 仅提取以下两类链接1邮件明确要求用户点击才能完成某操作的链接如确认邮箱、重置密码、查看账单、审批请求、查看通知详情等2退订/取消订阅链接。不要提取推广性质的链接如下载App、注册领优惠、查看更多商品等营销链接、追踪像素、邮件签名中的社交链接。每条包含简短描述文字和完整 URL。最多 3 条。没有符合条件的链接时为空数组 - links: 仅提取以下两类链接1邮件明确要求用户点击才能完成某操作的链接如确认邮箱、重置密码、查看账单、审批请求、查看通知详情等2退订/取消订阅链接。不要提取推广性质的链接如下载App、注册领优惠、查看更多商品等营销链接、追踪像素、邮件签名中的社交链接。每条包含简短描述文字和完整 URL。最多 3 条。没有符合条件的链接时为空数组
- 退订链接提取规则推广邮件必须提取退订链接。退订链接通常在邮件最底部包含以下关键词之一unsubscribe、退订、取消订阅、opt out、manage preferences、email preferences。即使链接被包裹在 HTML 标签中,也要提取 href 属性里的完整 URL。如果邮件底部同时有多个退订相关链接只提取最主要的那个 - 退订链接提取规则推广邮件必须提取退订链接。退订链接通常在邮件最底部包含以下关键词之一unsubscribe、退订、取消订阅、opt out、manage preferences、email preferences。即使链接被包裹在 HTML 标签中,也要提取 href 属性里的完整 URL。如果邮件底部同时有多个退订相关链接只提取最主要的那个
- plain_text: 将邮件全文转换为可读的纯文本版本。去除所有HTML标签、CSS样式、脚本代码保留完整的文字内容和原始段落结构。不删减、不修改、不总结任何内容完整保留原文所有信息
- summary 要简洁,把需要知道的信息浓缩成一句话,不需要分条列出 - summary 要简洁,把需要知道的信息浓缩成一句话,不需要分条列出
- 当 category 为 "promotion"summary 直接写成一句话:「[发送方名称] 在推广 [推广的产品/服务/活动]」,例如「腾讯云在推广双十一云服务器折扣」。此时 can_reply 为 falsereply_suggestions 为空数组 - 当 category 为 "promotion"summary 直接写成一句话:「[发送方名称] 在推广 [推广的产品/服务/活动]」,例如「腾讯云在推广双十一云服务器折扣」。此时 can_reply 为 falsereply_suggestions 为空数组
- can_reply 为 false 表示无需回复或不适合建议回复(此时忽略 reply_suggestions - can_reply 为 false 表示无需回复或不适合建议回复(此时忽略 reply_suggestions

View File

@@ -68,7 +68,8 @@ def tg_send_and_mark(cfg: Config, info: dict):
_email_contexts[thinking_msg_id] = { _email_contexts[thinking_msg_id] = {
"summary_text": info["text"], "summary_text": info["text"],
"summary_data": info["data"], "summary_data": info["data"],
"original_body": info["original_body"][:10000], "original_body": info["original_body"],
"plain_text": info["data"].get("plain_text", ""),
"original_sender": info.get("original_sender", ""), "original_sender": info.get("original_sender", ""),
"original_recipient": info.get("original_recipient", ""), "original_recipient": info.get("original_recipient", ""),
"original_reply_to": info.get("original_reply_to", ""), "original_reply_to": info.get("original_reply_to", ""),

View File

@@ -276,7 +276,7 @@ def _handle_callback(tg_cfg: TelegramConfig, cfg: Config, cb: dict):
if action == CALLBACK_VIEW_ORIG and ctx: if action == CALLBACK_VIEW_ORIG and ctx:
can_reply = ctx.get("can_reply", True) can_reply = ctx.get("can_reply", True)
text = f"*📄 原文 \\- {_escape(ctx['subject'])}*\n\n{_escape(ctx['original_body'])}" text = f"*📄 原文 \\- {_escape(ctx['subject'])}*\n\n{_escape(ctx.get('plain_text', ctx['original_body']))}"
_tg_req(tg_cfg, "editMessageText", { _tg_req(tg_cfg, "editMessageText", {
"chat_id": chat_id, "message_id": msg_id, "chat_id": chat_id, "message_id": msg_id,
"text": text, "parse_mode": "MarkdownV2", "text": text, "parse_mode": "MarkdownV2",