OpenClaw 邮件智能摘要系统:多通道通知配置手册

作者: 🐤小鸡 & 韩宇栋 日期: 2026-02-07 适用版本: OpenClaw 2026.2.4+


系统概览

目标

构建一个自动化邮件智能摘要系统,能够:

  • 定时检查多个邮箱(Gmail / PKU / QQ / 163)的新邮件
  • 对邮件进行智能分类(🗑️垃圾 / 🎓学术 / 💼工作 / 👤个人)
  • 生成摘要 + 回复建议
  • 同时推送到 Telegram 和 iMessage 两个通道

技术栈

组件说明
OpenClaw Gateway核心调度引擎
email_summary agent专用邮件处理 Agent
Gmail OAuth2 API发送测试邮件
IMAP拉取邮件(fetch_emails.py)
Telegram Bot API通知推送(default bot)
iMessage (imsg-ssh)通知推送
Cron (isolated session)定时触发

架构设计

graph LR
    Cron[🕐 OpenClaw Cron
定时触发] -->|agentTurn
isolated session| Agent[🤖 email_summary Agent] Agent -->|IMAP| Mail[📬 邮箱
Gmail / PKU / QQ / 163] Agent -->|message
channel=telegram| TG[📱 Telegram
default bot 通知专用] Agent -->|message
channel=imessage| iMsg[💬 iMessage]

Agent 运行模式

触发方式Session 类型Channel 绑定跨通道限制
sessions_spawn (从 Telegram)子 session继承 Telegram❌ 受限
Cron isolated独立 session无绑定✅ 自由
Heartbeat (main session)主 session继承当前 channel❌ 受限

关键结论:使用 Cron isolated session 是实现多通道推送的最佳方式。


问题排查历程

第一次尝试:sessions_spawn

操作:从 Telegram 主 session spawn email_summary agent

结果

  • ✅ Telegram 推送成功
  • ❌ iMessage 推送失败

错误信息

1
2
Cross-context messaging denied: action=send target provider "imessage"
while bound to "telegram".

原因sessions_spawn 创建的子 session 继承了父 session 的 channel 绑定(Telegram),OpenClaw 的安全策略阻止跨 provider 消息发送。

文档参考

When a message tool call is bound to an active chat session, sends are constrained to that session’s target to avoid cross-context leaks.

OpenClaw Tools 文档

第二次尝试:Cron isolated session

操作:通过 cron.add 创建 isolated job 触发 email_summary agent

结果

  • ❌ Telegram 推送失败
  • ✅ iMessage 推送成功

错误信息

1
Telegram bot token missing. Set TELEGRAM_BOT_TOKEN or channels.telegram.botToken.

原因:Telegram 配置了多 account 模式(main + research),但没有 default account。当 isolated session 调用 message(channel=telegram) 时,OpenClaw 查找 default account 的 token,找不到就报错。

源码分析/src/telegram/token.ts):

1
2
3
4
5
6
// Token 解析优先级:
// 1. accounts[accountId].tokenFile
// 2. accounts[accountId].botToken
// 3. channels.telegram.tokenFile  (仅 accountId === "default")
// 4. channels.telegram.botToken   (仅 accountId === "default")
// 5. TELEGRAM_BOT_TOKEN 环境变量  (仅 accountId === "default")

当未指定 accountId 时,默认使用 "default"。如果 accounts 中没有 "default" 键,所有 fallback 路径都要求 accountId === "default" 才生效,导致找不到 token。

第三次尝试:添加 default 通知 bot ✅

操作

  1. 在 BotFather 创建专用通知 bot
  2. 在 config 中添加 channels.telegram.accounts.default
  3. 设置 dmPolicy: "disabled" + groupPolicy: "disabled"

结果

  • ✅ Telegram 推送成功(通过 default bot)
  • ✅ iMessage 推送成功

配置方案

1. 添加 Telegram default 通知 bot

channels.telegram.accounts 中添加 default account:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
{
  "channels": {
    "telegram": {
      "accounts": {
        "default": {
          "enabled": true,
          "botToken": "<通知专用 bot 的 token>",
          "dmPolicy": "disabled",     // 不接收任何 DM
          "groupPolicy": "disabled"   // 不接收任何群消息
        },
        "main": {
          // 原有配置不变,用于日常对话
        },
        "research": {
          // 原有配置不变,用于研究助手
        }
      }
    }
  }
}

要点

  • default 是 OpenClaw 的保留 accountId,未指定 accountId 时自动使用
  • dmPolicy: "disabled" 确保这个 bot 只用于出站通知,不接收用户消息
  • 需要先在 Telegram 上给新 bot 发 /start,否则 bot 无权限主动发消息

2. 使用 Cron isolated session 触发

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// cron.add 参数
{
  "name": "邮件智能摘要",
  "schedule": {
    "kind": "cron",
    "expr": "*/5 * * * *",
    "tz": "Asia/Shanghai"
  },
  "sessionTarget": "isolated",
  "agentId": "email_summary",
  "wakeMode": "now",
  "payload": {
    "kind": "agentTurn",
    "message": "检查所有邮箱的新邮件,进行智能分类和摘要,推送到 Telegram 和 iMessage。"
  },
  "delivery": { "mode": "none" }
}

为什么用 delivery: none

  • delivery 只能配一个 channel + 一个 target
  • 我们需要同时推送到 Telegram 和 iMessage
  • 所以让 agent 自己调用 message 工具,分别推送到两个通道

3. 跨通道消息配置(可选)

如果还需要通过 sessions_spawn(而非 cron)触发 agent,需要额外配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "agents": {
    "list": [
      {
        "id": "email_summary",
        "tools": {
          "message": {
            "crossContext": {
              "allowAcrossProviders": true,
              "marker": { "enabled": false }
            }
          }
        }
      }
    ]
  }
}

测试验证

测试流程

  1. 发送测试邮件(通过 Gmail OAuth2 API)
  2. 创建一次性 Cron jobschedule.kind: "at" + deleteAfterRun: true
  3. 验证两个通道是否收到通知

验证清单

检查项预期结果
Telegram (default bot) 收到摘要
iMessage 收到摘要
邮件分类正确
时间显示为 UTC+8
pending_emails.json 已清理

经验总结

🔑 核心要点

  1. Cron isolated session 是多通道推送的最佳选择

    • 无 channel 绑定 → 不受 cross-context 限制
    • 每次运行独立 session → 无历史上下文污染
    • delivery: none + agent 自行调用 message → 灵活控制多通道
  2. Telegram 多 account 必须配 default

    • 未指定 accountId 时,OpenClaw 默认查找 "default" account
    • 没有 default 会导致 “bot token missing” 错误
    • 建议用专用通知 bot 作为 default,设 dmPolicy: "disabled"
  3. Cross-context 限制是安全特性,不是 bug

    • 防止 agent 在一个 channel 的上下文中意外向另一个 channel 发消息
    • 如需跨通道,优先用 cron isolated session,而非放开 crossContext
  4. sessions_spawn vs cron 的选择

    • sessions_spawn:继承父 session 的 channel 绑定,受 cross-context 限制
    • cron isolated:无绑定,自由发送到任意 channel
    • 对于需要多通道推送的任务,始终使用 cron

⚠️ 踩过的坑

原因解决
iMessage 推送失败 (sessions_spawn)子 session 继承 Telegram 绑定改用 cron isolated
Telegram token missing (cron)多 account 模式无 default添加 default account
本地无法发送邮件服务器无 SMTP/mail 命令使用 Gmail OAuth2 API

📚 相关文档


本文档记录了 2026-02-07 的完整调试过程,供后续配置参考。