feat: add email_send_log table to track email sends and registration status

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-30 14:29:30 +08:00
parent a07e08a761
commit 87bee98049
3 changed files with 81 additions and 3 deletions

View File

@@ -21,12 +21,14 @@ import (
) )
type UserService struct { type UserService struct {
userDao *dao.UserDao userDao *dao.UserDao
emailSendLogDao *dao.EmailSendLogDao
} }
func NewUserService() *UserService { func NewUserService() *UserService {
return &UserService{ return &UserService{
userDao: dao.NewUserDao(), userDao: dao.NewUserDao(),
emailSendLogDao: dao.NewEmailSendLogDao(),
} }
} }
@@ -141,6 +143,12 @@ func (svc *UserService) SendEmailVerifyCode(ctx context.Context, emailAddr strin
if cacheErr := cache.SetUserSendEmailLimit(ctx, emailAddr); cacheErr != nil { if cacheErr := cache.SetUserSendEmailLimit(ctx, emailAddr); cacheErr != nil {
log.Error(ctx, "func", "SendEmailVerifyCode", "msg", "set send email limit error", "error", cacheErr) log.Error(ctx, "func", "SendEmailVerifyCode", "msg", "set send email limit error", "error", cacheErr)
} }
record := &dao.EmailSendLog{Email: emailAddr, Status: dao.EmailSendStatusSent}
if logErr := svc.emailSendLogDao.Create(dao.DB.WithContext(ctx), record); logErr != nil {
log.Error(ctx, "func", "SendEmailVerifyCode", "msg", "create email send log error", "error", logErr)
}
return nil return nil
} }
@@ -156,7 +164,16 @@ func (svc *UserService) RegisterByEmail(ctx context.Context, emailAddr, password
_ = cache.DeleteUserEmailCode(ctx, emailAddr) _ = cache.DeleteUserEmailCode(ctx, emailAddr)
return svc.registerByEmailInternal(ctx, emailAddr, password) uid, err = svc.registerByEmailInternal(ctx, emailAddr, password)
if err != nil {
return 0, err
}
if logErr := svc.emailSendLogDao.MarkRegistered(dao.DB.WithContext(ctx), emailAddr); logErr != nil {
log.Error(ctx, "func", "RegisterByEmail", "msg", "mark email send log registered error", "error", logErr)
}
return uid, nil
} }
func (svc *UserService) registerByEmailInternal(ctx context.Context, emailAddr, password string) (uid int64, err error) { func (svc *UserService) registerByEmailInternal(ctx context.Context, emailAddr, password string) (uid int64, err error) {

View File

@@ -0,0 +1,50 @@
package dao
import (
"gorm.io/gorm"
)
type EmailSendStatus int8
const (
EmailSendStatusSent EmailSendStatus = 0 // 已发送,用户未注册
EmailSendStatusRegistered EmailSendStatus = 1 // 用户已完成注册
)
type EmailSendLog struct {
BaseModel
Email string `gorm:"column:email;type:varchar(255);not null;comment:邮箱地址" json:"email"`
Status EmailSendStatus `gorm:"column:status;type:tinyint;not null;default:0;comment:状态: 0=已发送未注册 1=已注册" json:"status"`
}
func (e *EmailSendLog) TableName() string {
return "email_send_log"
}
type EmailSendLogDao struct{}
func NewEmailSendLogDao() *EmailSendLogDao {
return &EmailSendLogDao{}
}
func (d *EmailSendLogDao) Create(tx *gorm.DB, log *EmailSendLog) error {
return tx.Create(log).Error
}
func (d *EmailSendLogDao) GetLatestByEmail(tx *gorm.DB, email string) (*EmailSendLog, error) {
var record EmailSendLog
err := tx.Where("email = ?", email).Order("id DESC").First(&record).Error
if err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, err
}
return &record, nil
}
func (d *EmailSendLogDao) MarkRegistered(tx *gorm.DB, email string) error {
return tx.Model(&EmailSendLog{}).
Where("email = ? AND status = ?", email, EmailSendStatusSent).
Update("status", EmailSendStatusRegistered).Error
}

View File

@@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS `email_send_log` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`email` VARCHAR(255) NOT NULL COMMENT '邮箱地址',
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态: 0=已发送未注册, 1=已注册',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
INDEX `idx_email` (`email`),
INDEX `idx_status` (`status`),
INDEX `idx_created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='邮件发送记录表';