SMTP 断线自动重连:修掉大 delay 下整批 please run connect() first

现象:--delay 调到 60s/封、发 305 人时,第一封报 Server not connected,
之后每一封都是 please run connect() first,全军覆没。

根因:SMTP 服务器会掐掉空闲连接(QQ/163/阿里云常见 5~15 分钟,有的更短)。
脚本只在开头 smtp_login 一次,之后从不重连——连接一旦被服务器关掉,
同一个死掉的连接对象会被反复使用,除第一封外全是 connect() 报错。
delay 越大必然越早触发;以前默认 1s/封时几乎等不到超时,所以没暴露过。

改动:
- 新增 SmtpSession 包装连接:
  * 空闲超过 smtp_idle_reconnect 秒(默认 30,可 0 关闭)就主动断开重连,
    不必每封都先吃一发失败
  * 仍遇到断线类异常(ServerDisconnected/ConnectError/OSError)立即重连
    重试,最多 3 次(间隔 2s/4s);耗尽后抛原始异常、该收件人如实计失败
  * 只重试连接类异常;SMTP 拒收(5xx/4xx 回话)不重试,避免重复投递
  * 「Server not connected」不会被误判为限流,不会误触发发送中止
- 新增 --smtp-idle-reconnect / params.ini [send] smtp_idle_reconnect
- 发送循环改用 SmtpSession,结束统一 close
This commit is contained in:
tamakyi
2026-09-07 20:14:34 +08:00
parent f83ea3e29a
commit 5823b5fbb3
3 changed files with 92 additions and 8 deletions
+5
View File
@@ -41,6 +41,7 @@ README — TamaBox 站内信群发工具(mail-broadcast
to = ; 可选:默认测试收件邮箱
delay = 1.0
group_pause = 3.0
smtp_idle_reconnect = 30 ; SMTP 空闲超时秒数,超时就重连
[bounce] ; 退信核查 / 发送中限流巡检(见下节)
watch_bounces = 1 ; 发送中巡检限流退信,发现即中止
@@ -257,6 +258,10 @@ conf/app.ini 路径的解析优先级:
- 发送前打印数据库统计与语言分布,人工核对
- 每封间隔 --delay 秒(默认 1.0);--pause-every/--pause-for 防限流
- 按语言分群发送,组间 --group-pause 秒(默认 3.0
- SMTP 断线自动重连:服务器会掐掉空闲连接,--delay 调大(如 60s/封)时
必现「Server not connected / please run connect() first」,整批失败。
连接空闲超过 `smtp_idle_reconnect` 秒(默认 30,0 关闭)就主动重连;
仍遇到断线则立即重试最多 3 次(间隔 2s/4s),失败才会记为该收件人失败
- SMTP 拒收(refused)计入失败并写入报告
- From/Subject 头自动做 RFC2047 编码(中文显示名不会被 QQ 邮箱 550 拒收)
- 自动定位 users 表所在 schema(避免 psql 命中别的同名空表)