11 KiB
todos:
- id: "ddl-mail-tables" content: "在 slot-notification 新增 mail_config(SMTP 直字段)/ mail_template / mail_send_log 表 DDL" status: pending
- id: "mail-module" content: "实现 app/mail 模块:Model、Entity、Cache、MailService、SmtpMail SDK" status: pending
- id: "notification-api" content: "新增 EmailController + MailConfigAdminController 与 route 注册" status: pending
- id: "sdk-client" content: "扩展 slot-lib / slot-sdk 的 MailService 客户端方法" status: pending
- id: "console-migrate" content: "slot-console CommonController 改调 notification;废弃本地 MailService" status: pending
- id: "admin-ui" content: "slot-admin 后端 + slot-admin-vue 邮件配置管理页" status: pending
- id: "data-migration" content: "编写 mail_config 从 slot-console 配置组到表的幂等迁移脚本" status: pending
- id: "verify" content: "跑 verify-slot-backend.sh,验证发信/验码/后台 CRUD 链路" status: pending isProject: false
slot-notification 邮件配置表化(对齐短信)
现状与结论
当前两套通知渠道配置方式不一致:
| 能力 | 短信(已收口) | SMTP 邮件(未收口) |
|---|---|---|
| 配置存储 | slot-notification/app/sms/model/SmsConfigModel.php → sms_config 表 |
slot-console/app/service/lib/MailService.php → ConfigService::getGroupData('mail_config') |
| 发送服务 | slot-notification/app/sms/services/SmsService.php |
slot-console 本地 MailService + PHPMailer |
| 验证码 API | /innerapi/sms/sendVerifyCode |
slot-console CommonController::sendEmailCode |
| 后台管理 | slot-admin → slot-lib → notification /innerapi/admin/* |
slot-admin 通用配置页 email_config(另一套) |
结论:应该建表。 你已选择「完整对齐短信」,建议把 SMTP 邮件作为 slot-notification 的第二条外发渠道,与短信保持同一套「配置表 + 发送日志 + innerapi + 后台管理 + SDK 客户端」模式。
注意:slot-notification 里现有 MailController / EmailService 实际是站内消息兼容别名,不是 SMTP。新 SMTP 能力应使用独立命名空间(建议 app/mail/*)和独立路由前缀(建议 /innerapi/email/*),避免与 /innerapi/mail/*(站内消息)冲突。
flowchart LR
subgraph before [当前]
lobby1[Lobby] --> console1[slot-console CommonController]
console1 --> config1["ConfigService mail_config"]
console1 --> mail1[MailService PHPMailer]
end
subgraph after [目标]
lobby2[Lobby] --> console2[slot-console 薄代理]
console2 --> sdk[slot-lib MailService]
sdk --> notif[slot-notification EmailController]
notif --> table["mail_config 表"]
notif --> smtp[SmtpMail PHPMailer]
notif --> log["mail_send_log 表"]
end
表结构设计(邮件用直字段,短信保留 JSON)
在 s_message(与 sms_config 同库)新增两张表。
为什么邮件不用 JSON、短信用 JSON?
| 对比 | 短信 sms_config.config |
邮件 mail_config |
|---|---|---|
| 字段形态 | 各平台差异大(Buka 要 appId/senderId,Ant/Chuanglan 字段不同) | SMTP 标准字段固定,截图与代码一致 |
| 后台表单 | 按 platform 动态展示不同表单项 |
固定 6~8 个输入框,与现有配置页一一对应 |
| 查询/校验 | 结构不统一,适合 JSON | 可直接列级校验、索引、迁移映射 |
结论:邮件配置用直接字段更好;不必为了「和短信表长得像」而强行 JSON。
当前邮件配置项(来自截图,仅 SMTP 连接)
截图中的 6 项即为 mail_config 配置组现有字段,与 MailService 读取项一致。这就是邮件配置表应存的全部内容:
| 配置项 | 列名建议 | 说明 |
|---|---|---|
| smtp host | smtp_host |
如 email-smtp.us-east-1.amazonaws.com |
| 用户名 | username |
SMTP 登录账号 |
| 密码 | password |
SMTP 密码/应用专用密码 |
| 端口 | port |
如 587 |
| 发件人地址 | from_address |
原 from |
| 发件人名称 | from_name |
如 TOGOO |
加密方式(tls/ssl)不单独落库:发送时按 port 推断即可(587 → STARTTLS,465 → SSL),与现网行为一致。
邮件模板(独立概念,不属于 mail_config)
验证码邮件的标题/正文来自 email_template 配置组(title、binding_email),属于发送模板,不是 SMTP 连接配置。
发送邮件时需要两张表配合:
flowchart LR
sendMail[MailService 发信] --> mailConfig["mail_config\nSMTP 连接"]
sendMail --> mailTemplate["mail_template\n标题/正文模板"]
mail_config(仅 SMTP 连接,直字段)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
bigint PK | 主键 |
platform |
varchar(32) | 渠道标识,如 AwsSes、Zoho |
status |
tinyint | 1 启用 / 2 禁用 |
num |
int | 排序,降序优先 |
smtp_host |
varchar(255) | SMTP 主机 |
username |
varchar(128) | SMTP 用户名 |
password |
varchar(512) | SMTP 密码 |
port |
int | SMTP 端口 |
from_address |
varchar(255) | 发件人邮箱 |
from_name |
varchar(128) | 发件人显示名 |
create_time / update_time |
datetime | 审计字段 |
mail_template(邮件发送模板,独立表)
| 字段 | 类型 | 说明 |
|---|---|---|
id |
bigint PK | 主键 |
template_code |
varchar(64) | 模板编码,如 bindingEmail、authEmail |
template_name |
varchar(128) | 模板名称 |
title |
varchar(255) | 邮件标题模板 |
body |
text | 邮件正文模板,支持 {code} 等变量 |
status |
tinyint | 1 启用 / 2 禁用 |
create_time / update_time |
datetime | 审计字段 |
首期迁移:把 email_template 配置组中的 title + binding_email 迁入 mail_template(template_code=authEmail 或按业务拆分)。
注意:message_template 是站内消息模板,与 SMTP 外发邮件模板是不同业务,不混用。
mail_send_log(发送日志,放 s_common)
镜像 sms_send_log:
unique_sn,email,platform,subject,content,status,type,retry_num,create_time
后端实现(slot-notification)
1. 数据层
新建 app/mail/ 模块,参照 app/sms/:
MailConfigModel/MailSendLogModelMailConfigEntity(后台 CRUD,复用短信 Entity 分页模式)- 在
initDB.php补充 DDL;另提供db/mail_config.sql便于手工执行
2. 发送层
composer.json增加phpmailer/phpmailerMailService:从mail_config取 SMTP 连接,从mail_template取标题/正文 → PHPMailer 发信 → 写mail_send_logapp/mail/services/sdk/BaseMail.php+SmtpMail.php(首期只实现 SMTP,结构与BaseSms一致,便于后续扩展 SendGrid 等)MailCache:验证码 Redis 缓存(镜像SmsCache),key 规则与 slot-consoleEmailCodeLibService保持一致,避免迁移期验证码失效
3. API 层
新增路由(config/route.php):
POST /innerapi/email/send-verify-codePOST /innerapi/email/verify-codePOST /innerapi/admin/mail-config/index|save|update|destroyPOST /innerapi/admin/mail-template/index|save|update|destroy(模板 CRUD,与配置分开)
新建 EmailController(发送/校验)与 MailConfigAdminController(配置 CRUD),不要复用现有站内消息 MailController。
4. 渠道选择策略
首期与短信一致:按 status=启用 + num desc 取第一条;预留后续 failover(注释掉的短信轮询逻辑可一并参考)。
跨服务改造
slot-lib / slot-sdk
在 slot-lib/src/services/notification/ 新增 MailService(或 EmailService):
sendVerifyCode(email, type)verifyCode(email, code, type)getMailConfigPageList/saveMailConfig/updateMailConfig/destroyMailConfig
同步扩展 slot-sdk/src/service/notification/NotificationService.php。
slot-console(调用方改造)
CommonController::sendEmailCode / verifyEmailCode:
- 改为调用 slot-lib
MailService,不再直接依赖本地MailService+ConfigService - 本地
MailService标记废弃或删除(确认无其他引用后)
限流、参数校验仍留在 slot-console Controller 层(与现有短信 napi 模式一致)。
slot-admin + slot-admin-vue
镜像短信后台:
- 后端:
slot-admin/app/game/controller/SmsController.php→ 新建MailController - 前端:新建
mail/config/页,仅 6 个 SMTP 字段 + platform/status/num;另建mail/template/页管理标题/正文模板 - 菜单/权限:新增
mailConfig路由与按钮权限
数据迁移
新增一次性迁移脚本(建议 slot-notification/app/command/MigrateMailConfig.php):
- 从
s_config读取mail_config配置组 → 写入mail_config表(6 个 SMTP 字段) - 从
s_config读取email_template配置组 → 写入mail_template表(title+binding_email) - 幂等插入(已存在则跳过)
迁移完成后,slot-console 侧 mail_config / email_template 配置组可保留只读一段时间,确认无回退需求后再清理。
风险与边界
- 命名冲突:
/innerapi/mail/*继续保留给站内消息;SMTP 统一走/innerapi/email/* - 验证码兼容:
MailCache的 Redis key 必须与 slot-console 现有ShareRedisKeyManagerService::emailCode()一致 - 模板范围:本期只迁移验证码邮件模板(
binding_email/title);充值/提现等 MQ 站内邮件模板(message_template配置组)不在本次范围 - 多 SMTP failover:表结构支持,首期实现「取第一条启用配置」即可
验收标准
- slot-admin 可 CRUD
mail_config,与短信配置页体验一致 - Lobby 发/验邮箱验证码链路走 slot-notification,功能与迁移前一致
- 发送成功/失败均写入
mail_send_log - slot-console 不再读取
ConfigService::getGroupData('mail_config') - 执行
verify-slot-backend.sh通过