Skip to content

Feature Notifications zh

SkimMail docs edited this page Sep 15, 2026 · 1 revision

English · Tiếng Việt · 中文

通知

1.3.0 起,SkimMail 可以在出事时主动告诉你,而不用你一直盯着:某个账户停止 同步、某条出口挂了、某个 OAuth 登录快要过期——而自 1.4.0 起,还包括你的规则认 为值得说一声的任何事。投递走的是你配置一次、各个功能共用的通知渠道。

它解决什么问题

这是两个不同的问题,值得分开谈,因为它们的失败方式不一样。

运维告警(“Watchtower”)回答的是:这台服务器还在干活吗? 一个三周前就悄悄停 止同步的自建邮件阅读器,比一个明显宕掉的更糟,而没人会盯着一个自己没理由打开的仪 表盘。

推送通知回答的是:有我在乎的东西到了吗? 那是另一批受众——手机前的你——也是另 一条投递路径。

它在哪里

  • 设置 ▸ Notifications —— 推送偏好、通知渠道,以及每个渠道对哪些 Watchtower 事件触发。读设置是 viewer 级;改设置是 operator 级。
  • 规则也路由进同一批渠道:设置 ▸ Rules。见规则与信号

以上这些设置都是实例级的,不是按用户的:这个实例的每个用户共用同一组渠道和同 一份推送偏好。

两类通知

Watchtower 告警 推送
回答 服务器还在工作吗? 有邮件到了吗?
发往 渠道(聊天、webhook) 浏览器和设备
触发于 auto-stop、出口失效、OAuth 失败 新邮件,或某条规则的推送动作
静默时段 不适用 适用
需要 一个渠道 一个已订阅的浏览器或一台 FCM 设备

告警不会被静默时段压住,这是刻意的:静默时段说的是邮件,而一个凌晨两点停掉的账户, 到早上八点还停着。

通知渠道

设置 ▸ Notifications ▸ Notification channels。 六种类型:

类型 你要提供什么 机密怎么保存
Webhook 一个 http(s) URL,外加可选的 HMAC 签名密钥 URL 明文,密钥加密
Telegram 一个 bot token 和一个 chat ID token 加密
Slack 一个 incoming-webhook URL URL 本身就是凭据——加密保存
Discord 一个 incoming-webhook URL 加密保存
Microsoft Teams 一个 Workflows(Power Automate)URL 加密保存
Google Chat 一个 incoming-webhook URL 加密保存

所有保存的机密都是只写的:API 只说明有没有,从不说明是什么,保存时留空则保留 原值。如果某条投递错误里恰好带了凭据——比如 URL 里的 bot token——它会在错误抵达日志 或 API 之前被抹掉。

聊天类渠道收到的是纯文本渲染,这是刻意的:不用 markdown、不用 parse mode,这样 账户名或服务商的错误串里带格式字符时,也不会把消息弄坏或改形。Teams 收到的是 Adaptive Card 信封,因为旧的 O365 connector 格式已经停用。

每个渠道都有自己的 enabled 开关、自己的 Alert me when 选项,以及一个 Send test 按钮,它发一条合成事件并报告 HTTP 状态码和往返时间。测试之前请先保存 渠道。

Watchtower 告警

三个事件,每个渠道上各自独立开关:

事件 何时触发 默认
account_down 断路器在连续失败后自动停掉一个账户
proxy_down 被自动停掉的账户所用的出口已推导为 down
oauth_expiring 被停掉的 Gmail/Outlook 账户的失败看起来像认证失败

三者都是 auto-stop 断路器的后果,所以它们在账户被停掉的那一刻触发,而不是每次 同步失败都触发——触发条件见同步与同步健康。此外 proxy_down 还会按出口去重,冷却 30 分钟,免得一条驮着八个账户的死代理产生八条 告警。

oauth_expiring 默认关闭,因为它是个更软的信号:它是从服务商错误文本推断出来的, 而且它总是伴随同一账户的 account_down 一起到来。

Webhook 负载与签名

Webhook 渠道收到的是一个 JSON POST:

{
  "event": "account_down",
  "source": "watchtower",
  "message": "me@example.com stopped syncing after 3 failed attempts",
  "account": "me@example.com",
  "account_id": 4,
  "error": "dial tcp: i/o timeout",
  "failures": 3,
  "app": "SkimMail",
  "timestamp": 1757808000
}

