系统概览
本系统为多个网站 / 模块提供统一的验证码邮件能力。每个接入方是一个「应用」,拥有:
- 独立的 API Key(发信凭证)
- 独立的邮件模板(4 个场景各一份)
- 独立的验证码存储与限流(互不干扰)
业务流程:
业务系统 --POST /api/verify/send--> 本系统 --SMTP--> 用户邮箱
业务系统 --POST /api/verify/check--> 本系统 --校验 Redis--> 返回结果
一、创建应用
方式一:管理页面(推荐)
1
2
点左侧「+ 新建应用」,填写应用名称(显示在邮件里)、应用标识(英文/数字)、初始模板风格。
3
创建成功后得到
ak_ 开头的 API Key,复制保存给接入方。应用名称可以随时在左侧列表点「编辑」修改,改完立即影响新发出的邮件显示名。
方式二:管理 API
curl -X POST http://你的服务器:8000/api/apps \
-H "X-Admin-Key: 你的管理密钥" \
-H "Content-Type: application/json" \
-d '{"name":"XX商城","app_key":"shop","preset":"vibrant-orange"}'
二、接入发信
接入方只需调用两个接口,请求头带自己的 X-API-Key。
发送验证码
POST /api/verify/send
X-API-Key: ak_xxxxxxxxxxxxxxxx
Content-Type: application/json
{"email": "user@example.com", "scene": "register"}
校验验证码
POST /api/verify/check
X-API-Key: ak_xxxxxxxxxxxxxxxx
Content-Type: application/json
{"email": "user@example.com", "scene": "register", "code": "123456"}
scene 取值:
| 值 | 场景 |
|---|---|
register | 注册 |
login | 登录 |
reset | 找回密码 |
change | 变更 / 绑定 |
校验成功返回 {"ok":true,"message":"验证码校验成功"},即可放行业务操作。
同一个应用的发信与校验必须使用同一个 API Key。验证码按应用隔离,换 Key 校验会失败。
Python 调用示例
import httpx
BASE = "http://你的服务器:8000"
KEY = "ak_xxxxxxxxxxxxxxxx"
HEADERS = {"X-API-Key": KEY}
def send_code(email: str, scene: str = "register"):
r = httpx.post(f"{BASE}/api/verify/send",
json={"email": email, "scene": scene},
headers=HEADERS, timeout=10)
r.raise_for_status()
return r.json()
def check_code(email: str, code: str, scene: str = "register") -> bool:
r = httpx.post(f"{BASE}/api/verify/check",
json={"email": email, "scene": scene, "code": code},
headers=HEADERS, timeout=10)
return r.status_code == 200 and r.json().get("ok")
Node.js 调用示例
const BASE = "http://你的服务器:8000";
const KEY = "ak_xxxxxxxxxxxxxxxx";
async function sendCode(email, scene = "register") {
const res = await fetch(`${BASE}/api/verify/send`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-API-Key": KEY },
body: JSON.stringify({ email, scene }),
});
return res.json();
}
三、自定义模板
每个应用的 4 个场景各有一份模板,可独立修改,不影响其他应用。
1
打开 模板管理,选择左侧应用。
2
切换场景标签(注册 / 登录 / 找回密码 / 变更绑定)。
3
编辑标题、HTML 正文、纯文本正文。
4
点「预览」查看渲染效果(验证码固定 123456),确认后点「保存模板」。
四、模板变量
模板使用 Jinja2 语法,渲染时自动转义变量,防止注入。
| 变量 | 含义 | 示例 |
|---|---|---|
{{ company }} | 应用名称 | XX商城 |
{{ scene_name }} | 场景中文名 | 注册 |
{{ code }} | 验证码 | 123456 |
{{ ttl_minutes }} | 有效期(分钟) | 10 |
还支持 Jinja2 控制语句,例如:
{% if code %}您的验证码是 {{ code }}{% endif %}
五、内置模板
| preset | 名称 | 风格 |
|---|---|---|
minimal-blue | 简约蓝 | 白底蓝字,清爽通用(默认) |
business-gray | 商务灰 | 深色头部,正式稳重 |
vibrant-orange | 活力橙 | 橙色主调,活泼年轻 |
「套用预设样式」会覆盖该应用 4 个场景的模板,自定义过的内容会被替换。
六、隔离说明
| 维度 | 隔离方式 |
|---|---|
| 验证码 | Redis key 含应用 ID,A 应用发的码 B 应用校验不到 |
| 限流 | 按「应用 + 邮箱」计数,互不影响 |
| 模板 | 按应用 + 场景存储,各改各的 |
| 日志 | 发送日志带应用 ID,可按应用筛选 |
七、常见问题
Q1:接入方只换 API Key 就行吗?
是。接口地址、请求参数、返回格式都不变,只需要把 X-API-Key 换成新应用的 key。注意收发要用同一个 key。
Q2:邮件里的品牌名怎么改?
改应用名称即可。在模板管理页左侧应用列表点「编辑」改名,新发出的邮件显示名立即生效。
Q3:能不能让接入方自己登录改模板?
当前用统一的 Admin Key,适合内部使用。若要对外开放自助管理,需要再加接入方账号体系。
Q4:应用被删除了验证码还在吗?
系统不提供删除应用,避免误删。如需停用,可将数据库 app.status 改为 disabled,对应 API Key 立即失效。
Q5:内网应用怎么接入?
用内网地址调用即可,例如 http://172.21.109.5:8000,无需走公网。