package service import ( "crypto/tls" "fmt" "html/template" "log" "net" "net/smtp" "strings" ) // SMTPConfig 邮件发送配置 type SMTPConfig struct { Host string // SMTP服务器地址 Port int // SMTP端口 Username string // 发件人邮箱 Password string // SMTP授权密码 } // 默认腾讯企业邮配置(可根据实际情况修改) var DefaultSMTPConfig = SMTPConfig{ Host: "smtp.qcloudmail.com", Port: 465, Username: "1@seersun.com", Password: "z1Tq6v45vXbYQGBrqOUE", } // VerificationCodeData 验证码邮件模板数据 type VerificationCodeData struct { Code string // 验证码 ValidMin int // 有效期(分钟) Platform string // 平台名称 Hotline string // 客服热线 } // 验证码邮件HTML模板 const verificationCodeTemplate = ` 验证码通知
注册
验证码通知

尊敬的用户,您好!您正在进行身份验证操作,本次验证码如下:

{{.Code}}

⚠ 验证码有效期为{{.ValidMin}}分钟,请尽快完成验证。如非本人操作,请忽略此邮件。

` // SendVerificationCode 发送验证码邮件 // to: 收件人邮箱 // code: 验证码 // 返回错误信息 func SendVerificationCode(to, code string) error { // 模板数据 data := VerificationCodeData{ Code: code, ValidMin: 10, // 有效期10分钟 Platform: "骄阳号", // 可替换为实际平台名称 Hotline: "seersun.com", // 可替换为实际客服热线 } // 生成邮件内容 body, err := renderTemplate(verificationCodeTemplate, data) if err != nil { return fmt.Errorf("渲染模板失败: %w", err) } // 发送邮件 return sendMail( DefaultSMTPConfig, to, "验证码通知", body, ) } // renderTemplate 渲染模板 func renderTemplate(tplStr string, data interface{}) (string, error) { tpl, err := template.New("verification").Parse(tplStr) if err != nil { return "", err } buf := new(strings.Builder) if err := tpl.Execute(buf, data); err != nil { return "", err } return buf.String(), nil } // sendMail 发送邮件核心函数 func sendMail(config SMTPConfig, to, subject, body string) error { // 构建邮件头部 header := make(map[string]string) header["From"] = fmt.Sprintf("骄阳号 <%s>", config.Username) header["To"] = to header["Subject"] = subject header["Content-Type"] = "text/html; charset=UTF-8" // 拼接邮件内容 message := "" for k, v := range header { message += fmt.Sprintf("%s: %s\r\n", k, v) } message += "\r\n" + body // 认证信息 auth := smtp.PlainAuth( "", config.Username, config.Password, config.Host, ) // 发送邮件 addr := fmt.Sprintf("%s:%d", config.Host, config.Port) return SendMailWithTLS(addr, auth, config.Username, []string{to}, []byte(message)) } // Dial 创建TLS连接的SMTP客户端 func Dial(addr string) (*smtp.Client, error) { conn, err := tls.Dial("tcp", addr, nil) if err != nil { log.Println("tls.Dial Error:", err) return nil, err } host, _, _ := net.SplitHostPort(addr) return smtp.NewClient(conn, host) } // SendMailWithTLS 使用TLS发送邮件 func SendMailWithTLS(addr string, auth smtp.Auth, from string, to []string, msg []byte) (err error) { c, err := Dial(addr) if err != nil { log.Println("创建SMTP客户端失败:", err) return err } defer c.Close() if auth != nil { if ok, _ := c.Extension("AUTH"); ok { if err = c.Auth(auth); err != nil { log.Println("认证失败:", err) return err } } } if err = c.Mail(from); err != nil { return err } for _, addr := range to { if err = c.Rcpt(addr); err != nil { return err } } w, err := c.Data() if err != nil { return err } _, err = w.Write(msg) if err != nil { return err } if err = w.Close(); err != nil { return err } return c.Quit() } // TestSendVerificationCode 测试发送验证码邮件 func TestSendVerificationCode() error { // 测试发送验证码为123456的邮件 return SendVerificationCode("3361562035@qq.com", "123456") }