listmonk 如何接入 SendGrid / Twilio 签名事件 Webhook 记录弹跳

发布时间:2026/9/14 6:54:01
listmonk 如何接入 SendGrid / Twilio 签名事件 Webhook 记录弹跳 listmonk 如何接入 SendGrid / Twilio 签名事件 Webhook 记录弹跳【免费下载链接】listmonkHigh performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.项目地址: https://gitcode.com/GitHub_Trending/li/listmonk如果 listmonk 的发送走 SendGrid 或 Twilio Email 的 SMTP 通道而你又想把发送产生的弹跳自动记回 listmonk而不是靠 POP3 邮箱扫描可以使用这两个服务商提供的签名事件 Webhook。listmonk 内置了接收端点/webhooks/service/sendgrid在 listmonk 侧启用弹跳处理、填入签名密钥并在服务商侧把 Webhook URL 指过去之后listmonk 会对每次回调验签、解析弹跳事件并写入 bounces 表再按你配置的弹跳处置策略退订、拉黑、删除等执行计数。以下内容基于 docs/docs/content/bounces.md、frontend/src/views/settings/bounces.vue 和 internal/bounce/webhooks/sendgrid.go。前提是你的 listmonk 实例可被公网访问——文档统一以https://listmonk.yoursite.com/...举例其中listmonk.yoursite.com是占位域名需要换成你的实际域名。一、启用弹跳处理与 Webhook文档明确说明弹跳处理bounce processing未启用时POP3 扫描和 Webhook API 都不可用所以第一步必须打开它。在管理面板Settings → Bounces页面对应 frontend/src/views/settings/bounces.vue 中的字段依次设置打开Enable bounce processing配置项bounce.enabled为三种弹跳类型配置处置策略每一行分别对应 soft / hard / complaint设置Bounce count每个订阅者的弹跳计数与Action可选None、Unsubscribe、Blocklist、Delete打开Enable bounce webhooks配置项bounce.webhooks_enabled。count/action 的组合可参考文档在 Amazon SES 一节给出的示例值Soft2/NoneHard1/BlocklistComplaint1/Blocklist。二、配置签名密钥与 Webhook URLlistmonk 侧仍在Settings → Bounces中打开Enable bounce webhooks后会出现各服务商的配置区。在 SendGrid 一行打开Enable SendGrid配置项bounce.sendgrid_enabled并在SendGrid Key配置项bounce.sendgrid_key中粘贴签名密钥。该密钥来自 SendGrid 事件 Webhook 的安全特性event webhook security features文档外部链接指向的就是 SendGrid 官方对应章节用于生成签名用的公钥。listmonk 会把这个密钥做 base64 解码、解析为 ECDSA 公钥并用它验证每次回调见 internal/bounce/webhooks/sendgrid.go签名来自请求头X-Twilio-Email-Event-Webhook-Signaturebase64 编码的 ASN.1 R/S 结构时间戳来自请求头X-Twilio-Email-Event-Webhook-Timestamp校验方式对「时间戳 请求体」取 SHA-256 后做 ECDSA 验签。SendGrid 与 Twilio Email 使用同一套签名方案因此两者共用这一个端点和同一个密钥字段。服务商侧在 SendGrid / Twilio Email 的事件 Webhook 设置中把回调 URL 登记为文档原文示例https://listmonk.yoursite.com/webhooks/service/sendgridURL 中的listmonk.yoursite.com是文档占位符替换成你的 listmonk 公网域名同时按服务商要求开启签名发送。控制台中的具体操作路径以 SendGrid / Twilio 官方事件 Webhook 文档为准文档表格的 More info 列给出了出处。三、回调进来后 listmonk 做了什么入口是 cmd/bounce.go 的BounceWebhook路由参数service为sendgrid且密钥已配置时进入该分支收到一个请求后验签先读取上面两个请求头做签名校验密钥错误、签名无效时请求直接返回400事件不会入库。只处理弹跳事件请求体是事件 JSON 数组event不等于bounce的条目delivered、open、click 等被直接跳过。软硬弹跳分类按事件的bounce_classification字段technical和content记为soft其余情况记为hard。写入 bounces 表source固定记为sendgridemail转小写原始请求全文保存在meta中备查。关联活动事件 JSON 中的XListmonkCampaign字段SendGrid 会把邮件里的 X- 头展平进事件对应 listmonk 发出的X-Listmonk-Campaign邮件头被用作campaign_uuid使弹跳能对应到具体活动。所有弹跳随后统一走Record落库并按你在第一节配置的 Bounce count / Action 策略对订阅者执行处置。四、验证接入是否生效弹跳真实发生例如向一个不存在的收件人地址发信触发弹跳后用文档 Exporting bounces 一节给出的方式核对JSON API 查询username/password为你的 listmonk 凭据示例来自文档请替换实际值curl -u username:password http://localhost:9000/api/bounces或直接查数据库SELECT bounces.created_at, bounces.subscriber_id, subscribers.uuid AS subscriber_uuid, subscribers.email AS email FROM bounces LEFT JOIN subscribers ON (subscribers.id bounces.subscriber_id) ORDER BY bounces.created_at DESC LIMIT 1000;通过该 Webhook 写入的记录source为sendgridmeta保留原始事件内容据此可以和其他渠道POP3 扫描、其他服务商的记录区分。管理面板的 Bounces 页面同样可以看到这些记录。五、已知限制弹跳处理未启用时/webhooks/bounce与各服务商 Webhook 端点都不可用文档明确它们只在开启后生效。只产生 hard / softSendGrid/Twilio 通道不会生成complaint类型记录。非弹跳事件不落库一次回调里若只有投递状态或打开事件不会产生 bounces 记录。密钥必须与服务商端一致签名校验不通过时所有请求都以 400 拒绝此时先核对 SendGrid Key 填的是否为当前有效的签名密钥。可选分支用自定义脚本记录弹跳如果你的弹跳来自自己的邮箱、数据库或邮件服务器日志而不是签名 Webhook可以调用通用POST /webhooks/bounce接口见 docs/docs/content/bounces.md。必填字段email与subscriber_uuid至少一个外加source和typehard/soft可选campaign_uuid与任意metaJSONcurl -u api_username:access_token -X POST http://localhost:9000/webhooks/bounce \ -H Content-Type: application/json \ --data {email: user1mail.com, campaign_uuid: 9f86b50d-5711-41c8-ab03-bc91c43d711b, source: api, type: hard, meta: {\additional\: \info\}}其中api_username/access_token为你的 API 凭据user1mail.com与 UUID 是文档示例实际使用时替换为真实值。注意文档说明该接口的type字段当前不影响弹跳的处置方式——实际处置始终由 Bounces 页面的 count/action 配置决定。【免费下载链接】listmonkHigh performance, self-hosted, newsletter and mailing list manager with a modern dashboard. Single binary app.项目地址: https://gitcode.com/GitHub_Trending/li/listmonk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考