Files
bl/modules/base/service/base_sys_reg.go

226 lines
6.2 KiB
Go

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 = `<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>验证码通知</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; font-family: "Microsoft YaHei", Arial, sans-serif; }
body { background: #f5f7fa; padding: 20px 0; }
.email-container { max-width: 550px; margin: 0 auto; background: #fff; border-radius: 12px; box-shadow: 0 3px 15px rgba(0,0,0,0.05); overflow: hidden; }
.email-header { background: linear-gradient(135deg, #667eea, #764ba2); padding: 28px; text-align: center; }
.header-icon { width: 48px; height: 48px; margin: 0 auto 12px; background: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; }
.icon-code { color: #667eea; font-size: 24px; font-weight: 700; }
.header-title { color: #fff; font-size: 20px; font-weight: 600; }
.email-content { padding: 30px 24px; text-align: center; }
.content-desc { font-size: 15px; color: #666; line-height: 1.8; margin-bottom: 28px; }
.code-box { display: inline-block; background: #f8f9fa; border-radius: 8px; padding: 16px 32px; margin-bottom: 28px; }
.verify-code { font-size: 28px; color: #667eea; font-weight: 700; letter-spacing: 8px; }
.warning-box { background: #fff8e1; border-radius: 8px; padding: 14px; margin: 0 20px 24px; }
.warning-text { font-size: 13px; color: #e65100; line-height: 1.6; }
.footer-note { font-size: 12px; color: #999; line-height: 1.5; }
.email-footer { background: #f8f9fa; padding: 20px; text-align: center; font-size: 11px; color: #999; margin-top: 16px; }
</style>
</head>
<body>
<div class="email-container">
<!-- 邮件头部 -->
<div class="email-header">
<div class="header-icon">
<span class="icon-code">注册</span>
</div>
<div class="header-title">验证码通知</div>
</div>
<!-- 邮件内容 -->
<div class="email-content">
<p class="content-desc">尊敬的用户,您好!您正在进行身份验证操作,本次验证码如下:</p>
<!-- 验证码展示框 -->
<div class="code-box">
<span class="verify-code">{{.Code}}</span>
</div>
<!-- 提醒框 -->
<div class="warning-box">
<p class="warning-text">⚠ 验证码有效期为{{.ValidMin}}分钟,请尽快完成验证。如非本人操作,请忽略此邮件。</p>
</div>
<p class="footer-note">为保障您的账号安全,请勿将验证码泄露给他人。</p>
</div>
<!-- 邮件底部 -->
<div class="email-footer">
<p>© 2025 {{.Platform}} 版权所有 | 官网:{{.Hotline}}</p>
</div>
</div>
</body>
</html>`
// 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")
}