从自建 SMTP 到调接口:给项目加邮件验证码的经过
前段时间给一个内部项目加邮件验证码,注册和一些敏感操作要做二次验证。本以为是小事,结果在"发邮件"这步上花的时间比写业务还多——从自己搭 SMTP 到最后改用现成接口,把这段经过记一下。
一开始是自己配的 SMTP
最早的方案是找了个邮箱,开了 SMTP,用代码连上去发。本地测的时候挺顺,发到自己邮箱也能收到。等到放到测试环境给同事用,问题就来了——一部分人收不到,去垃圾箱里翻才找到。
查了一圈,是发件域名没配 SPF 和 DKIM,邮件被收件方判成可疑邮件。把这两条解析记录补上,情况好一些,但还是不稳定。再加上要自己处理发送失败重试、控制发送频率,代码越写越多,而这些跟项目本身一点关系都没有。
折腾到后面我就在想,发个验证码而已,有没有必要搞这么重。
后来换成调接口
最后改成用现成的发信接口了,省了一大截事。我用的是 Spug 的邮件推送,接入很短。
登录之后在「邮件模板」里有个默认的验证码模板,把模板编码复制出来(类似 Mk9Fs4dT1bW),这个编码就是调用凭证,不用另外申请 token。然后把编码拼到地址后面发请求:
curl -d '{"to": "ops@example.com", "scene": "二次验证", "code": "664218", "minute": "10"}' \
https://push.spug.cc/mail/Mk9Fs4dT1bW
后端就是包一层 HTTP 请求:
import requests
body = {'to': 'ops@example.com', 'scene': '二次验证', 'code': '664218', 'minute': '10'}
resp = requests.post('https://push.spug.cc/mail/Mk9Fs4dT1bW', json=body, timeout=5)
print(resp.json())
验证码还是后端自己生成和校验,接口只负责发出去。SPF、DKIM 这些就不用自己操心了。
踩到的几个点
记下来给后面的人省点时间:
- 返回
code: 200不等于邮件送到了。它只是说请求入库成功,邮件是异步发的。返回里的request_id最好存下来,之后有人说没收到,可以拿它去查这封邮件的状态。我后来发现"没收到"基本都是进了垃圾箱。 - 模板编码别放前端。它等于凭证,放前端或者提交到公开仓库,别人就能拿去用你的额度。我是放在后端配置里的,另外服务端 IP 固定,就顺手配了个 IP 白名单。
- 发信记得设超时。毕竟是外部请求,别因为它卡住注册流程。
回头看,自己搭 SMTP 不是搭不出来,而是维护这些跟业务无关的东西不值当。换成接口之后这块就没再管过。用的是 Spug 邮件推送,sms.spug.cc,有需要的可以去看看。

浙公网安备 33010602011771号