feat(base): 添加邮件验证码发送功能并注释机器人测试代码
This commit is contained in:
225
modules/base/service/base_sys_reg.go
Normal file
225
modules/base/service/base_sys_reg.go
Normal file
@@ -0,0 +1,225 @@
|
||||
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")
|
||||
}
|
||||
Reference in New Issue
Block a user