修复发信账号来源选了 own 却仍用 app.ini 发送

复现确认的三处缺陷(用户报:params 配了 own、启动时选 own,实际仍用 app 发):
1. 交互提示只认字面量 own:UI 其它选项都是 1/2/3/4,输入 2 会静默回落 app
2. 交互默认硬编码 app,忽略 params.ini 已配的 source=own → 直接回车也回落 app
3. 连锁:本轮选完若保存 params.ini,会把 source 写成 app 落盘,之后一直生效
   (这正是「填错信息报 426 → 改好后能跑但走 app 邮箱」的原因)

修复:
- 交互改为 1/2 数字选型(仍兼容 app/own 字面量),默认取 params.ini 的 source
- main 提供 _mail_source_default = params.ini [mail] source
- 保存时仅当本轮交互显式选过才写回 source,命令行临时 --mail-source 不落盘
- 发信前额外打印一行生效账号与来源,避免被忽略

回归:选 1→app、选 2→own、回车沿用 own、own 字面量兼容、保存后 source 正确、
未显式选时保留文件值,共 7 项断言
This commit is contained in:
tamakyi
2026-09-08 01:18:40 +08:00
parent 1407fa9fb6
commit 35e9a7231a
2 changed files with 27 additions and 10 deletions
+24 -9
View File
@@ -83,7 +83,7 @@ from email.mime.text import MIMEText
from email.utils import formataddr, make_msgid, parsedate_to_datetime
from urllib.parse import quote_plus
SCRIPT_VERSION = "2026-09-08.mailsource.v5"
SCRIPT_VERSION = "2026-09-08.mailsource.v6"
DEFAULT_STATE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "broadcast_state.json")
DEFAULT_REPORT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "broadcast_report.json")
@@ -1841,13 +1841,21 @@ def run_interactive(cfg, templates, extra_vars, args, config_path):
f"(每 {args.watch_every} 封一次)"
f" 来源:params.ini [bounce] / 命令行,改值请编辑 params.ini")
# 发信账号来源:只有 params.ini [mail] 配齐了才提供切换
# 发信账号来源:只有 params.ini [mail] 配齐了才提供切换。
# 默认取 params.ini 已配置的 source(而不是硬编码 app),并且同时接受
# 数字选型——UI 里其它选项都是 1/2/3/4,只认 "own" 会让人输入 2 时静默回落。
if getattr(args, "_own_mail_ready", False):
cur = (getattr(args, "mail_source", None) or "").strip().lower()
default_src = cur if cur in ("app", "own") else "app"
src = ask("发信账号来源(app = conf/app.ini 的 SMTP;own = 程序自带 params.ini [mail])",
default_src).strip().lower()
args.mail_source = "own" if src == "own" else "app"
cur = (getattr(args, "mail_source", None)
or getattr(args, "_mail_source_default", "app") or "app").strip().lower()
if cur not in ("app", "own"):
cur = "app"
default_choice = "2" if cur == "own" else "1"
print("\n发信账号来源:")
print(" 1) conf/app.ini 的 SMTP(站点自己的邮箱)")
print(" 2) 程序自带 params.ini [mail] 的 SMTP")
src = ask("选择 [1/2]", default_choice).strip().lower()
args.mail_source = "own" if src in ("2", "own") else "app"
args._mail_source_chosen = True # 本轮显式选过,保存时才写回文件
print(f" 发信账号 = {'程序自带 params.ini [mail]' if args.mail_source == 'own' else 'conf/app.ini [mail]'}")
# 站点地址:只有完全没值时才问(值链已在 main 里兜底过 external_url)
@@ -1943,7 +1951,10 @@ def run_interactive(cfg, templates, extra_vars, args, config_path):
save_params(DEFAULT_PARAMS, config_path, site_url, box_prefix, extra_vars,
batch_size=getattr(args, "batch_size", 0) or 0,
smtp_idle_reconnect=getattr(args, "smtp_idle_reconnect", 30.0) or 30.0,
mail={"source": getattr(args, "mail_source", None) or "app"},
# 只有本轮在交互里显式选过来源才写回文件,否则保留原值:
# 命令行临时 --mail-source 不该被保存成永久配置
mail=({"source": args.mail_source}
if getattr(args, "_mail_source_chosen", False) else None),
bounce={
"watch_bounces": args.watch_bounces,
"watch_every": args.watch_every,
@@ -2199,11 +2210,13 @@ def main():
elif not args.interactive:
print("[警告] site_url 为空:{{site}} 与无个性域名用户的 {{box_link}} 将为空串")
# 程序自带 SMTP 是否已配齐(交互模式据此提供来源切换)
# 程序自带 SMTP 是否已配齐(交互模式据此提供来源切换);默认来源取自
# params.ini [mail] source,否则交互里回车会把已配好的 own 静默改成 app
_m = params.get("mail") or {}
args._own_mail_ready = bool((_m.get("smtp") or "").strip()
and (_m.get("account") or "").strip()
and (_m.get("password") or "").strip())
args._mail_source_default = (_m.get("source") or "app").strip().lower()
if args.interactive:
site_url, args.box_prefix, extra_vars = run_interactive(
@@ -2505,6 +2518,8 @@ def main():
f"(如 {sorted(watch_rate)[0]}:"
f"{watch_rate[sorted(watch_rate)[0]]['reason']})")
print(f"\n[发信账号] {cfg['mail_account']} @ {cfg['mail_smtp']}:{cfg['mail_port']}"
f"(来源:{'程序自带 params.ini [mail]' if mail_source == 'own' else 'conf/app.ini [mail]'})")
print(f"\n[发送中] 目标 {total} 封,每封间隔 {args.delay}s"
+ (f",每组间隔 {args.group_pause}s" if args.group_pause > 0 else "")
+ (f",每 {args.pause_every} 封暂停 {args.pause_for}s" if args.pause_every > 0 else "")