Files
cursor/plans/Plan-b5e97267.plan.md
ray zhou 2dd9f17da9 ok
2026-06-29 14:51:55 +08:00

11 KiB
Raw Blame History


todos:

  • id: "ddl-mail-tables" content: "在 slot-notification 新增 mail_configSMTP 直字段)/ 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.phpsms_config slot-console/app/service/lib/MailService.phpConfigService::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/senderIdAnt/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 → STARTTLS465 → SSL与现网行为一致。

邮件模板(独立概念,不属于 mail_config

验证码邮件的标题/正文来自 email_template 配置组(titlebinding_email),属于发送模板,不是 SMTP 连接配置。

发送邮件时需要两张表配合:

flowchart LR
  sendMail[MailService 发信] --> mailConfig["mail_config\nSMTP 连接"]
  sendMail --> mailTemplate["mail_template\n标题/正文模板"]

mail_config(仅 SMTP 连接,直字段)

字段 类型 说明
id bigint PK 主键
platform varchar(32) 渠道标识,如 AwsSesZoho
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) 模板编码,如 bindingEmailauthEmail
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_templatetemplate_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 / MailSendLogModel
  • MailConfigEntity(后台 CRUD复用短信 Entity 分页模式)
  • initDB.php 补充 DDL另提供 db/mail_config.sql 便于手工执行

2. 发送层

  • composer.json 增加 phpmailer/phpmailer
  • MailService:从 mail_config 取 SMTP 连接,从 mail_template 取标题/正文 → PHPMailer 发信 → 写 mail_send_log
  • app/mail/services/sdk/BaseMail.php + SmtpMail.php(首期只实现 SMTP结构与 BaseSms 一致,便于后续扩展 SendGrid 等)
  • MailCache:验证码 Redis 缓存(镜像 SmsCachekey 规则与 slot-console EmailCodeLibService 保持一致,避免迁移期验证码失效

3. API 层

新增路由(config/route.php

  • POST /innerapi/email/send-verify-code
  • POST /innerapi/email/verify-code
  • POST /innerapi/admin/mail-config/index|save|update|destroy
  • POST /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

  1. s_config 读取 mail_config 配置组 → 写入 mail_config6 个 SMTP 字段)
  2. s_config 读取 email_template 配置组 → 写入 mail_template 表(title + binding_email
  3. 幂等插入(已存在则跳过)

迁移完成后,slot-consolemail_config / email_template 配置组可保留只读一段时间,确认无回退需求后再清理。


风险与边界

  • 命名冲突/innerapi/mail/* 继续保留给站内消息SMTP 统一走 /innerapi/email/*
  • 验证码兼容MailCache 的 Redis key 必须与 slot-console 现有 ShareRedisKeyManagerService::emailCode() 一致
  • 模板范围:本期只迁移验证码邮件模板(binding_email/title);充值/提现等 MQ 站内邮件模板(message_template 配置组)不在本次范围
  • 多 SMTP failover:表结构支持,首期实现「取第一条启用配置」即可

验收标准

  1. slot-admin 可 CRUD mail_config,与短信配置页体验一致
  2. Lobby 发/验邮箱验证码链路走 slot-notification功能与迁移前一致
  3. 发送成功/失败均写入 mail_send_log
  4. slot-console 不再读取 ConfigService::getGroupData('mail_config')
  5. 执行 verify-slot-backend.sh 通过