Files
cloudflare_temp_email/vitepress-docs/docs/zh/guide/config-send-mail.md
Dream Hunter 3bcc0c19ce fix: clarify account and address terminology (#1113)
* fix: clarify account and address terminology

* fix: narrow account and address terminology changes

* fix: simplify mailbox settings label

* fix: align mailbox translations and send docs
2026-08-19 13:31:55 +08:00

197 lines
7.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 配置发送邮件
::: tip 推荐方案
推荐使用 Cloudflare `send_email` binding 作为默认发信通道。绑定 `SEND_MAIL` 并完成 Email Routing onboarding 后,即可直接向任意外部地址发信。
Workers Paid 每月含 3,000 封,超出部分 $0.35 / 1000 封。
:::
## 发信通道优先级
每次 `/api/send_mail` 请求按如下顺序匹配通道,**命中即发送**
| 顺序 | 条件 | 通道 | 扣 balance |
|------|------|------|-----------|
| 1 | `SEND_MAIL` 已绑定 **且** 收件人在 `verifiedAddressList` | Cloudflare binding兼容模式 | 否 |
| 2 | `RESEND_TOKEN``RESEND_TOKEN_<DOMAIN>` 已配置 | Resend API | 是 |
| 3 | `SMTP_CONFIG` 含当前域名配置 | worker-mailer SMTP | 是 |
| 4 | `SEND_MAIL` 已绑定(以上均未命中) | **Cloudflare binding推荐主通道** | 是 |
| — | 以上均未命中 | 抛错 | — |
> [!NOTE]
> binding 发信失败会直接报错。
## 使用 Cloudflare `send_email` binding推荐
仅 CLI 部署时使用,在 `wrangler.toml` 中添加:
```toml
# 通过 Cloudflare send_email binding 发送邮件
send_email = [
{ name = "SEND_MAIL" },
]
```
> [!warning] 重要
> 绑定名必须为 `SEND_MAIL`,与 Cloudflare 官方文档示例中的 `SEND_EMAIL` 不同。
完成下列步骤后即可直接向任意外部地址发信:
1. 在 Cloudflare Dashboard 给对应域名开启 Email Routing 并完成 onboarding
2. `wrangler.toml` 添加上述 `send_email` 绑定
3. 部署 Worker
无需配置任何额外的 env var。
## 使用 Resend 发送邮件
注册 `https://resend.com/domains` 根据提示添加 DNS 记录,
> [!WARNING] Cloudflare 上 DNS 记录的代理状态
> Resend 域名验证的 CNAME 记录**必须设置为 仅 DNS**(灰云),在
> Cloudflare DNS 控制面板中代理(橙云)记录会阻止 Resend
> 完成验证,且一次失败的尝试可能需要数小时才能重试。
> 参见 [#515](https://github.com/dreamhunter2333/cloudflare_temp_email/issues/515)。
`API KEYS` 页面创建 `api key`
然后执行下面的命令,将 `RESEND_TOKEN` 添加到 secrets 中
> [!NOTE]
> 如果你觉得麻烦,也可以直接明文放在 `wrangler.toml` 中 `[vars]` 下面,但是不推荐这样做
如果你是通过 UI 部署的,可以在 Cloudflare 的 UI 界面中添加到 `Variables and Secrets` 下面
```bash
# 切换到 worker 目录
cd worker
wrangler secret put RESEND_TOKEN
```
如果你有多个域名,对应不同的 `api key`,可以在 `wrangler.toml` 中添加多个 secret, 名称为 `RESEND_TOKEN_` + `<. 换成 _ 的 大写域名>`,例如
```bash
wrangler secret put RESEND_TOKEN_XXX_COM
wrangler secret put RESEND_TOKEN_DREAMHUNTER2333_XYZ
```
## 使用 SMTP 发送邮件
`SMTP_CONFIG` 的格式如下,**key 必须是你自己的发信域名**value 为 SMTP 配置。
SMTP 配置格式详情可以参考 [zou-yu/worker-mailer](https://github.com/zou-yu/worker-mailer/blob/main/README_zh-CN.md)
> [!warning] 重要
> JSON 中的 key如下面示例中的 `your-domain.com`)必须替换为**你自己的域名**,即 `DOMAINS` 变量中配置的域名。
> 这是最常见的配置错误之一,请勿直接复制示例中的域名。
```json
{
"your-domain.com": {
"host": "smtp.example.com",
"port": 465,
"secure": true,
"authType": [
"plain",
"login"
],
"credentials": {
"username": "your-smtp-username",
"password": "your-smtp-password"
}
}
}
```
**字段说明:**
| 字段 | 说明 |
|------|------|
| key`your-domain.com` | 你的发信域名,必须与 `DOMAINS` 中配置的域名一致 |
| `host` | SMTP 服务器地址,如 `smtp.mailgun.org``smtp.gmail.com` 或你自建的 SMTP 服务器地址 |
| `port` | SMTP 端口,通常 `465`SSL`587`STARTTLS |
| `secure` | 是否使用 SSL/TLS端口 465 时设为 `true`,端口 587 时设为 `false` |
| `authType` | 认证方式,一般使用 `["plain", "login"]` |
| `credentials.username` | SMTP 服务器的登录用户名 |
| `credentials.password` | SMTP 服务器的登录密码 |
如果你有**多个域名**使用不同的 SMTP 服务,在同一个 JSON 中添加多个 key 即可:
```json
{
"domain-a.com": {
"host": "smtp.mailgun.org",
"port": 465,
"secure": true,
"authType": ["plain", "login"],
"credentials": { "username": "user@domain-a.com", "password": "xxx" }
},
"domain-b.com": {
"host": "smtp.gmail.com",
"port": 465,
"secure": true,
"authType": ["plain", "login"],
"credentials": { "username": "user@gmail.com", "password": "app-password" }
}
}
```
然后执行下面的命令,将 `SMTP_CONFIG` 添加到 secrets 中
> [!NOTE]
> 如果你觉得麻烦,也可以直接明文放在 `wrangler.toml` 中 `[vars]` 下面,但是不推荐这样做
如果你是通过 UI 部署的,可以在 Cloudflare 的 UI 界面中添加到 `Variables and Secrets` 下面
```bash
# 切换到 worker 目录
cd worker
wrangler secret put SMTP_CONFIG
```
## 用户账号、邮箱地址与发信权限
这三个概念相互关联,但不是同一个对象:
| 概念 | 说明 |
|------|------|
| 用户账号 | 用于登录用户中心,可绑定和管理多个邮箱地址;用户账号的登录邮箱本身不等于用于收发信的邮箱地址 |
| 邮箱地址 | 实际收信和发信的身份,例如 `name@example.com`前端首页当前选中的地址由该地址的凭证Address JWT认证 |
| 发信权限与额度 | `address_sender` 中的权限和额度以**邮箱地址**为单位独立管理;`NO_LIMIT_SEND_ROLE` 配置的用户角色可以绕过地址额度检查 |
因此,同一用户账号绑定的多个邮箱地址不会共享发信权限或余额。为某个地址申请发信权限时:
1. 先在前端切换到需要发信的邮箱地址
2. 打开「发送邮件」页
3. 点击「申请权限」
申请只作用于当时选中的邮箱地址。切换到另一个地址后,需要查看该地址自己的额度,并在需要时单独申请。邮箱地址不必绑定用户账号也可以独立持有发信权限。
## 发信余额机制
邮箱地址发送邮件需要有该地址的发信余额。余额机制如下:
1. **自动初始化默认额度**:当 `DEFAULT_SEND_BALANCE > 0` 时,用户打开前端发信页或第一次调用发信接口时,系统会自动为该地址初始化默认额度
2. **手动申请**:如果 `DEFAULT_SEND_BALANCE = 0`,使用者可以在前端切换到目标邮箱地址并点击「申请权限」,为当前地址创建待管理员处理的发信权限记录
3. **无限制发送**:以下方式可以跳过余额检查:
- 在 admin 后台将地址加入「无限制发送地址列表」
- 配置 `NO_LIMIT_SEND_ROLE` 环境变量,指定可以无限发送的用户角色
> [!NOTE]
> `DEFAULT_SEND_BALANCE` 仅在地址尚无 `address_sender` 记录时自动插入初始额度(`ON CONFLICT DO NOTHING`已有记录包括管理员禁用或手动设置的行一律保持原样runtime 不会修改;历史异常或被禁用的地址需由管理员在后台手动启用并设置余额。
>
> 第 1 层 `verifiedAddressList` 命中时不扣余额,但同样计入发信额度;第 2/3/4 层统一扣 balance。
>
> 发信额度对**全部**发信渠道生效admin 发信接口也会一起计入。
>
> 每日和每月额度按 **UTC** 时间窗口计算。
>
> 当前额度实现属于 **soft guard**,适合日常额度控制;在数据库异常或高并发场景下,它不适合作为绝对严格的成本硬闸。
## 给 Cloudflare 上已认证的转发邮箱发送邮件
适合未完成 Email Routing onboarding 的域名,或 Workers 免费版。
只有收件人在 admin 后台的 `已验证地址列表` 中时,才会通过 `SEND_MAIL` binding 发信。