From 35e9a7231aae7388443d9502d918c2bd06ba0057 Mon Sep 17 00:00:00 2001 From: tamakyi Date: Tue, 8 Sep 2026 01:18:40 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8F=91=E4=BF=A1=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E6=9D=A5=E6=BA=90=E9=80=89=E4=BA=86=20own=20=E5=8D=B4?= =?UTF-8?q?=E4=BB=8D=E7=94=A8=20app.ini=20=E5=8F=91=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 复现确认的三处缺陷(用户报: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 项断言 --- README.md | 4 +++- broadcast.py | 33 ++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index d24c0dd..dce473e 100644 --- a/README.md +++ b/README.md @@ -275,7 +275,9 @@ conf/app.ini 路径的解析优先级: skip_tls_verify = 0 临时切换(优先级高于 params.ini):`--mail-source own` / `--mail-source app` - 交互模式里若 [mail] 配齐了,会多问一次选哪个来源。 + 交互模式里若 [mail] 配齐了,会多问一次(`1` = app.ini,`2` = 程序自带; + 默认值取 params.ini 已配置的 source,直接回车即沿用)。 + 只有交互里显式选过才会写回 params.ini;命令行临时切换不会被保存成永久配置。 安全提醒: - params.ini 会被 git 跟踪,**不要把密码明文写进去**;用 `env:变量名` diff --git a/broadcast.py b/broadcast.py index 00733ae..3b6b9b0 100644 --- a/broadcast.py +++ b/broadcast.py @@ -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 "")