通用型邮件处理流水线 Skill — "路由 → 精确时间窗 → 归一化匹配 → 结构化提取 → 推送 → 定时"六位一体:
provider="qq" / "gmail" / "outlook" …… 一个参数搞定 host/port,告别手抄地址。start_datetime / end_datetime 下沉到代码,数学比对不漏件、不越界。【SEO順位チェック_夜間バッチ処理】 无视后续空白全文稳命中。extracted_data。setup_cron.sh 幂等注册。text
imap-mail-pipeline/
├── _meta.json
├── main.py # 调度入口
├── reader.py # 路由/时间窗/归一化匹配/正则提取
├── pusher.py # 钉钉/飞书/Telegram 推送
├── setup_cron.sh # crontab 一键注册
└── skill.md # 本文档
参数类型必填默认说明email_accountstring✅—邮箱完整账号auth_passwordstring✅—客户端授权码(敏感)**providerstring选填""内置路由快捷方式,见下表imap_hoststring选填""provider 未填时使用imap_portinteger选填993端口start_datetime**string选填end - 24h开始时间 YYYY-MM-DD HH:MM:SS****end_datetimestring选填当前时间结束时间 YYYY-MM-DD HH:MM:SSsubject_keywordsstring选填""主题关键字,英文逗号分隔body_keywordsstring选填""正文关键字,英文逗号分隔match_logicstring选填AND``AND / OR(组内逻辑)extract_patternsobject选填{}正则字段提取preview_lengthinteger选填500正文预览长度push_platformstring选填""``dingtalk / feishu / tg``webhook_urlstring选填""推送 Webhookpush_secretstring选填""加签密钥 或 TG chat_id
⚠️ 时间控制使用
start_datetime/end_datetime精确参数,不再使用早期设计中的time_window_hours。
providerHostPortaliyun **(默认兜底)**imap.qiye.aliyun.com993aliyun_mailimap.aliyun.com993qqimap.qq.com993exmail / tencentimap.exmail.qq.com993163imap.163.com993126imap.126.com993yeahimap.yeah.net993sinaimap.sina.com993sohuimap.sohu.com993139imap.139.com993gmailimap.gmail.com993outlook / hotmail / office365outlook.office365.com993yahooimap.mail.yahoo.com993icloudimap.mail.me.com993fastmailimap.fastmail.com993zohoimap.zoho.com993protonmail127.0.0.11143(需本地 Bridge)
text
provider(命中内置表) > imap_host/imap_port(自定义) > 默认 aliyun
YYYY-MM-DD HH:MM:SSYYYY-MM-DD(当 00:00:00 处理)、 YYYY-MM-DDTHH:MM:SS、带时区的 ISO 8601(如 2026-04-21T23:00:00+08:00)start_datetime 的 本地日期 调用 IMAP SEARCH SINCE(粗筛,保守扩大)Date 头为 aware datetimestart_datetime ≤ 邮件真实时间 ≤ end_datetimejson
// 最近 24 小时(什么都不填)
{}
// 指定绝对时间窗(跨日)
{"start_datetime": "2026-04-20 23:00:00", "end_datetime": "2026-04-21 10:00:00"}
// 带时区
{"start_datetime": "2026-04-20T23:00:00+09:00"}
匹配前对 目标文本 和 用户关键字 同时执行归一化,清除:
类别字符基础空白半角空格 / \t / \n / \r / \f / \vUnicode 空白\u00A0(NBSP) / \u3000(全角空格)/ \u2028 / \u2029 等零宽字符\u200B ~ \u200F、 \u2060、 \uFEFF(BOM/ZWNBSP)双向控制符\u202A ~ \u202E(LRE/RLE/PDF/LRO/RLO)
【SEO順位チェック_夜間バッチ処理】【SEO順位チェック_夜間バッチ処理】 正常終了(中间有全角空格)【seo順位チェック_夜間バッチ処理】【seo順位チェック_夜間バッチ処理】正常終了in 判定 → ✅ 100% 命中同理适用于正文中的换行、零宽字符干扰。
bash
echo '{
"email_account": "user@example.com",
"auth_password": "YOUR_AUTH_CODE",
"provider": "qq",
"subject_keywords": "【SEO順位チェック_夜間バッチ処理】"
}' | python3 main.py
bash
echo '{
"email_account": "user@example.com",
"auth_password": "YOUR_AUTH_CODE",
"provider": "outlook",
"start_datetime": "2026-04-20 23:00:00",
"end_datetime": "2026-04-21 10:00:00",
"subject_keywords":"並行,SEO",
"match_logic": "OR",
"extract_patterns": {
"parallel_id": "【並行(\\d+)番目】",
"machine": "(本番\\d+号機)",
"status": "(成功|失敗|完了|エラー)"
}
}' | python3 main.py
json
{
"imap_host": "mail.corporate.internal",
"imap_port": 993,
"email_account": "user@corporate.internal",
"auth_password": "xxx"
}
平台push_platform``webhook_url``push_secret钉钉dingtalk群机器人 Webhook加签密钥( SEC...,可选)飞书feishu群机器人 Webhook签名密钥(可选)Telegramtg``https://api.telegram.org/bot<TOKEN>/sendMessage目标 chat_id
推送的 Markdown 消息会携带 extracted_data 字段,群里一眼可见关键信息。
bash
chmod +x setup_cron.sh
export SKILL_EMAIL_ACCOUNT=user@example.com
export SKILL_AUTH_PASSWORD=YOUR_AUTH_CODE
export SKILL_PROVIDER=qq
export SKILL_SUBJECT_KEYWORDS="【SEO順位チェック_夜間バッチ処理】"
export SKILL_EXTRACT_PATTERNS='{"status":"(成功|失敗|完了)"}'
export SKILL_PUSH_PLATFORM=dingtalk
export SKILL_WEBHOOK_URL="https://oapi.dingtalk.com/robot/send?access_token=xxx"
export SKILL_PUSH_SECRET="SECxxxxxxxx"
# 每天 09:00 自动跑;时间窗留空即为过去 24h(滑动窗口,适合定时场景)
./setup_cron.sh "0 9 * * *" /var/log/mail-pipeline.log
💡 为什么定时任务要留空时间窗参数? 留空时默认为"当前时间 - 24h"到"当前时间",每次 cron 触发都是 滚动窗口,天然适配定时任务。固定的
start_datetime反而会让每次都查同一段历史,不是你想要的。
json
{
"success": true,
"server": "imap.qq.com:993",
"window": {
"from": "2026-04-20 23:00:00 +0800",
"to": "2026-04-21 10:00:00 +0800",
"tz": "CST"
},
"filter": "时间窗[2026-04-20 23:00:00 +0800 ~ 2026-04-21 10:00:00 +0800] AND 主题[OR:並行,SEO] AND 提取[parallel_id,machine,status]",
"count": 2,
"emails": [
{
"uid": "10311",
"from": "batch@example.com",
"timestamp": "2026-04-21T09:32:15+08:00",
"timestamp_local": "2026-04-21 09:32:15 +0800",
"subject": "【並行2番目】SEO 日次バッチ 完了通知",
"extracted_data": {
"parallel_id": "2",
"machine": "本番1号機",
"status": "完了"
},
"preview": "本番1号機にて 並行2番目 の SEO バッチが 09:31 に正常に完了しました……"
},
{
"uid": "10308",
"from": "batch@example.com",
"timestamp": "2026-04-20T23:15:02+08:00",
"timestamp_local": "2026-04-20 23:15:02 +0800",
"subject": "【並行1番目】SEO 跑批 失敗通知",
"extracted_data": {
"parallel_id": "1",
"machine": "本番2号機",
"status": "失敗"
},
"preview": "本番2号機の 並行1番目 で例外が発生しました……"
}
]
}
Skill 保持通用,所有业务语义都在 Prompt 里表达:
text
你是批处理作业监控助手。请调用 imap-mail-pipeline 完成汇总: 【调用参数】 { "email_account": "<用户邮箱>", "auth_password": "<授权码>", "provider": "qq", "start_datetime": "2026-04-20 23:00:00", "end_datetime": "2026-04-21 10:00:00", "subject_keywords":"【SEO順位チェック_夜間バッチ処理】", "extract_patterns": { "parallel_id": "【並行(\\d+)番目】", "machine": "(本番\\d+号機)", "status": "(成功|失敗|完了|エラー|異常)" } } 【分析步骤】 1. 读取每封邮件的 extracted_data。 2. 以 (machine, parallel_id) 为复合主键聚合,按 timestamp 取最新状态。 3. 构建矩阵:行=機器、列=並行号、单元格=最新 status。 4. 高亮异常:status ∈ {失敗, エラー, 異常} 用 ⚠️;成功/完了 用 ✅。 5. 时间窗内未出现的 (machine, parallel_id) 标 "—"。 【输出格式】 - Markdown 表格 - 下方列出异常项目的主题 + timestamp_local,便于快速定位
痛点本 Skill 方案跨日时间边界start_datetime / end_datetime 数学比对,零漏件邮件标题里混入全角空格归一化后 in 必中手抄 host 容易错provider: "qq" 一键路由日文/正则转义复杂extract_patterns 代码层编译,Skill 吐结构化字段业务换场景要改代码换 Prompt / 换 extract_patterns 即可,Skill 零改动
字段类型说明successboolean是否成功serverstring实际使用的 host:port``window.from / window.tostring生效的时间窗(带时区)window.tzstring服务器本地时区filterstring生效过滤条件的人类可读描述countinteger命中邮件数emails[].uidstringIMAP 邮件 UIDemails[].fromstring发件人(解码后)emails[].timestampstring (ISO 8601)邮件时间,aware datetimeemails[].timestamp_localstring本地时区格式化字符串emails[].subjectstring主题(解码后)emails[].extracted_dataobject正则提取结果;未配置为 {}``emails[].previewstring正文预览push.pushedboolean是否推送成功
旧参数1.0.0 对应time_window_hours: 24不填 start_datetime / end_datetime(默认即为过去 24h)time_window_hours: N改传具体的 start_datetime / end_datetime,或由调用方动态计算手写 imap_host优先改用 provider(内置 20+ 主流服务商)
其余参数(关键字、正则、推送)均向前兼容。