内容
<p align="center">
<img src="https://upload.wikimedia.org/wikipedia/commons/7/7e/Gmail_icon_%282020%29.svg" width="128" height="128" alt="Gmail Logo">
</p>
<h1 align="center">
🚀 Gmail 模板测试工具
</h1>
<h4 align="center">
测试、预览和完善 HTML 邮件模板的最快捷方式。
</h4>
<p align="center">
<a href="#license">
<img alt="许可证" src="https://img.shields.io/badge/License-MIT-blue.svg?style=for-the-badge&color=B5E8E0&logoColor=D9E0EE&labelColor=302D41">
</a>
<a href="https://github.com/Volcann/gmail-html-mailer/stargazers">
<img alt="星标" src="https://img.shields.io/github/stars/volcann/gmail-html-mailer?style=for-the-badge&logo=starship&color=B5E8E0&logoColor=D9E0EE&labelColor=302D41">
</a>
<a href="https://github.com/Volcann/gmail-html-mailer/graphs/contributors">
<img alt="贡献者" src="https://img.shields.io/github/contributors/volcann/gmail-html-mailer?style=for-the-badge&logo=gitbook&color=B5E8E0&logoColor=D9E0EE&labelColor=302D41">
</a>
</p>
停止浪费时间触发复杂的用户流程,只为了查看交易邮件在收件箱中的显示效果。`gmail-template-tester` 是一个自动化脚本,它解析 Jinja2 风格的 HTML 模板,智能模拟所需的数据,并将最终渲染结果直接发送到您的 Gmail 账户 — 自动覆盖每个条件分支。
现在支持 **Gemini CLI 集成**:直接从终端以纯英文传递模板路径,并将测试发送到收件箱,无需手动触摸 Python 脚本。Gemini CLI 使用令牌缓存减少 API 开销,让您的工作流程更高效。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 问题
传统方式测试邮件模板意味着:
1. 在数据库中播种假数据
2. 点击 5 步 UI 流程触发邮件
3. 检查邮件是否确实发送
4. 为每个需要覆盖的 `{% if %}` 分支重复上述步骤
该工具消除了所有这些步骤。**指向一个模板文件,它处理其余部分。**
## 影响
| 指标 | 之前 | 之后 |
|---|---|---|
| 测试单个模板的时间 | ~15 分钟 | ~5 秒 |
| 每次运行覆盖的分支 | 1(手动) | 所有(自动) |
| 需要的数据库设置 | 是 | 否 |
| 需要的 UI 流程 | 是 | 否 |
- **即时视觉反馈** — 在真实的 Gmail 客户端中查看 HTML 渲染效果
- **自动分支覆盖** — 每个 `{% if is_premium %}` 都会自动生成一个单独的邮件
- **零配置模拟** — `{{ first_name }}` 获得一个听起来真实的名字;`{{ price }}` 获得一个现实的价格
- **60% 的 QA 时间减少** 用于邮件模板验证
- **Gemini CLI 快捷方式** — 用纯英文描述模板路径,让 Gemini 调度测试
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## ⚡ 选择您的模式
> 选择适合您的工作流程。两种模式的作用相同 — 将渲染的邮件变体直接发送到您的收件箱。
<table>
<tr>
<td width="50%" align="center">
### 🐍 无 Gemini CLI
```bash
python main.py templates/welcome.html
python main.py templates/invoice.html --dry-run
```
➡️ [跳转到 Python 用法](#usage)
</td>
<td width="50%" align="center">
### 🤖 使用 Gemini CLI
```
> 测试 templates/welcome.html 并发送到我的收件箱
> 对 templates/ 文件夹中的所有模板进行 dry-run 并显示输出
```
➡️ [跳转到 Gemini CLI 集成](#gemini-cli-integration)
</td>
</tr>
</table>
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 📑 导航
- [先决条件](#prerequisites)
- [安装](#installation)
- [用法](#usage) *(Python CLI)*
- [Gemini CLI 集成](#gemini-cli-integration)
- [控制台输出](#console-output)
- [工作原理](#how-it-works)
- [项目结构](#project-structure)
- [配置参考](#configuration-reference)
- [CLI 参考](#cli-reference)
- [模板兼容性](#template-compatibility)
- [安全注意事项](#security-notes)
- [故障排除](#troubleshooting)
- [贡献](#contributing)
- [许可证](#license)
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 先决条件
- Python 3.7 或更高版本
- 一个 Gmail 账户
- 一个 [Gmail 应用密码](https://support.google.com/accounts/answer/185833)(16 个字符,从 Google 账户 → 安全 → 应用密码生成)
- *(可选)* [Gemini CLI](https://github.com/google-gemini/gemini-cli) 用于自然语言模板调度
> **注意:** 应用密码需要启用 Google 账户的 2-Step Verification。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 安装
**1. 克隆仓库**
```bash
git clone https://github.com/Volcann/gmail-html-mailer.git
cd gmail-html-mailer
```
**2. 安装依赖**
```bash
# 使用 uv(推荐)
uv sync
# 或使用标准 Python venv + pip
python3 -m venv .venv
source .venv/bin/activate
pip install .
```
**3. 配置环境**
在项目根目录创建 `.env` 文件:
```env# SMTP 配置
SENDER_EMAIL=your_email@gmail.com
APP_PASSWORD=your_16_character_app_password
RECEIVER_EMAIL=where_to_send_tests@gmail.com
# LLM 上下文生成(可选)
USE_GEMINI=false
GEMINI_API_KEY=your_gemini_api_key_here
```
> 将您的 `.env` 文件排除在版本控制之外。已包含 `.gitignore` 条目。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 用法
**基本用法**
```bash
python main.py my_template.html
```
**预览而不发送(dry-run)**
```bash
python main.py my_template.html --dry-run
```
dry-run 模式将所有变体渲染到 stdout 而不触及 SMTP。使用它进行本地审查、CI 检查或在发送之前检查模拟数据。
**示例**
```bash
# 测试欢迎邮件
python main.py templates/welcome.html
# 在 dry-run 模式下测试发票模板
python main.py templates/invoice.html --dry-run
# 测试通知邮件
python main.py templates/order_shipped.html
```
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 控制台输出
```text
╔══════════════════════════════════════════╗
║ 🚀 智能 HTML 模板邮件发送器 ║
╚══════════════════════════════════════════╝
────────────────────────────────────────────
模板:demo_template.html
────────────────────────────────────────────
ℹ 变量:19
ℹ 标志:2
ℹ 循环:1
ℹ 变体:4
⚠ dry-run 模式 — 不会发送邮件
────────────────────────────────────────────
调度中
────────────────────────────────────────────
✔ [1/4] ON:is_premium+show_banner
✔ [2/4] ON:is_premium | OFF:show_banner
✔ [3/4] ON:show_banner | OFF:is_premium
✔ [4/4] OFF:is_premium+show_banner
结果 sent=4 failed=0 time=0.01s
```
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## Gemini CLI 集成
您可以从 [Gemini CLI](https://github.com/google-gemini/gemini-cli) — Google 的开源终端 AI 代理 — 驱动此工具,而不是直接调用 Python。这在您想要一次测试多个模板或更喜欢对话式界面而不是记住 CLI 标志时很有用。
**为什么使用 Gemini CLI?**
Gemini CLI 在 Gemini 2.5 Pro 上运行,具有 1M 令牌上下文窗口,并使用自动令牌缓存避免在每次调用时重新处理重复的上下文。对于像这样的脚本 — 您在不同模板上重复执行相同的设置 — 该缓存使事情快速且廉价。
**安装 Gemini CLI**
```bash
npm install -g @google/gemini-cli
# 或无需安装:
npx @google/gemini-cli
```
**示例提示**
一旦进入项目目录的 Gemini CLI 会话:
```
> 测试 templates/welcome.html 并将其发送到我的收件箱
> 对 templates/invoice.html 进行 dry-run 并显示输出
> 测试 templates/ 文件夹中的所有模板
```
Gemini CLI 将解析模板路径,使用适当的參數运行 `main.py`,并报告结果 — 所有这些都无需您手动编写单个命令。
**无头/脚本化用法**
```bash
echo "测试 templates/order_shipped.html" | gemini --yolo
```
`--yolo` 标志允许 Gemini 在不提示确认的情况下执行 shell 命令 — 适用于 CI 管道。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 工作原理
该工具分为四个自主阶段:
### 1. 解析 AST
使用 Jinja2 抽象语法树映射模板中的每个令牌:
- `{{ variable }}` — 标识所有必需的变量
- `{% if condition %}` — 标识所有条件分支
- `{% for item in items %}` — 标识所有循环
### 2. 模拟数据
为检测到的每个变量生成语义上合理的假数据:
| 变量模式 | 生成的值 |
|---|---|
| `first_name`, `last_name`, `name` | 听起来真实的全名 |
| `email` | 现实的电子邮件地址 |
| `price`, `amount`, `cost` | 格式化的货币值 |
| `url`, `link` | 有效的 HTTPS URL |
| `date`, `timestamp` | 格式化的日期字符串 |
| `{% for item in items %}` | 2-4 个现实的项目数组 |
| 其他 | 使用标题大小写的键名作为备用 |
### 3. 生成排列组合
对于检测到的每个 `{% if %}`/`{% else %}` 块,该工具生成一个单独的渲染,其中条件设置为 `True`,另一个设置为 `False`。
具有 **2 个条件**的模板生成 **4 封邮件**(2² = 4)。
具有 **3 个条件**的模板生成 **8 封邮件**(2³ = 8)。
每个分支都被覆盖。没有任何隐藏的内容。
### 4. 通过 SMTP 发送
使用 Gmail 的 SMTP 服务器 (`smtp.gmail.com:587`) 和您的应用密码,通过 TLS 发送每个渲染的变体。所有发送操作都会记录到 stdout,并附带时间信息。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 项目结构
```
gmail-html-tester/
├── src/
│ └── gmail_html_tester/
│ ├── **init**.py
│ ├── cli.py # 入口点和 CLI 参数解析
│ ├── config.py # 配置加载和管理
│ ├── generator.py # 数据生成引擎
│ ├── parser.py # Jinja2 AST 遍历和令牌提取
│ ├── smtp.py # SMTP 连接和邮件调度
│ ├── utils.py # 核心共享实用函数
│ ├── mcp/ # 模型上下文协议(MCP)集成
│ │ ├── **init**.py
│ │ ├── app.py # MCP 应用程序初始化
│ │ ├── server.py # MCP 服务器核心逻辑
│ │ └── tools.py # 面向 LLM 的工具定义
│ └── mock/ # 模拟数据引擎
│ ├── **init**.py
│ ├── constants.py # 备用模式和语义常量
│ ├── mocks.py # Faker 数据生成逻辑
│ └── utils.py # 模拟辅助函数
├── templates/
│ └── email_template.html # 参考/示例 HTML 邮件模板
├── tests/ # 单元测试和集成测试
├── GEMINI.md # LLM 上下文/指令指南
├── LICENSE # 项目许可证
├── main.py # 根脚本便捷入口
├── mcp_server.py # MCP 服务器专用入口
├── pyproject.toml # 项目元数据和依赖项(PEP 621)
├── README.md # 项目文档
└── uv.lock # 由 uv 管理的锁定依赖树
```
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 配置参考
应用程序依赖环境变量进行身份验证、SMTP 路由和 LLM 功能。在下面的参考基础上创建 `.env` 文件:
### 环境变量
| 变量 | 必需 | 默认值 | 描述 |
| :--- | :--- | :--- | :--- |
| `SENDER_EMAIL` | **是** | *无* | 用于调度测试邮件的 Gmail 地址。 |
| `APP_PASSWORD` | **是** | *无* | 16 个字符的 Google 应用密码(不是您的标准密码)。 |
| `RECEIVER_EMAIL` | **是** | *无* | 测试邮件变体发送到的目标地址。 |
| `USE_GEMINI` | 否 | `false` | 将其设置为 `true` 以启用模板的 LLM 驱动上下文生成。 |
| `GEMINI_API_KEY` | 否* | *无* | Gemini 的 API 密钥。 *如果 `USE_GEMINI` 设置为 `true`,则需要此项。 |
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## CLI 参考
```
python main.py <template_file> [选项]
参数:
template_file 您的 Jinja2 HTML 模板的路径
选项:
--dry-run 将所有变体渲染到 stdout 而不发送
--help 显示此帮助消息
```
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 模板兼容性
该工具支持标准的 Jinja2 语法:
```html
<!-- 变量 -->
Hello {{ first_name }},
<!-- 条件语句 -->
{% if is_premium %}
<p>您的高级计划于 {{ renewal_date }} 续期。</p>
{% else %}
<p><a href="{{ upgrade_url }}">升级到高级版 →</a></p>
{% endif %}
<!-- 循环 -->
{% for item in order_items %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.price }}</td>
</tr>
{% endfor -->
```
> 嵌套的条件语句和嵌套的循环均受支持。每个嵌套级别都会复合排列计数,因此具有 4+ 个条件的模板可能会生成大量变体。使用 `--dry-run` 在发送前检查。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 安全注意事项
- **应用密码不是您的账户密码。** 它们是作用域凭证,可以在任何时候通过 Google 账户 → 安全 → 应用密码撤销。
- 永远不要提交您的 `.env` 文件。包含的 `.gitignore` 默认将其排除。
- 该工具通过 TLS (`STARTTLS`) 连接 — 凭证永远不会以纯文本传输。
- 测试邮件仅发送到您指定的 `RECEIVER_EMAIL` 地址,而不管模板中存在任何电子邮件地址。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 故障排除
**`SMTPAuthenticationError`**
您的应用密码可能不正确,或者发送者账户未启用 2-Step Verification。从 Google 账户 → 安全 → 应用密码生成应用密码。
**`UndefinedError: 'X' is undefined`**
模拟器无法匹配变量名。备用方案是变量名本身 — 如果您看到原始变量名输出,则使用备用方案。这是预期行为。
**`ConnectionRefusedError`**
检查您的网络连接并确认 `smtp.gmail.com` 在 587 端口可达。一些企业防火墙会阻止传出的 SMTP。
**模板生成太多变体**
具有许多条件语句的模板会生成指数更多的邮件。使用 `--dry-run` 检查计数后再发送。考虑将具有多个独立条件的模板分成单独的文件。
**Gemini CLI 未正确运行脚本**
确保您在项目目录运行 Gemini CLI 会话,以便它可以解析相对模板路径。如果 Gemini 停止执行,请添加 `--yolo` 跳过确认提示。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="http://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 贡献
1. 复刻仓库
2. 创建一个功能分支 (`git checkout -b feature/your-feature`)
3. 提交您的更改 (`git commit -m 'Add your feature'`)
4. 将其推送到分支 (`git push origin feature/your-feature`)
5. 打开拉取请求
请保持代码库的注释免费作为一种风格 — 代码即是文档。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
## 许可证
MIT 许可证。详见 `LICENSE`。
<img src="https://img.shields.io/badge/-007ACC?style=flat&line-height=1&width=1000" width="100%" height="3px">
*Built to save developers time, frustration, and inbox clutter.*
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器