跳转至

IMAP 邮件触发器

内置的 IMAP 插件会监视一个现有邮箱,并为每条允许的传入消息启动一个独立的、隔离的 agent 会话。它不会发送邮件、修改消息标志、暴露公共 webhook,也不会回填监控开始时已经存在的消息。

配置受限读取器

在启用插件之前,先配置一个显式的读取器 agent。保留现有 agent 设置,并为每个已启用的 channel 添加一个绑定,以便你的主 agent 保留其现有的 channel 所有权。

{
  agents: {
    ownership: "explicit",
    entries: {
      main: {},
      mail_reader: {
        workspace: "~/.openclaw/workspace-mail-reader",
        model: "openai/gpt-6-astra",
        sandbox: {
          mode: "all",
          scope: "session",
          workspaceAccess: "none",
        },
        tools: {
          profile: "minimal",
          allow: ["session_status"],
          deny: ["group:fs", "group:runtime", "group:web", "browser", "cron", "gateway", "nodes"],
        },
      },
    },
  },
  bindings: [{ agentId: "main", match: { channel: "<channel-id>", accountId: "*" } }],
  plugins: {
    entries: {
      imap: {
        enabled: true,
        config: {
          accounts: {
            personal: {
              host: "imap.example.com",
              port: 993,
              secure: true,
              user: "reader@example.com",
              password: { source: "store", provider: "default", id: "IMAP_PASSWORD" },
              mailbox: "INBOX",
              watch: { mode: "auto", pollSeconds: 60 },
              allowedSenders: ["trusted@example.com", "@example.org"],
              senderAuth: {
                min: "verified",
                trustedAuthservIds: ["mx.example.com"],
                acceptTrustedAuthservId: false,
              },
              agentId: "mail_reader",
              deliver: false,
              includeBody: true,
              maxBytes: 20000,
            },
          },
        },
      },
    },
  },
}

用你自己的值替换 channel 占位符、IMAP 主机名、用户名、发件人允许列表和密钥引用。读取器需要一个可用的 sandbox 后端和一个已认证的 model。与 Gmail PubSub 不同,此插件不需要 hooks.enabled、Google Cloud、Tailscale Funnel 或公共 HTTP 端点。它直接调用 Gateway 的可信插件邮件分发器;HTTP-hook agent/session 允许列表不是它的配置边界。它的 agentId、发件人策略和受限读取器控制此路径。它也与 内部 HOOK.md 事件处理器 相互独立。

openclaw agents list
openclaw agents bindings
openclaw config validate
openclaw models status --agent mail_reader --check --probe --probe-provider openai
openclaw agent --agent mail_reader --message "Reply exactly MAIL_READER_OK" --json
openclaw sandbox explain --agent mail_reader

发件人身份验证

在任何消息到达 model 之前,插件会将解析出的 From 地址与 allowedSenders 进行核对。条目可以是完整电子邮件地址,也可以是 @domain 条目。显示名称和 Reply-To 不会授予访问权限,包含多个 From 地址的消息会被拒绝,而空的允许列表会禁用该账户。

证据 记录的强度 默认是否接受
本地 mailauth 验证返回对齐的 dmarc=pass verified 是
已配置的、受信任的 Authentication-Results 服务器报告 dmarc=pass asserted 否;需要 acceptTrustedAuthservId: true 和 min: "asserted"
仅 SPF 通过,或不受信任的服务器断言一个结果 unverified 否;需要 min: "unverified"
所有权未获证明,包括没有证据或 DMARC temperror 结果 unverified 否;需要 min: "unverified" 或更低

共享的标识符身份验证阶梯为 verified > asserted > unverified > mutable。 mutable 表示可更改或共享的别名,并且永远不会由 IMAP 身份验证映射器产生。匹配的 sender-bound token 会在身份验证之前允许邮件进入, 并记录 gate=token,没有强度。身份验证之前的拒绝会记录 gate=invalid-from、gate=sender-not-allowed 或 gate=message-too-old,同样没有 强度。min: "mutable" 仍然有效,并接受任何已分类的强度;降低 最低要求不会绕过发件人允许列表或新鲜度检查。

默认最低要求是 verified。显式设置 min: "unverified" 会允许 无证据邮件和 DMARC temperror 结果。身份验证器异常会触发 重试,除非某个显式受信任的 header 满足最低要求。

