117 lines
3.0 KiB
Go
117 lines
3.0 KiB
Go
package email
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/cenkalti/backoff/v5"
|
|
"github.com/ssdomei232/goodBaby/configs"
|
|
"github.com/ssdomei232/goodBaby/handler/db"
|
|
"github.com/ssdomei232/goodBaby/model"
|
|
"github.com/wneessen/go-mail"
|
|
)
|
|
|
|
// 从 Rule 中获取 EmailAccount 配置
|
|
func GetEmailAccountFromRule(rule *model.Rule) (*EmailAccountConfig, error) {
|
|
gormDB, err := db.GetGormDB()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 1. 通过 account_id 获取到对应的 account 配置
|
|
var emailAccount model.Account
|
|
result := gormDB.Where("id = ?", rule.AccountID).First(&emailAccount)
|
|
if result.Error != nil {
|
|
return nil, result.Error
|
|
}
|
|
|
|
// 2. 通过 account 配置中的 config 字段获取到 EmailAccount
|
|
var emailAccountConfig EmailAccountConfig
|
|
err = json.Unmarshal([]byte(emailAccount.Config), &emailAccountConfig)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &emailAccountConfig, nil
|
|
}
|
|
|
|
// 从 Rule 中获取 EmailRule 配置
|
|
func GetEmailRuleFromRule(rule *model.Rule) (*EmailRule, error) {
|
|
var emailRule EmailRule
|
|
err := json.Unmarshal([]byte(rule.ConfigJson), &emailRule)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &emailRule, nil
|
|
}
|
|
func sendMailMsgWithRetry(rule *model.Rule, address string) {
|
|
config, err := configs.GetConfig()
|
|
if err != nil {
|
|
log.Printf("获取配置失败: %v", err)
|
|
return
|
|
}
|
|
var timeout time.Duration = time.Duration(config.TimeoutDurationHours) * time.Hour
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
defer cancel()
|
|
|
|
operation := func() (string, error) {
|
|
err := sendMailMsg(address, rule)
|
|
return "", err
|
|
}
|
|
|
|
_, err = backoff.Retry(ctx, operation, backoff.WithBackOff(backoff.NewExponentialBackOff()))
|
|
if err != nil {
|
|
log.Printf("发送邮件失败: %v", err)
|
|
}
|
|
}
|
|
|
|
func sendMailMsg(address string, rule *model.Rule) error {
|
|
emailAccountConfig, err := GetEmailAccountFromRule(rule)
|
|
if err != nil {
|
|
log.Printf("获取邮件账户配置失败: %v", err)
|
|
return fmt.Errorf("获取邮件账户配置失败: %v", err)
|
|
}
|
|
|
|
emailRule, err := GetEmailRuleFromRule(rule)
|
|
if err != nil {
|
|
log.Printf("获取邮件规则配置失败: %v", err)
|
|
return fmt.Errorf("获取邮件规则配置失败: %v", err)
|
|
}
|
|
|
|
client, err := mail.NewClient(
|
|
emailAccountConfig.SMTPServer,
|
|
mail.WithPort(emailAccountConfig.Port),
|
|
mail.WithSSL(),
|
|
mail.WithUsername(emailAccountConfig.Username),
|
|
mail.WithPassword(emailAccountConfig.Password),
|
|
mail.WithSMTPAuth(mail.SMTPAuthPlain),
|
|
)
|
|
if err != nil {
|
|
return fmt.Errorf("创建邮件客户端失败: %v", err)
|
|
}
|
|
|
|
// 创建邮件
|
|
message := mail.NewMsg()
|
|
if err := message.From(emailAccountConfig.Username); err != nil {
|
|
return fmt.Errorf("设置发件人失败: %v", err)
|
|
}
|
|
|
|
if err := message.To(address); err != nil {
|
|
return fmt.Errorf("设置收件人失败: %v", err)
|
|
}
|
|
|
|
message.Subject(emailRule.Title)
|
|
message.SetBodyString(mail.TypeTextPlain, emailRule.Msg)
|
|
|
|
// 发送邮件
|
|
if err := client.DialAndSend(message); err != nil {
|
|
return fmt.Errorf("发送邮件失败: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|