feat(邮件通知): 重构邮件通知系统并增加配置选项
- 移除 Cloudflare Email 绑定,改为支持外部邮件网关 - 新增邮件通知全局开关及管理员/用户通知独立配置 - 在管理后台添加邮件通知配置界面 - 优化邮件发送逻辑,增加错误处理和日志记录 - 更新相关文档说明
This commit is contained in:
@@ -30,7 +30,6 @@ onMounted(async () => {
|
||||
const comments = new window.CWDComments({
|
||||
el: commentsRoot.value,
|
||||
apiBaseUrl,
|
||||
postSlug: window.location.pathname,
|
||||
});
|
||||
|
||||
comments.mount();
|
||||
|
||||
@@ -14,13 +14,12 @@
|
||||
|
||||
### 查询参数
|
||||
|
||||
| 名称 | 位置 | 类型 | 必填 | 说明 |
|
||||
| -------------- | ------ | ------- | ---- | -------------------------------------------------------------------- |
|
||||
| `post_slug` | query | string | 是 | 文章唯一标识符,与前端配置中的 `postSlug` 保持一致 |
|
||||
| `page` | query | integer | 否 | 页码,默认 `1` |
|
||||
| `limit` | query | integer | 否 | 每页数量,默认 `20`,最大 `50` |
|
||||
| `nested` | query | string | 否 | 是否返回嵌套结构,默认 `'true'` |
|
||||
| `avatar_prefix`| query | string | 否 | 覆盖头像地址前缀,优先级高于服务端设置和前端配置 |
|
||||
| 名称 | 位置 | 类型 | 必填 | 说明 |
|
||||
| --------------- | ----- | ------- | ---- | --------------------------------------------------- |
|
||||
| `post_slug` | query | string | 是 | `window.location.origin + window.location.pathname` |
|
||||
| `page` | query | integer | 否 | 页码,默认 `1` |
|
||||
| `limit` | query | integer | 否 | 每页数量,默认 `20`,最大 `50` |
|
||||
| `nested` | query | string | 否 | 是否返回嵌套结构,默认 `'true'` |
|
||||
|
||||
### 成功响应
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* 拥有一个 Node.js 运行环境,版本 >= 22(本地部署需要)
|
||||
* 拥有一个域名并托管在 Cloudflare 上(这个不是必须项,但可以提高国内访问速度,也更方便)
|
||||
|
||||
后端项目目录为 `cwd-comments-api/`,基于 Cloudflare Workers + D1 + KV 实现。
|
||||
后端项目目录为 `/cwd-comments-api/`,基于 Cloudflare Workers + D1 + KV 实现。
|
||||
|
||||
## 部署
|
||||
|
||||
@@ -48,11 +48,11 @@ npm install
|
||||
|
||||
```jsonc
|
||||
"d1_databases": [
|
||||
{
|
||||
"binding": "CWD_DB",
|
||||
"database_name": "CWD_DB",
|
||||
"database_id": "xxxxxx" // D1 数据库 ID
|
||||
}
|
||||
{
|
||||
"binding": "CWD_DB",
|
||||
"database_name": "CWD_DB",
|
||||
"database_id": "xxxxxx" // D1 数据库 ID
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@@ -68,10 +68,10 @@ npm install
|
||||
|
||||
```jsonc
|
||||
"kv_namespaces": [
|
||||
{
|
||||
"binding": "CWD_AUTH_KV",
|
||||
"id": "xxxxxxx" // KV 存储 ID
|
||||
}
|
||||
{
|
||||
"binding": "CWD_AUTH_KV",
|
||||
"id": "xxxxxxx" // KV 存储 ID
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@@ -155,7 +155,7 @@ wrangler dev
|
||||
- `binding` 必须为 `CWD_DB`,与代码中的 `env.CWD_DB` 一致。
|
||||
- `database_name` 和 `database_id` 根据 Cloudflare 实际创建结果填写。
|
||||
|
||||
数据库结构定义见 [`schemas/comment.sql`](../../cwd-comments-api/schemas/comment.sql)。
|
||||
数据库结构定义见 `schemas/comment.sql`。
|
||||
|
||||
### KV 存储
|
||||
|
||||
@@ -191,15 +191,15 @@ KV 主要用于:
|
||||
|
||||
所需环境变量如下表所示。
|
||||
|
||||
| 名称 | 类型 | 描述 |
|
||||
| ----------------- | ----------- | -------------------------------------------------------------------- |
|
||||
| `CWD_DB` | D1 绑定 | 评论数据存储数据库 |
|
||||
| `CWD_AUTH_KV` | KV 绑定 | 管理员登录 Token、登录尝试计数等 |
|
||||
| `ALLOW_ORIGIN` | string | 预留的允许跨域来源配置,目前实现中仍使用 `*` |
|
||||
| `CF_FROM_EMAIL` | string | 作为发件人显示的邮箱地址(需在 Cloudflare Email 路由中预先配置)选填 |
|
||||
| `SEND_EMAIL` | send_email | Cloudflare Email 发送绑定,供通知邮件使用 |
|
||||
| `ADMIN_NAME` | string | 管理员登录名称 |
|
||||
| `ADMIN_PASSWORD` | string | 管理员登录密码 |
|
||||
| 名称 | 类型 | 描述 |
|
||||
| ------------------ | ----------- | --------------------------------------------------------------------- |
|
||||
| `CWD_DB` | D1 绑定 | 评论数据存储数据库 |
|
||||
| `CWD_AUTH_KV` | KV 绑定 | 管理员登录 Token、登录尝试计数等 |
|
||||
| `ALLOW_ORIGIN` | string | 预留的允许跨域来源配置,目前实现中仍使用 `*` |
|
||||
| `MAIL_GATEWAY_URL` | string | 外部邮件网关 HTTP 地址,由此网关转发到 QQ SMTP 或其他邮箱服务(可选) |
|
||||
| `MAIL_GATEWAY_TOKEN` | string | 调用外部邮件网关使用的鉴权 Token(可选) |
|
||||
| `ADMIN_NAME` | string | 管理员登录名称 |
|
||||
| `ADMIN_PASSWORD` | string | 管理员登录密码 |
|
||||
|
||||
在 Cloudflare 控制台中配置方式:
|
||||
|
||||
@@ -207,96 +207,3 @@ KV 主要用于:
|
||||
- 在 `Environment Variables` 中添加 `ADMIN_NAME`、`ADMIN_PASSWORD` 等变量
|
||||
- 在 `D1 Databases` 中绑定 `CWD_DB`
|
||||
- 在 `KV Namespaces` 中绑定 `CWD_AUTH_KV`
|
||||
- 在 `Email` 中绑定 `SEND_EMAIL`(如需启用邮件通知)
|
||||
|
||||
**注:** 需要在 Cloudflare 控制面板中为 Email 路由开启发送权限并配置发件人域和地址,并在 `wrangler.jsonc` 中为 Worker 添加 `send_email` 绑定,以便在代码中通过 `env.SEND_EMAIL.send()` 直接发信。
|
||||
|
||||
## 发信设置
|
||||
|
||||
手动在 `wrangler.jsonc` 中添加 `send_email` 绑定,以便在代码中通过 `env.SEND_EMAIL.send()` 直接发信。
|
||||
|
||||
```jsonc
|
||||
{
|
||||
...
|
||||
"send_email": [
|
||||
{
|
||||
"name": "SEND_EMAIL"
|
||||
}
|
||||
],
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
参数 `CF_FROM_EMAIL` 这里填写的邮箱是你绑定域名后创建的 Email 路由,两者需保持一致。
|
||||
|
||||
## 中间件配置说明
|
||||
|
||||
后端使用 Hono 框架,在入口文件中统一配置了 CORS 和管理员认证中间件。
|
||||
|
||||
入口文件位置:[`cwd-comments-api/src/index.ts`](../../cwd-comments-api/src/index.ts)
|
||||
|
||||
### CORS 中间件
|
||||
|
||||
当前实现位于 [`cwd-comments-api/src/utils/cors.ts`](../../cwd-comments-api/src/utils/cors.ts),对 `/api/*` 和 `/admin/*` 路径统一应用:
|
||||
|
||||
- 允许来源:`*`
|
||||
- 允许方法:`GET, POST, PUT, DELETE, OPTIONS`
|
||||
- 允许请求头:`Content-Type, Authorization`
|
||||
- 暴露响应头:`Content-Length`
|
||||
- 不允许携带凭证(`credentials: false`)
|
||||
|
||||
这意味着:
|
||||
|
||||
- 评论组件和管理后台可以在任意域名下通过 HTTP 调用后端接口,无需浏览器端额外跨域配置。
|
||||
- 由于不允许跨域携带 Cookie,认证完全通过 `Authorization: Bearer <token>` 头完成。
|
||||
|
||||
代码中预留了 `ALLOW_ORIGIN` 绑定,目前默认行为是允许所有来源。如果你有严格的安全需求,可以在此基础上自定义 CORS 逻辑,将 `origin` 收紧到指定域名。
|
||||
|
||||
### 管理员认证中间件
|
||||
|
||||
管理员认证中间件位于 [`cwd-comments-api/src/utils/auth.ts`](../../cwd-comments-api/src/utils/auth.ts),对 `/admin/*` 路径统一生效(登录接口除外):
|
||||
|
||||
- 从请求头 `Authorization` 中解析 Bearer Token。
|
||||
- 在 `CWD_AUTH_KV` 中校验 `token:<key>` 对应的会话信息。
|
||||
- Token 由 `/admin/login` 接口生成,有效期为 24 小时。
|
||||
|
||||
认证失败时返回:
|
||||
|
||||
- 状态码:`401`
|
||||
- 响应体:`{ "message": "Unauthorized" }` 或 `Token expired or invalid`
|
||||
|
||||
## 日志配置与规范
|
||||
|
||||
后端主要通过 `console.log` 输出结构化日志,便于在 Cloudflare 控制台或日志采集系统中查看。
|
||||
|
||||
### 请求级别日志
|
||||
|
||||
在入口中为所有请求记录起止日志:
|
||||
|
||||
- `Request:start`:
|
||||
- `method`:HTTP 方法
|
||||
- `path`:请求路径
|
||||
- `url`:完整 URL
|
||||
- `hasDb`:是否成功注入 D1 绑定
|
||||
- `hasAuthKv`:是否成功注入 KV 绑定
|
||||
- `Request:end`:
|
||||
- `method`:HTTP 方法
|
||||
- `path`:请求路径
|
||||
|
||||
### 业务级别日志
|
||||
|
||||
示例(评论提交流程):
|
||||
|
||||
- `PostComment:request`:记录 `postSlug`、是否为回复、邮箱是否存在、IP 等信息。
|
||||
- `PostComment:inserted`:记录评论已写入数据库。
|
||||
- `PostComment:mailDispatch:*`:记录邮件通知相关流程和限流结果。
|
||||
|
||||
错误情况:
|
||||
|
||||
- 统一使用 `console.error` 输出错误对象,例如邮件发送失败或数据库写入异常。
|
||||
|
||||
### 日志使用建议
|
||||
|
||||
- 不在日志中输出管理员密码、完整 Token 等敏感信息。
|
||||
- 如果接入外部日志系统,可以基于日志前缀(如 `Request:*`、`PostComment:*`)做过滤和告警。
|
||||
- 在调试阶段可以保留日志,生产环境如需减少日志量,可根据需要在代码中调整输出。
|
||||
|
||||
Reference in New Issue
Block a user