发信账号来源开关:app.ini / 程序自带 SMTP

- params.ini 新增 [mail]:source=app(默认,用 conf/app.ini [mail])或
  own(用 account/password/smtp/port/skip_tls_verify 这套);--mail-source
  app|own 可临时覆盖(命令行 > params.ini)
- 切换后发信与退信核查(IMAP,含主机推导)都走这套账号;切换到 own 但
  配置缺项时直接 FATAL,不用半套配置
- password 支持 env:变量名:params.ini 会被 git 跟踪,明文密码时打印警告
- 交互模式:[mail] 配齐时多问一次来源;保存时 [mail] 小节原样回写
- 修复:save_params 缺少 batch_size/smtp_idle_reconnect 形参,但调用点已在
  传 → 交互模式选「保存到 params.ini」会 TypeError 崩溃(上一并行编辑漏改)
- 补回上一轮被漏掉的 README「合并信封批量发送」章节与 452 安全机制条目
This commit is contained in:
tamakyi
2026-09-08 00:23:51 +08:00
parent d4e5c611b0
commit 1407fa9fb6
3 changed files with 202 additions and 5 deletions
+45
View File
@@ -261,6 +261,50 @@ conf/app.ini 路径的解析优先级:
- 每次核查另写一份明细报告 broadcast_bounce_report.json(含每个收件人的
类别与判定依据,以及 scan_mode / scan_cursor
发信账号来源:app.ini / 程序自带 SMTP
------------------------------------
默认用 conf/app.ini [mail] 的 SMTP(站内信跟随站点自己的邮箱)。切到程序
自带的一套后,发信与退信核查(IMAP)都走这套账号:
[mail]
source = app ; app(默认)= conf/app.ini [mail]own = 下面这套
account = bot@other.com
password = env:MY_SMTP_PASSWORD ; 支持 env:变量名,推荐
smtp = smtp.other.com
port = 465
skip_tls_verify = 0
临时切换(优先级高于 params.ini):`--mail-source own` / `--mail-source app`
交互模式里若 [mail] 配齐了,会多问一次选哪个来源。
安全提醒:
- params.ini 会被 git 跟踪,**不要把密码明文写进去**;用 `env:变量名`
从环境变量读取,或把 params.ini 加入 .gitignore
- 明文写死时脚本会打印警告,但不会阻止运行
- 切到 own 但 [mail] 缺 smtp/account/password 时直接 FATAL,不会用半套配置
合并信封批量发送(可选)
------------------------
默认逐人一封(一个 SMTP 信封 = 1 个 RCPT TO)。开启 batch_size 后,
「渲染后内容完全相同」的收件人合并发送:一个信封 = 1×MAIL FROM +
N×RCPT TO + 1×DATA,发送次数从「人数」降到「信封数」(如 305 人、
每 50 人一封 → 约 7 次发信)。
开启方式(0=关闭):
broadcast.py --send --single --batch-size 25
或 params.ini [send] batch_size = 25
与限流的关系(要点):
- 服务商按「发信次数」计频率 → 合并后成倍降低触发概率(主要收益)
- 服务商按「单位时间收件人总数」计数 → 无缓解,仍靠 delay/pause 控制节奏
- 单封收件人数上限常见 50~100:超限的 RCPT 会被 452 拒收,脚本自动把
batch_size 砍半、被拒者重试,不会中止也不会误判为限流
- 信封收件人对其他收件人不可见;批量信封的 To: 头显示为「站点名+发件邮箱」
适用的前提是内容逐字相同:模板含 {{name}}/{{box_link}} 等个人化占位符时,
渲染结果逐人不同,会自动落回逐封,不会错合。断点续发按人记录(DATA 被
服务器接收即整批入账,被拒的除外);发送中限流巡检照常按收件人数计数。
安全机制
--------
- 默认 dry-run--send 需终端输入 yes 确认(--yes 跳过)
@@ -272,6 +316,7 @@ conf/app.ini 路径的解析优先级:
连接空闲超过 `smtp_idle_reconnect` 秒(默认 30,0 关闭)就主动重连;
仍遇到断线则立即重试最多 3 次(间隔 2s/4s),失败才会记为该收件人失败
- SMTP 拒收(refused)计入失败并写入报告
- 批量信封遇 452「收件人数超限」自动砍半拆批重试;限流类拒收仍立即中止
- From/Subject 头自动做 RFC2047 编码(中文显示名不会被 QQ 邮箱 550 拒收)
- 自动定位 users 表所在 schema(避免 psql 命中别的同名空表)
- 语言列自动试跑探测(language → lang → NULL 兜底),老库没有该列也能发