边缘函数发不了邮件?我用 CNB 容器绕开了这个坑
从 TCP 限制到协作方案,一个无服务器邮件通知的实现
全文共 1018 字,阅读约需 3 分钟
最近给 OK University 加了一个评论邮件通知功能:当 AI 审核通过一条评论,或者我回复了评论人,就自动发一封邮件过去。听起来简单,部署到 EdgeOne Pages 上才发现,无服务器环境发邮件比想象中多绕了几道弯。
第一道坎:边缘函数里没有 TCP
EdgeOne 的 Pages 函数跑在 V8 isolate 上,只暴露标准 Web API(fetch 等),没有 Node.js 的 net/tls 模块。传统的 SMTP 客户端需要直连 25/465/587 端口,做 TLS 握手,这套在边缘函数里根本跑不了。
我先试了 Agent Mail CLI,发现它在边缘侧依赖本地工具链;又考虑 Resend 这类 API,但需要配置 DNS 记录;而自建 SMTP 中继又意味着必须维护一台服务器。这些方案要么依赖太重,要么和“无服务器”的初衷相悖。
让专业的人做专业的事:边缘只发信号,容器负责发信
最后的思路是把“要不要发”和“怎么发”拆开:
- 边缘函数只负责在用户触发评论事件时,通过
fetch调 CNB OpenAPI(build/start),触发一条api_trigger类型的流水线; - CNB 容器负责真正的发信逻辑
scripts/send-mail.mjs,容器有完整 Node.js 环境,可以用nodemailer正常连接 QQ 邮箱 SMTP。
这个流程的好处是:边缘函数不碰 TCP,只发一个无状态的 HTTP 请求;CNB 容器只在需要发信时启动,发完即走,没有常驻服务器。
简化的链路
- 评论人提交评论,或站长回复评论;
edge-functions/api/comments.js里的triggerMail收集to、subject、body;fetchPOST 到 API,同时把邮件参数注入到流水线环境变量;- CNB 流水线启动,执行
send-mail.mjs; nodemailer读取 QQ SMTP 配置,发送邮件。
一点感想
无服务器架构很适合处理轻量、事件驱动的逻辑,但遇到 SMTP 这种需要长连接、TCP 握手的场景,硬扛容易把自己绕进去。把边缘函数当作“触发器”,把重活交给短生命周期容器,是更服帖的做法。不是每一件事都要在边缘函数里完成,只要它们能高效地协作。
现在评论系统算是完整闭环了:评论 → 审核 → 通知 → 回复 → 再通知。下一次打开邮箱看到“你的评论已通过审核”的时候,应该就能意识到这背后绕了多大一圈。
最后需要注意的是,CNB是有云构建时长的,运行发邮件的流水线把处理器设为1就够了,节约一下云构建时长。
