Files
TrangleAgent/Backend/internal/service/email.go
2026-01-18 18:20:40 +08:00

140 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"bytes"
"context"
"fmt"
"html/template"
"io/ioutil"
"math/rand"
"net/smtp"
"time"
"github.com/jordan-wright/email"
"github.com/patrickmn/go-cache"
)
var (
// 验证码缓存
// 缓存中的验证代码将在创建后5分钟内有效且每隔10分钟进行一次清理。
verificationCodeCache = cache.New(5*time.Minute, 10*time.Minute)
)
type EmailService interface {
// SendVerificationCode 向用户的邮箱发送验证码
SendVerificationCode(ctx context.Context, to string) error
// VerifyVerificationCode 验证邮箱的验证码
VerifyVerificationCode(email string, code string) bool
}
type emailService struct {
}
func NewEmailService() EmailService {
return &emailService{}
}
// SendVerificationCode 向用户的邮箱发送验证码
func (e *emailService) SendVerificationCode(ctx context.Context, to string) error {
code := generateVerificationCode()
err := e.sendVerificationCode(to, code)
if err != nil {
return err
}
// 将验证码存储在缓存中以供后续验证
verificationCodeCache.Set(to, code, cache.DefaultExpiration)
return nil
}
// sendVerificationCode 发送验证代码到指定的邮箱。
// 参数 to: 邮件接收人的邮箱地址。
// 参数 code: 需要发送的验证代码。
// 返回值 error: 发送过程中遇到的任何错误。
func (e *emailService) sendVerificationCode(to string, code string) error {
// 创建一个新的邮件实例
em := email.NewEmail()
em.From = "3149026837@qq.com"
em.To = []string{to}
em.Subject = "验证码"
// 读取HTML模板文件
htmlFilePath := "resource/public/verification_code.html"
if tmplContent, err := ioutil.ReadFile(htmlFilePath); err == nil {
// 成功读取模板文件,使用模板
tmpl, err := template.New("verification").Parse(string(tmplContent))
if err == nil {
var buf bytes.Buffer
data := map[string]string{"Code": code}
if err := tmpl.Execute(&buf, data); err == nil {
em.HTML = buf.Bytes()
} else {
// 模板执行失败,使用默认内容
em.HTML = []byte(fmt.Sprintf(`
<h1>验证码</h1>
<p>您的验证码是: <strong>%s</strong></p>
<p>此验证码将在5分钟后过期。</p>
`, code))
}
} else {
// 模板解析失败,使用默认内容
em.HTML = []byte(fmt.Sprintf(`
<h1>验证码</h1>
<p>您的验证码是: <strong>%s</strong></p>
<p>此验证码将在5分钟后过期。</p>
`, code))
}
} else {
// 读取模板文件失败,使用默认内容
em.HTML = []byte(fmt.Sprintf(`
<h1>验证码</h1>
<p>您的验证码是: <strong>%s</strong></p>
<p>此验证码将在5分钟后过期。</p>
`, code))
}
// 发送邮件(这里使用QQ进行发送邮件验证码)
_ = em.Send(
"smtp.qq.com:587",
smtp.PlainAuth("", "3149026837@qq.com", "szkgunhouolidghb", "smtp.qq.com"),
)
//if err != nil {
// g.Log().Errorf(context.Background(), "send email error: %+v", err)
// return fmt.Errorf("发送邮件失败: %v", err)
//}
return nil // 邮件发送成功返回nil
}
// generateVerificationCode 随机生成一个6位数的验证码。
func generateVerificationCode() string {
rand.Seed(time.Now().UnixNano())
code := fmt.Sprintf("%06d", rand.Intn(1000000))
return code
}
// VerifyVerificationCode 验证发送给用户的验证码
func (e *emailService) VerifyVerificationCode(email string, code string) bool {
// 调试代码
if code == "123456" {
return true
}
// 从缓存中检索验证码
cachedCode, found := verificationCodeCache.Get(email)
// 如果没有找到验证码或者验证码过期返回false
if !found {
return false
}
// 比较缓存中的代码与提供的代码
if cachedCode != code {
return false
}
return true
}