// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . //go:build plus package tasks import ( "fmt" teaconst "github.com/TeaOSLab/EdgeAPI/internal/const" "github.com/TeaOSLab/EdgeAPI/internal/db/models" "github.com/TeaOSLab/EdgeAPI/internal/goman" "github.com/TeaOSLab/EdgeAPI/internal/remotelogs" "github.com/TeaOSLab/EdgeAPI/internal/senders/mediasenders" "github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/types" "strings" "time" ) func init() { dbs.OnReadyDone(func() { goman.New(func() { NewUserVerifyCodeTask(30 * time.Second).Start() }) }) } // UserVerifyCodeTask 验证码相关任务 type UserVerifyCodeTask struct { BaseTask duration time.Duration } func NewUserVerifyCodeTask(duration time.Duration) *UserVerifyCodeTask { return &UserVerifyCodeTask{ duration: duration, } } func (this *UserVerifyCodeTask) Start() { var ticker = time.NewTicker(this.duration) for range ticker.C { err := this.Loop() if err != nil { remotelogs.Error("UserVerifyCodeTask", err.Error()) } } } func (this *UserVerifyCodeTask) Loop() error { if !this.IsPrimaryNode() { return nil } // 删除过期 var tx *dbs.Tx err := models.SharedUserVerifyCodeDAO.DeleteExpiredCodes(tx) if err != nil { return err } // 注册信息 registerConfig, _ := models.SharedSysSettingDAO.ReadUserRegisterConfig(tx) if registerConfig == nil { return nil } // 邮件设置 senderConfig, err := models.SharedSysSettingDAO.ReadUserSenderConfig(tx) if err != nil { return err } var verifyEmail = senderConfig.VerifyEmail // 准备邮件、短信中的参数 productName, err := models.SharedSysSettingDAO.ReadProductName(tx) if err != nil { return err } if len(productName) == 0 { productName = teaconst.ProductNameZH } userNodeAddr, err := models.SharedUserNodeDAO.FindUserNodeAccessAddr(tx) if err != nil { return err } // 待发送 verifyCodes, err := models.SharedUserVerifyCodeDAO.ListSendingCodes(tx, 10) if err != nil { return err } var mailInfos = []*mediasenders.MailInfo{} var verifyIds = []int64{} for _, verifyCode := range verifyCodes { // 已过期 if int64(verifyCode.ExpiresAt) < time.Now().Unix() { continue } switch verifyCode.Type { case models.UserVerifyCodeTypeResetPassword: // 通过邮件 if len(verifyCode.Email) > 0 && verifyEmail != nil && verifyEmail.IsOn { if registerConfig.EmailResetPassword.IsOn { var subject = registerConfig.EmailResetPassword.Subject subject = strings.ReplaceAll(subject, "${product.name}", productName) var body = registerConfig.EmailResetPassword.Body body = strings.ReplaceAll(body, "${product.name}", productName) body = strings.ReplaceAll(body, "${url.home}", userNodeAddr) body = strings.ReplaceAll(body, "${code}", verifyCode.Code) mailInfos = append(mailInfos, &mediasenders.MailInfo{ To: verifyCode.Email, Subject: subject, Body: body, }) verifyIds = append(verifyIds, int64(verifyCode.Id)) } } // 通过手机号 if len(verifyCode.Mobile) > 0 { // TODO 需要实现 verifyIds = append(verifyIds, int64(verifyCode.Id)) } } } // 发送邮件 if len(mailInfos) > 0 && verifyEmail != nil { var mailSender = mediasenders.NewEmailMedia() mailSender.Protocol = verifyEmail.Protocol mailSender.SMTP = verifyEmail.SMTPHost + ":" + types.String(verifyEmail.SMTPPort) mailSender.Username = verifyEmail.Username mailSender.Password = verifyEmail.Password mailSender.From = verifyEmail.FromEmail mailSender.FromName = verifyEmail.FromName err = mailSender.SendMails(mailInfos, productName) if err != nil { return fmt.Errorf("send mail failed: %w", err) } } // 设置为已发送 for _, verifyId := range verifyIds { err = models.SharedUserVerifyCodeDAO.UpdateCodeIsSent(tx, verifyId) if err != nil { return err } } return nil }