Appwrite SMTP 丢件:复用连接,没有探活
现象。 Appwrite 的 SMTP 间歇性丢件:有的信就是到不了,没有固定规律。
日志。 日志里看到发送失败,于是顺着往源码查。
agent 读源码。 coding agent 读了 Appwrite 1.9.9 的源码,一路追到机制。
机制。 邮件 worker 是常驻的 Swoole 进程。项目没配 SMTP 时,走注册的 adapter($register->get('smtp')),是个单例,keepAlive: true(app/init/registers.php)。messaging 1.2.0 的 SMTP adapter 包的是 PHPMailer 6.9.1,keepAlive 一开就跨发送复用同一个 PHPMailer 实例。复用之前没有任何探活。PHPMailer 只有读到 EOF 才认连接已死,所以服务端闲置断开的连接,在下一封真正发之前看起来还是活的。
对照。 项目自配 SMTP 每次新建 adapter,不受影响。两路的 keepAlive 都是 true,差别在复用,不在 flag。
发现。 这个机制没有 probe:复用的连接在下一封之前从不探活,这条路上也没有重试。追踪到这儿为止。
再连一个:五分钟是从哪来的? 这次的五分钟是 Mailpit 的 SMTP 超时:这套部署的 SMTP 服务就是 Mailpit,它的 SMTP 闲置超时把连接断了。NAT 还是连着的相关概念:NAT 映射闲置会过期(how-nat-works),而应用心跳本来就兼职续 NAT 账行(keepalive-two-layers)。闲置超时是同一类机制,但这一次的五分钟是 Mailpit 的。