把「发一封邮件」做成一项服务
不是 SMTP 的简单封装。Gomail 管的是谁发的、用什么模板、发给谁、到了没有、要不要停这一整条链路。
发信能力
🧩 模板变量与校验
模板声明变量清单,渲染时缺变量直接返回 422,而不是发出一封「您好 ,您的验证码是」。宁可报错也不发出残信。
🧼 HTML 自动转义
变量插值到 HTML 部分一律 html.escape;邀请人昵称这类用户可控输入进邮件,从此不再是存储型 XSS 入口。
📄 双版本正文
同一封邮件同时生成 HTML 与纯文本。缺纯文本版容易被判垃圾邮件,这是发信信誉里最便宜的一分。
🏷 品牌前缀
主题统一加 【GOGO-简称】;客户要求完全白标时用 brand_name 整体覆盖。
📮 Message-ID 可反查
每封信注入 <16位hex>@发信域 的 Message-ID,阿里云回执带回的 msg_id 与之对应,回执能精确落回台账。
💾 通道降级不假装成功
未配 SMTP 时落 outbox 并在台账标 outbox;绝不返回 sent —— 自欺欺人的状态会让故障排查失去线索。
网站表单留言收集
让用户在你网站上填的表单,进你的收件箱,也进你的后台。
📥 一个端点收留言
网站表单 POST 到 /api/v1/inbox/submit,留言落库并生成查询号。不需要邮件服务器,也不碰 IMAP。
📧 同步发通知到指定邮箱
留言正文完整进入通知邮件;配了 form_notify 模板就按你的版式发。Reply-To 指向留言人,客服点回复即可联系。
🛡 专用表单密钥
gmk_ 开头,可以安全贴在网页前端:只能往指定表单投递、只能从白名单域名发起。gm_live_ 绝不能进浏览器。
🚧 五道防滥用
来源域名白名单、蜜罐字段、密钥+IP 双维限速、内容与字段数上限、接入方停用即熔断。
🗃 后台可查可管
管理台「站点留言」按表单、状态筛选与关键词搜索,支持标记已读 / 归档 / 垃圾。留言保留原文,只改状态不改内容。
🧯 邮件失败不丢留言
先落库后通知。SMTP 抖动只是通知没发出去,留言本身已经安全入库 —— 客户的线索不会消失。
隔离、台账与治理
多商户共用一个发信域名时,这几条决定会不会被连带拖进黑名单。
🔐 密钥与主叫识别
gm_live_ / gm_test_ 两类密钥,库里只有 SHA-256。接入方身份由密钥反查,绝不从请求体读 app_id。
🗂 台账不存明文邮箱
只落 to_hash(SHA-256)与 to_masked(如 1***@gogo198.net)。备份、导出、主从复制都会带走明文,落地之后收不回来。
↩ 回执直接入账
阿里云 EventBridge / MNS 回调同一端点,送达、软退、硬退、投诉、退订按状态码分类落账。
🚦 抑制名单与熔断
硬退与投诉自动入名单。552/554 归软退不拉黑 —— 一次内容误判就永久封掉真实用户,是无法自愈的误伤。
🧑⚖️ 角色与数据范围
商户登录后 owned_app_id 决定可见范围;请求别人的 app_id 一律 403。空结果会把「没数据」和「没权限」混成一笔糊涂账。
🧾 调用日志脱敏
只存脱敏后的 request_summary,密码/token/secret 字段一律置 ***,IP 抹到最后一段。
API 能力矩阵
| 能力 | 接口 | 鉴权 | 说明 |
|---|---|---|---|
| 发送邮件 | POST /api/v1/send | 接入方 API Key | 按 template_key 渲染后投递,返回 status/channel/message_id |
| 自查台账 | GET /api/v1/me/deliveries | 接入方 API Key | 只能看自己的,且无明文邮箱 |
| 健康度 | GET /api/v1/me/stats | 接入方 API Key | 7 日窗口的送达率 / 硬退率 / 投诉率 |
| 注册 / 登录 | POST /api/v1/auth/* | 无 / 会话 | 邮箱注册 + 验证链接 + 账号口令登录 |
| 后台管理 | /api/v1/admin/* | 会话(管理员)或静态令牌 | 接入方、密钥、模板、用户、台账、日志 |
| 回执回调 | POST /api/v1/webhooks/mail/aliyun | URL 令牌 | 必须公网可达且只认 80/443 |