From fe1b21fe06291f3790a51d5a9ceef2bfc6039faa Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 21 Jul 2025 20:33:39 +0800 Subject: [PATCH] . --- email_ui.py | 47 ++++++++++++++++++++++++-------------------- send_email_module.py | 2 +- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/email_ui.py b/email_ui.py index 9e8c491..6dac013 100644 --- a/email_ui.py +++ b/email_ui.py @@ -1,15 +1,15 @@ # -*- coding: utf-8 -*- """ -email_ui.py — 一键群发工具 (强化校验版) --------------------------------------- +email_ui.py — 一键群发工具 (强化校验版,支持自定义默认称呼) +------------------------------------------------------------ 运行: python email_ui.py """ -import os, logging, re, random +import os, logging, re from datetime import datetime import gradio as gr from send_email_module import send_email -EMAIL_CONFIG_KEY = "default" # 对应 config/default.json +EMAIL_CONFIG_KEY = "default" LOG_FILE = "email_send_log.txt" logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") @@ -17,7 +17,7 @@ logging.basicConfig(level=logging.INFO, EMAIL_RE = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$") # 简易邮箱正则 -# -------------------- 工具 -------------------- +# ---------- 工具 ---------- def _load_template(file_obj): if file_obj is None: return "" @@ -25,36 +25,31 @@ def _load_template(file_obj): return f.read() -def _error(msg): - """生成统一的红字提示 + 让 state 为空 -> Send 仍锁定""" +def _error(msg): # 统一红字提示 return gr.update(value=f"

❌ {msg}

"), None -# -------------------- 预览 -------------------- +# ---------- 预览 ---------- def preview_email(to_addrs, subject, html_file, language, - want_receipt, want_read_receipt): - # 0. 模板存在 + want_receipt, want_read_receipt, default_name): # ✨ new tpl = _load_template(html_file) if not tpl: return _error("请先上传 HTML 模板") - # 1. 收件人非空且格式合法 raw_addrs = [a.strip() for a in to_addrs.split(",") if a.strip()] if not raw_addrs: return _error("收件人邮箱不能为空") if invalid := [a for a in raw_addrs if not EMAIL_RE.match(a)]: return _error(f"邮箱格式非法: {', '.join(invalid)}") - # 2. 主题非空 if not subject.strip(): return _error("主题不能为空") - # 3. 模板至少包含 {{recipient_name}} if "{{recipient_name}}" not in tpl: return _error("模板缺少 {{recipient_name}} 占位符") - # ---- 全部通过,生成预览 ---- - preview = (tpl.replace("{{recipient_name}}", "there") + # 生成预览,用用户填写的 default_name(留空时仍展示 there) + preview = (tpl.replace("{{recipient_name}}", default_name or "there") .replace("{{recipient_email}}", "example@example.com") .replace("{{encoded_recipient_email}}", "ENCODED_EXAMPLE") .replace("{{timestamp}}", datetime.now().isoformat())) @@ -66,18 +61,24 @@ def preview_email(to_addrs, subject, html_file, language, "language": language, "want_receipt": want_receipt, "want_read_receipt": want_read_receipt, + "default_name": default_name.strip(), # ✨ new } return gr.update(value=preview), state -# -------------------- 发送 -------------------- +# ---------- 发送 ---------- def send_emails(state): if not state: return "⚠️ 请先 Preview 成功后再发送。" + out_lines = [] for addr in state["addresses"]: res = send_email( - EMAIL_CONFIG_KEY, addr, state["subject"], state["template"], "", + EMAIL_CONFIG_KEY, + addr, + state["subject"], + state["template"], + state["default_name"], # ✨ new (可为空串) request_receipt=state["want_receipt"], request_read_receipt=state["want_read_receipt"], language=state["language"], @@ -90,7 +91,7 @@ def send_emails(state): return "
".join(out_lines).replace("\n", "
") -# -------------------- Gradio UI -------------------- +# ---------- Gradio UI ---------- with gr.Blocks(css=".gr-button {min-width:8rem}") as demo: gr.Markdown("## ✉️ 简易 EDM 群发工具") @@ -98,9 +99,13 @@ with gr.Blocks(css=".gr-button {min-width:8rem}") as demo: subj = gr.Textbox(label="主题", placeholder="Subject here") tpl = gr.File(label="上传 HTML 模板") lang = gr.Radio(["english", "chinese"], value="chinese", label="语言") + default_name = gr.Textbox( # ✨ new + label="默认称呼(留空=老板/there)", value="" + ) + with gr.Row(): - rcpt = gr.Checkbox(label="投递回执") - read_r = gr.Checkbox(label="已读回执") + rcpt = gr.Checkbox(label="投递回执") + read_r = gr.Checkbox(label="已读回执") preview_btn = gr.Button("Preview ⬇️") send_btn = gr.Button("Send (确认发送) ✈️", interactive=False) @@ -109,7 +114,7 @@ with gr.Blocks(css=".gr-button {min-width:8rem}") as demo: preview_btn.click( preview_email, - [addrs, subj, tpl, lang, rcpt, read_r], + [addrs, subj, tpl, lang, rcpt, read_r, default_name], # ✨ new [out_html, state_box] ).then( lambda s: gr.update(interactive=s is not None), diff --git a/send_email_module.py b/send_email_module.py index a9e73b3..3037dcf 100644 --- a/send_email_module.py +++ b/send_email_module.py @@ -84,7 +84,7 @@ def send_email(key, to_address, subject, body_template, recipient_name, msg['Subject'] = subject if not recipient_name: - recipient_name = "there" + recipient_name = "老板" if language == "chinese" else "there" encoded_email = xor_encode(to_address, 0xAE) body = (