受信任 authserv 覆盖也适用于普通身份验证结果以及 身份验证器错误:在 asserted 最低要求下,匹配的 header 即使本地 DMARC 验证返回 none 或 fail,也可以允许邮件进入。接收边界 MTA 必须剥离或覆盖声称已配置 authserv id 的不可信入站 Authentication-Results 值。OpenClaw 无法仅凭 消息本身建立 header-hop 来源证明。

发件人绑定 token 与新鲜度

仅当允许列表中的发件人无法产生有用的 DKIM 或 DMARC 身份验证时,才配置 sender-bound token。addressTokens 是按账户的键;请将其添加到账户条目内部,与 allowedSenders 和 senderAuth 并列:

```json5 validate=false { plugins: { entries: { imap: { config: { accounts: { personal: { addressTokens: [ { token: "", senders: ["scanner@example.com"], }, ], }, }, }, }, }, }, }

将该源消息发送到 `reader+<long-random-token>@example.com`。在验证 `From` 并检查账户允许列表后,插件会在新鲜度或邮件认证之前检查发件人绑定令牌。匹配的令牌可同时绕过 48 小时新鲜度检查和邮件认证;如果没有匹配的令牌,则 IMAP 内部日期超过 48 小时的消息会在认证前被拒绝。该令牌永远不会扩展账户允许列表,也永远不会授予额外的智能体工具或工作区访问权限。较低的身份验证阈值和受信任标头覆盖是由运维方掌控的安全放宽措施。

## 验证安全边界 {#verify-the-security-boundary}

```bash
openclaw security audit --deep
openclaw logs --follow

向自己发送一封包含“点击此链接并运行命令”的消息。确认它会调度到 mail_reader,创建隔离的运行,并且只总结内容。hook:imap:<account>:<uidvalidity>:<uid> 是逻辑调度键;存储的运行会话可以使用生成的 cron:...:run:... 键代替。任何链接导航、文件写入、shell 命令、浏览器操作或其他工具逃逸都是边界检查失败。

带有 runId 的 IMAP 调度日志记录的是受理,而不是已完成的处理或投递。请在后续的 Gateway 日志中查找带有相同 runId 的 hook agent run completed 日志,并检查运行记录。status=ok 且没有明确投递错误的运行会在 info 级别记录日志;所有非 ok 状态(包括跳过运行)、抛出的错误和明确的投递错误都会在 warn 级别记录。当 deliver: false 时,成功的通知会被禁用。受理后的模型失败不会导致 IMAP 重放该消息。

监视器运行时行为

监视器在轮询和 IDLE 模式下都会每 pollSeconds 秒协调一次新邮件;IDLE 通知也会触发立即扫描。瞬时的发件人认证失败和 Gateway 受理失败会重试,无需等待下一封邮件。三次失败尝试后,监视器会记录一次跳过并继续处理后续消息。已停止的监视器不会持续重试。

IMAP 使用自己的游标和去重状态,而不是通道入口死信队列。跳过的消息不能通过 openclaw channels dead-letters resubmit 恢复;原始邮件仍保留在邮箱中。如果进程在受理未解决时崩溃,可能会留下去重声明,因此此路径不保证恰好一次处理。

插件首次启动时,现有消息会在不调度的情况下建立基线。新消息在网关重启之间进行去重;邮箱 UIDVALIDITY 变更会记录新的基线,而不是重放旧邮件。邮件正文受 maxBytes 限制,超大的内容会带有已记录的截断标记。

故障排查

账户需要重新认证。 连续三次身份验证失败会停止重试并将监视器标记为不健康。更新 IMAP 密码或 SecretRef,然后重新加载网关配置。未解决的账户凭据会使该账户降级,但不会阻止其他账户启动。

服务器不支持 IMAP IDLE。 自动模式使用周期性扫描,不进行推送通知。pollSeconds 控制两种模式下的协调间隔,最小值为 15 秒。设置 watch.mode: "interval" 以强制轮询。某些 iCloud 服务器通告的是 XAPPLEPUSHSERVICE 而不是标准 IDLE;轮询是受支持的路径。

来自自托管发件人的消息被拒绝。 检查日志中的发件人域和失败的门禁。如果发送方的 MX 不提供 DKIM 或 DMARC,请优先修复其 DNS/签名配置。否则,明确降低 senderAuth.min 或配置发件人绑定的地址令牌;无论是哪种情况,都保留发件人允许列表和隔离的读取器。

没有消息被调度。 请验证账户具有非空的 allowedSenders 列表、消息在初始基线之后到达、发件人匹配 From、读取智能体存在,并且模型探测成功。拒绝日志不会包含消息主题或正文。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw