何时使用
用户要求用 QQ 邮箱做任何操作时使用本 skill:发信、收信、查邮件、看未读、搜索、读全文、下载或发送附件、标记已读、删除、移动、回复、转发、查看文件夹。
QQ 邮箱
所有能力通过 scripts/mail.js 提供。在 skill 根目录下执行。
依赖:首次运行时脚本会自动检测 imap / mailparser / nodemailer 三个依赖,缺失则自动执行 npm install --omit=dev(约十几秒,仅一次),无需手动干预。若自动安装失败(如离线环境),手动在 skill 根目录执行 npm install --omit=dev 即可。
服务器
| 协议 | 地址 | 端口 |
|---|---|---|
| IMAP(收信) | imap.qq.com |
993 (SSL) |
| SMTP(发信) | smtp.qq.com |
465 (SSL) |
第一步:确认凭证
绝大多数失败都源于未配置凭证或填错授权码。执行任何收/发操作前,先确认配置状态:
node scripts/setup.js --show
- 显示「已配置」→ 直接进入下一步
- 显示「未配置」→ 引导用户完成配置,不要擅自猜测或要求用户把密码贴进聊天记录:
node scripts/setup.js
交互式流程会要求输入邮箱地址和授权码,输入过程不回显,并自动测试 IMAP + SMTP 连通性,通过后写入 ~/.workbuddy/qq-email.env(权限 600)。
授权码 ≠ QQ 登录密码。 获取路径:QQ 邮箱 → 设置 → 账户与安全 → 安全设置 → 开启 IMAP/SMTP 服务 → 生成 16 位授权码。
其他配置命令:
node scripts/setup.js --check # 测试当前配置是否可用
node scripts/setup.js --account x@qq.com --code xxxx # 非交互式写入
凭证读取优先级:环境变量 QQ_EMAIL_ACCOUNT / QQ_EMAIL_AUTH_CODE > ~/.workbuddy/qq-email.env。
命令参考
node scripts/mail.js <子命令> [参数]
node scripts/mail.js help # 查看全部用法
收信
# 列出邮件(默认最近 20 封)
node scripts/mail.js list
# 常用组合
node scripts/mail.js list --limit 10 --peek # 最近 10 封,带正文摘要
node scripts/mail.js list --unread # 只看未读
node scripts/mail.js list --days 7 # 最近 7 天
node scripts/mail.js list --from boss@company.com
node scripts/mail.js list --subject 报销
node scripts/mail.js list --query 发票 # 主题/发件人/正文 全匹配
node scripts/mail.js list --folder "Sent Messages" # 其它文件夹
node scripts/mail.js list --json # JSON 输出,便于程序处理
# 读取完整正文(UID 来自 list 输出)
node scripts/mail.js read 12345
node scripts/mail.js read 12345 --mark-read # 同时标记为已读
node scripts/mail.js read 12345 --html # 输出 HTML 原文而非纯文本
# 文件夹
node scripts/mail.js folders
附件
node scripts/mail.js attachments 12345 --dir ./downloads # 下载全部附件
node scripts/mail.js attachments 12345 --dir ./dl --index 2 # 只下载第 2 个
发信
node scripts/mail.js send --to a@b.com --subject "主题" --body "正文"
node scripts/mail.js send --to a@b.com,c@d.com --subject "主题" --body "正文" \
--cc x@y.com --bcc z@w.com --attach ./报告.pdf --attach ./图.png
node scripts/mail.js send --to a@b.com --subject "主题" --stdin < body.txt # 长正文
node scripts/mail.js send --to a@b.com --subject "主题" --body "<h1>标题</h1>" --html
也兼容旧的位置参数写法:node scripts/mail.js send <收件人> <主题> <正文>
邮件管理
node scripts/mail.js flag 12345 --read # 标记已读(--unread 为未读)
node scripts/mail.js flag 12345 --star # 加星标(--unstar 取消)
node scripts/mail.js delete 12345 # 删除(QQ 邮箱会先移入「已删除」,可恢复)
node scripts/mail.js move 12345 --to "Sent Messages"
回复与转发
node scripts/mail.js reply 12345 --body "收到,谢谢" # 保留会话线程,自动引用原文
node scripts/mail.js reply 12345 --body "收到" --all # 回复所有人
node scripts/mail.js forward 12345 --to x@y.com --body "请看附件" # 带原附件转发
典型任务 → 命令
| 用户说 | 做法 |
|---|---|
| 「看看有没有新邮件」 | list --unread --peek |
| 「这封邮件说了什么」 | list 找到 UID → read <UID> |
| 「把附件存下来」 | attachments <UID> --dir ./downloads |
| 「帮我回复一下」 | reply <UID> --body "..." |
| 「把这封转发给张三」 | forward <UID> --to zhangsan@x.com |
| 「找上周那封发票邮件」 | list --days 7 --query 发票 |
| 「发个邮件给 X」 | send --to X --subject ... --body ... |
重要约束
- UID 与文件夹绑定。同一封邮件移动到别的文件夹后 UID 会变,失效的 UID 会提示「未找到」,此时重新
list获取。 - 中文搜索走本地过滤(只扫描最近 200 封),QQ 邮箱服务端对中文 SEARCH 支持不可靠。若怀疑漏掉,加
--days扩大范围。 list默认只拉取邮件头,速度快;要正文摘要加--peek,要全文用read。- 收信默认不会把邮件标记为已读,需要时显式加
--mark-read。 --json输出结构化数据,适合后续用脚本处理;解析失败时检查退出码。
故障排查
setup --check 可一次性定位问题。常见错误:
| 现象 | 原因与处理 |
|---|---|
| 登录失败 | 90% 是填了 QQ 密码而非授权码,或服务未开启。运行 node scripts/setup.js 重新配置 |
| 只有收信或只有发信成功 | 设置页里 IMAP 与 SMTP 需分别开启 |
| 提示登录频率受限 | 短时间内重试过多,等几分钟 |
| 连接超时 / ETIMEDOUT | 检查网络与防火墙是否能访问 imap.qq.com:993、smtp.qq.com:465 |
| 未找到 UID | 邮件已被移动或删除,重新 list |
特殊场景才需要的开关:QQ_EMAIL_TLS_INSECURE=1 可跳过 TLS 证书校验(仅在确认存在中间设备劫持时临时使用,不推荐长期开启)。
安全
- 授权码只存本地
~/.workbuddy/qq-email.env(600 权限),绝不写入代码、日志或提交到版本库。 - 不要要求用户把授权码粘贴到对话里;引导其自行运行
node scripts/setup.js输入。 - 不要在终端用
echo回显授权码。用node scripts/setup.js --show查看配置状态,授权码默认打码显示。 - 发信属于对外部世界的不可逆操作:执行
send/reply/forward前,务必先向用户确认收件人、主题和正文,不要擅自发出。 delete会真实删除邮件(QQ 邮箱先移入「已删除」文件夹,可恢复);执行前确认目标 UID 无误。