Files
MailUI4Agents/deploy/push.json.example
JianFeeeee 46fa7fa729 feat(push): 可选、配置式、多厂商的推送通道(HMS 为首个实现)
用户要求:推送密钥必须是可选项(自部署后端不能写死推送方式),且要支持
多厂商配置式接入 —— 每个用户各自部署服务器、自己选厂商、自己配凭证。
所以落地成:

· internal/push:通道抽象 + 工厂表(RegisterType),加厂商不改配置层与端点形状;
  HMS 只是第一个实现(internal/push/hms.go)
· 配置在 PUSH_CONFIG(默认 <AGENTMAIL_DATA_DIR>/push.json),一项一个厂商,
  凭证走文件(app_secret_file / files.*,建议 600);环境变量只是可选覆盖
· 没配 = 整条推送路径连一次查库都不发生(shouldDispatch 早退);
  单项配错(未知类型/密钥读不到/enabled:false)只跳过那一条,不影响启动
· push_tokens 表带 provider 维度 + 三个 /me/devices/push-token 端点;
  没配推送时端点照存并回 enabled:false(登记成功 != 服务端开了推送)
· notify.Recipients 末尾异步挂钩:收件人名单直接用 SSE 那份 seen(两条通道
  共用同一份"谁该收到"的判据);失败只记日志,绝不拖住收信

HMS 的形状是拿真凭证打线上接口问出来的(v1 + message.token[] + testMessage;
payload/target 形状 v1 不认、v2 要服务账号 JWT)。未上架应用必须 test_message=true,
单批 ≤10 token(MaxTokensPerRequest 声明)、每日 1000 条兜底(项目级额度)。
实测:App ID + App Secret 能换到 access_token(3600s);形状被线上服务接受。

判据:repo 6 条 + push 12 条 + handler 3 组,全部做过**变异验证** ——
过程中抓出两条假判据(异步分发与 t.Cleanup 赛跑而假绿;密钥文件优先级没被覆盖)
并补掉。Go 全量测试与 go vet 干净。

★ 未验:端到端真机送达(需要真机 token + 客户端按 com.jianf.agentmail 重编并签名,
签名指纹还要在 AGC 登记)—— 从未真正发出过一条能到达设备的推送。
详见 docs/HMS-PUSH-PLAN.md 的「实现状态」一节。
2026-09-15 11:21:00 +08:00

68 lines
2.6 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"_说明": [
"AgentMail 推送通道配置(可选)。默认路径 <AGENTMAIL_DATA_DIR>/push.json,",
"也可用环境变量 PUSH_CONFIG 指向别处。文件不存在 = 没配推送 —— 那是正常状态,",
"服务端一切照常(SSE 仍是在线客户端的收信主通道)。",
"",
"设计要点:",
" · 多厂商:providers 是一张表,一项一个厂商(type)。同一实例可以同时接多个厂商。",
" · 配置式:加新厂商 = 服务端加一个 Factory 实现 + 一行 RegisterType,用户只改这个文件。",
" · 凭证是配置项:密钥走文件(app_secret_file 或 files.*),文件权限建议 600;",
" 不喜欢文件也可以内联 app_secret(方便临时验证,但不推荐)。",
" · 谁部署谁配:每个用户自己部署服务端、自己选厂商、自己填凭证。",
"",
"改完这个文件需要重启 gateway 生效:systemctl restart agentmail-gateway",
"(重启会打断正在跑的 worker,挑空闲时做。)"
],
"providers": [
{
"_说明": "华为 HMS Push(鸿蒙设备)。未上架应用必须 test_message=true,否则收不到。",
"type": "hms",
"name": "hms",
"enabled": true,
"app_id": "6917616450599975320",
"app_secret_file": "/etc/agentmail/hms-app-secret",
"client_config_file": "/etc/agentmail/agconnect-services.json",
"test_message": true,
"daily_limit": 1000
},
{
"_说明": [
"同一厂商接多套凭证的写法:显式给 name 区分,客户端按名字登记 token。",
"(例如同一个服务端要同时推给两个华为应用)"
],
"type": "hms",
"name": "hms-second-app",
"enabled": false,
"app_id": "0000000000000000000",
"files": {
"app_secret": "/etc/agentmail/hms-second-app.secret"
},
"test_message": true
},
{
"_说明": [
"其它厂商(Web Push / 小米 / 荣耀 …):",
"服务端需要先有该厂商的 Factory 实现(internal/push 里 RegisterType),",
"否则这一项会在启动日志里被标记为「不支持的类型,已跳过」,其余条目照常启用。",
"厂商私有的密钥类文件统一放 files 表里(键名由那个厂商的实现定义)。"
],
"type": "webpush",
"name": "webpush",
"enabled": false,
"files": {
"vapid_public_key": "/etc/agentmail/vapid.pub",
"vapid_private_key": "/etc/agentmail/vapid.pem"
}
}
]
}