|
|
||
|---|---|---|
| assets | ||
| .gitignore | ||
| README.md | ||
| bulk_invite_mailer.py | ||
| requirements.txt | ||
| run_tool.bat | ||
| start_gui.command | ||
| start_gui.vbs | ||
| tests_mailer.py | ||
README.md
Bulk Invitation Mailer
批量发送个性化邮件工具。从 Excel 或 CSV 读取收件人信息,为每位收件人单独生成邮件;支持发件人配置、变量替换、HTML 正文、附件、演练预览、发送日志和断点续发。
如果以演练模式运行,不会连接 SMTP 服务器发送真实邮件。
功能
- 支持
.xlsx、.xlsm和 UTF-8 CSV 收件人文件。 - 自动识别姓名、邮箱列;其他列可直接用于模板变量。
- 按收件人分别生成标题、正文和附件路径,例如
{{姓名}}、{{公司}}。 - 支持根据邀请函底图和 JSON 配置,将表格字段绘制为个性化邀请函附件。
- 支持纯文本和 HTML 正文;检测到 HTML 标签时会自动按 HTML 邮件生成。
- 支持多个 SMTP 发件人配置,以及 SSL、STARTTLS 和无加密连接。
- 演练模式为每位收件人生成
.eml预览文件,不发送邮件。 - 自动跳过重复邮箱、已完成记录;发送过程可暂停、继续或停止。
- 记录每次任务的发送日志、状态表、预览文件和重试信息。
环境与安装
需要 Python 3.9 或更高版本。Excel 读取依赖 openpyxl;图形界面使用 Python 自带的 Tkinter。
pip install -r requirements.txt
Windows PowerShell 可使用:
pip install -r requirements.txt
启动图形界面
Windows 下可双击 start_gui.vbs;需要看到命令行输出时运行:
python bulk_invite_mailer.py --gui
macOS 下首次使用时,在项目目录执行:
chmod +x start_gui.command
之后可双击 start_gui.command 启动。
不带命令行参数直接运行 python bulk_invite_mailer.py 也会打开图形界面。
图形界面使用流程
- 选择收件人表格,点击“读取并预览”。
- 确认姓名列和邮箱列;程序会标记重复邮箱和可能无效的邮箱格式。
- 选择已有发件人配置,或填写 SMTP 信息后保存为新配置。
- 填写标题、正文、HTML 选项、附件路径和发送间隔。
- 先保持“演练模式”生成预览;确认无误后关闭演练模式,再开始真实发送。
开始前会显示发送模式、发件人、收件人数、标题模板和首封邮件标题的确认窗口。可在界面中生成当前收件人的 HTML 与 .eml 预览,或在任务结束后直接打开日志和输出目录。
收件人表格
首行必须是列名。邮箱列会从以下名称中自动识别:邮箱、电子邮箱、邮件、收件邮箱、邮箱地址、email、e-mail、mail。姓名列也会自动识别 姓名、名字、收件人、客户姓名、嘉宾姓名 和 name。
姓名,邮箱,公司,场次
张三,zhangsan@example.com,示例公司,上海场
李四,lisi@example.com,示例公司,北京场
正文、标题和附件路径都能引用任意列:
{{姓名}},您好:
诚邀您参加 {{公司}} 的 {{场次}} 活动。
附件支持多个路径,以英文分号分隔:
attachments/{{姓名}}.pdf;attachments/活动说明.pdf
附件路径不存在时,当前收件人会暂停等待处理,不会静默跳过。
个性化邀请函附件
勾选“附加个性化邀请函”,选择 JSON 配置文件后,程序会在开始任务前为每位收件人生成邀请函,并作为普通附件附加到邮件。生成过程在连接 SMTP 前完成;姓名、字体、底图或像素尺寸不符合配置时,任务不会开始发送。
配置文件可放在收件人表格同目录。当前示例位于 app_data/recipients/06-发邀请函/邀请函配置.json:
{
"template_image": "邀请函底图.jpg",
"expected_image_size": [2568, 5511],
"output": {
"format": "pdf",
"file_name_template": "{{真实姓名}}邀请函"
},
"layers": [
{
"text_template": "{{真实姓名}}",
"position": { "x": 510, "y": 3030 },
"anchor": "mm",
"max_width": 450,
"font": {
"path": "%WINDIR%/Fonts/msyh.ttc",
"size": 92,
"min_size": 48
},
"color": "#382066"
}
]
}
position 使用底图原始像素坐标;anchor: "mm" 表示文字中心对准坐标。max_width 限制文字宽度,姓名过长时会在 size 和 min_size 之间自动缩小。每次任务会在输出目录生成 invitations/ 和所用的 invitation_config.json 副本。
发件人配置与隐私
发件人配置保存在 app_data/config/senders.csv,包含 SMTP 地址、端口、安全方式、发件人信息和授权码或密码。授权凭据以明文保存在本机,请妥善保护该目录。
界面设置保存在 app_data/config/mailer_config.json。默认运行数据目录如下:
app_data/
config/
mailer_config.json
senders.csv
recipients/
previews/
current_email_preview.html
current_email_preview.eml
outputs/
20260723_100000/
send_log.csv
send_status.csv
previews/
app_data/ 已被 Git 忽略。不要强制加入、压缩或上传其中的配置、收件人表格、预览和日志。
发送行为与日志
- 演练模式:为每位收件人生成
.eml文件,状态记为PREVIEWED。 - 真实发送:邮件成功提交给 SMTP 服务器后,状态记为
DONE。 - 同一次任务中,忽略大小写和首尾空白后相同的邮箱只处理首次出现的记录,后续记录标为
SKIPPED_DUPLICATE。 - 使用同一个输出目录再次运行时,已完成的记录会被跳过;可通过
--output-dir指定该目录以继续未完成任务。 - GUI 支持暂停、继续和停止。SMTP 临时错误可选择自动重试;其他发送错误会暂停在当前收件人处等待继续。
- 每次任务会写入
send_log.csv与send_status.csv;演练模式还会在previews/生成邮件文件。
日志记录收件人邮箱和发送状态,输出目录同样属于敏感数据。
命令行
列出已保存的发件人配置:
python3 bulk_invite_mailer.py --list-senders
保存发件人配置。推荐从环境变量读取授权码,避免把密码写入终端历史:
export SMTP_PASSWORD='授权码'
python3 bulk_invite_mailer.py \
--smtp-host smtp.example.com \
--smtp-port 465 \
--security ssl \
--sender sender@example.com \
--sender-name '活动组' \
--password-env SMTP_PASSWORD \
--save-sender-profile '默认发件人'
演练模式(默认,不会发送):
python3 bulk_invite_mailer.py \
--excel recipients.xlsx \
--sender-profile '默认发件人' \
--subject '{{姓名}},活动邀请' \
--body-file invite.html \
--html
真实发送:
python3 bulk_invite_mailer.py \
--excel recipients.xlsx \
--sender-profile '默认发件人' \
--subject '{{姓名}},活动邀请' \
--body-file invite.html \
--html \
--attachments 'attachments/{{姓名}}.pdf' \
--send
常用参数:
| 参数 | 用途 |
|---|---|
--sheet |
指定 Excel 工作表;默认读取活动工作表。 |
--name-column、--email-column |
手动指定姓名列、邮箱列。 |
--data-dir |
指定配置、收件人和默认输出目录;默认 ./app_data。 |
--senders-csv |
指定发件人配置 CSV。 |
--password-env |
授权码所在环境变量;默认 SMTP_PASSWORD。 |
--output-dir |
指定日志、状态表和演练预览目录。 |
--delay |
真实发送时两封邮件之间的等待秒数;默认 1.0。 |
--auto-retry-seconds |
命令行发生错误后的重试等待秒数;默认 180。 |
--send |
开启真实发送;省略时始终为演练模式。 |
查看全部参数:
python3 bulk_invite_mailer.py --help
测试
python3 -m unittest tests_mailer.py