193 lines
4.8 KiB
Go
193 lines
4.8 KiB
Go
// 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/TeaOSLab/EdgeCommon/pkg/userconfigs"
|
|
"github.com/iwind/TeaGo/Tea"
|
|
"github.com/iwind/TeaGo/dbs"
|
|
"github.com/iwind/TeaGo/logs"
|
|
"github.com/iwind/TeaGo/types"
|
|
"net/mail"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func init() {
|
|
dbs.OnReadyDone(func() {
|
|
goman.New(func() {
|
|
NewUserEmailVerificationTask(30 * time.Second).Start()
|
|
})
|
|
})
|
|
}
|
|
|
|
// UserEmailVerificationTask 用户邮件验证任务
|
|
type UserEmailVerificationTask struct {
|
|
BaseTask
|
|
|
|
duration time.Duration
|
|
}
|
|
|
|
func NewUserEmailVerificationTask(duration time.Duration) *UserEmailVerificationTask {
|
|
return &UserEmailVerificationTask{
|
|
duration: duration,
|
|
}
|
|
}
|
|
|
|
func (this *UserEmailVerificationTask) Start() {
|
|
var ticker = time.NewTicker(this.duration)
|
|
for range ticker.C {
|
|
err := this.Loop()
|
|
if err != nil {
|
|
remotelogs.Error("UserEmailVerificationTask", err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
func (this *UserEmailVerificationTask) Loop() error {
|
|
if !this.IsPrimaryNode() {
|
|
return nil
|
|
}
|
|
|
|
var tx *dbs.Tx
|
|
|
|
// 注册设置
|
|
registerConfig, err := models.SharedSysSettingDAO.ReadUserRegisterConfig(tx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !registerConfig.EmailVerification.IsOn {
|
|
return nil
|
|
}
|
|
|
|
// 删除过期的认证
|
|
var life = registerConfig.EmailVerification.Life
|
|
if life <= 0 {
|
|
life = userconfigs.EmailVerificationDefaultLife
|
|
}
|
|
var lifeDays = life / 86400
|
|
if lifeDays <= 0 {
|
|
lifeDays = 1
|
|
}
|
|
err = models.SharedUserEmailVerificationDAO.DeleteExpiredVerifications(tx, lifeDays)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 检查邮件设置
|
|
senderConfig, err := models.SharedSysSettingDAO.ReadUserSenderConfig(tx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var verifyEmail = senderConfig.VerifyEmail
|
|
if verifyEmail == nil {
|
|
// TODO 思考是否需要用户没有设置
|
|
return nil
|
|
}
|
|
if !verifyEmail.IsOn {
|
|
return nil
|
|
}
|
|
|
|
// 查找等待发送的认证
|
|
verifications, err := models.SharedUserEmailVerificationDAO.ListSendingVerifications(tx, 10 /** 单次10封 **/)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(verifications) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// 准备邮件中的参数
|
|
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
|
|
}
|
|
|
|
var mailInfos = []*mediasenders.MailInfo{}
|
|
var verificationIds = []int64{}
|
|
for _, verification := range verifications {
|
|
// 检查时间
|
|
if int64(verification.CreatedAt) < time.Now().Unix()-int64(life) {
|
|
// 已过期,设置为已发送
|
|
err = models.SharedUserEmailVerificationDAO.DeleteVerification(tx, int64(verification.Id))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
continue
|
|
}
|
|
|
|
_, err = mail.ParseAddress(verification.Email)
|
|
if err != nil {
|
|
// 邮件已发送,设置为已发送
|
|
err = models.SharedUserEmailVerificationDAO.DeleteVerification(tx, int64(verification.Id))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
|
|
// 标题和内容
|
|
var subject = registerConfig.EmailVerification.Subject
|
|
subject = strings.ReplaceAll(subject, "${product.name}", productName)
|
|
|
|
var body = registerConfig.EmailVerification.Body
|
|
body = strings.ReplaceAll(body, "${product.name}", productName)
|
|
body = strings.ReplaceAll(body, "${url.home}", userNodeAddr)
|
|
body = strings.ReplaceAll(body, "${url.verify}", userNodeAddr+"/email/verify/"+verification.Code)
|
|
|
|
mailInfos = append(mailInfos, &mediasenders.MailInfo{
|
|
To: verification.Email,
|
|
Subject: subject,
|
|
Body: body,
|
|
})
|
|
|
|
if Tea.IsTesting() {
|
|
logs.Println("sending verification mail to :", verification.Email)
|
|
}
|
|
|
|
verificationIds = append(verificationIds, int64(verification.Id))
|
|
}
|
|
if len(mailInfos) == 0 {
|
|
return 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 _, verificationId := range verificationIds {
|
|
err = models.SharedUserEmailVerificationDAO.UpdateVerificationIsSent(tx, verificationId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|