上述三个事件的 sourcewatchtower,规则命中则是 rule,其 eventrule_hitproxy_down 里出现的是 proxyproxy_id,而不是账户字段。

设置了签名密钥后,每次投递会带上:

X-SkimMail-Signature: sha256=<hex HMAC-SHA256 of the exact request body>
User-Agent: SkimMail-Watchtower

投递最多重试三次——只在网络错误或 5xx 时,退避按每次递增一秒。4xx 是终态: 被拒绝的负载是配置问题,不是暂时性问题。每个请求 10 秒超时,整个 fan-out 20 秒超 时。

投递从服务器直连发出,绝不走某个账户的出口。 webhook 指向的是你自己的 endpoint;把它路由过某个邮箱的 proxy,既出人意料,又会把“有告警”这件事泄露给那个 proxy。见连接与按账户出口

推送到浏览器和设备

两条彼此独立的通道,可用其一或两者:

  • Web Push(自 1.5.0)—— 标准 VAPID,不需要任何厂商账号。密钥对在首次启动时 生成并持久化,所以没什么要配置的。用 VAPID_PUBLIC + VAPID_PRIVATE(要么都 设,要么都不设)覆盖它,用 VAPID_SUBJECT 设置联系人。浏览器仍然需要一个 HTTPS 源和每台设备的一次授权,所以一个纯 http:// 的局域网地址无法订阅——把 SkimMail 放到 TLS 后面,或者用一个 tunnel 插件。
  • FCM 用于移动端 —— 除非你设置 FIREBASE_ENABLED=true 并让 FIREBASE_CREDENTIALS 指向一份 service-account JSON,否则它是关闭的。

被推送服务报告为已失效的订阅或设备 token,会在下一次发送时被自动删除,所以被吊 销的浏览器不会越积越多。

打开着的 SkimMail 标签页里的实时更新完全不用这一套:它们走应用本来就握着的 WebSocket,规则的应用内 toast 也是同一条路。

静默时段,以及一条通知可以说什么

推送有一条闸门链,每一环都必须通过:

  1. 存在一条通道(Web Push 或 FCM);
  2. Enable push notifications 已打开——它默认是关的
  3. 该账户在 Active accounts 里,或者那个列表为空,即代表全部;
  4. 当前时间在静默时段之外(任一端为 -1 即关闭;窗口可以跨零点,所以 22 → 7 就是一夜);
  5. 内容设置决定文字。

内容设置的优先顺序:Hide content 覆盖一切,给出一条通用消息。否则 Show senderShow subject 各加各的部分,两个都关时你同样得到一条通用消 息。

规则的推送动作走的就是这同一条链,包括静默时段和内容设置——规则无法穿透静默窗 口推送。规则发往渠道则不同:它按渠道 id 明确路由,不会被该渠道的 Watchtower 事件开关过滤。只有渠道自身的启用开关起作用。

限制

起始版本 1.3.0(渠道 1.4.0,Web Push 1.5.0)
角色 读需 viewer,改需 operator
渠道类型 6 种
渠道数量上限 50
Webhook 重试 3 次;仅限 5xx 与网络错误
超时 每次尝试 10 秒,每次 fan-out 20 秒
proxy_down 冷却 每个出口 30 分钟
每次同步的规则命中 每账户 20 条,超出后丢弃并写一行日志
  • 作用范围是实例,不是用户。 渠道、推送偏好和静默时段由登录这台服务器的所有人 共用。
  • 没有投递历史。 失败写进日志;没有任何机制把失败的告警排队稍后重发。
  • “Only notify for priority mail” 被保存了,但还没人用它。 它是为 AI 分类准备 的,而本版本没有 AI,所以今天没有任何代码读这个设置。

它不做什么

  • 它默认不逐封通知。 推送在你打开之前是关的,即使打开,它说的也是“有新邮件”, 而不是“邮件在此”。
  • 它不存储也不转发你的邮件。 聊天渠道收到的是关于一个事件的一行渲染文本;邮件 正文绝不会经由这条路离开服务器。
  • 遇到 4xx 它不再重试,而且它不排队。告警触发时正好挂掉的 endpoint 就错过了那 条告警。
  • 它不为每一次同步失败告警——只有断路器停掉账户时才会。短暂的失败体现在同步健康 看板上,而不是通知里。
  • 它不发邮件。 SkimMail 没有外发邮件通道,所以没有“出事给我发邮件”这个选项。

另见


SkimMail · skimmail@base101.app · 2026-09-14 · commit 76610cb

Clone this wiki locally