Files

153 lines
3.4 KiB
Go
Raw Permalink 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 mail
import (
"bytes"
"context"
"crypto/tls"
"fmt"
"html/template"
"net/mail"
"net/smtp"
"strings"
"bsm/full/module/base/sender/internal/config"
"bsm/full/module/base/sender/internal/excode"
"bsm/full/module/base/sender/internal/impl"
"bsm/full/module/base/sender/internal/models"
pb "bsm/full/module/base/sender/pb"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/vars"
)
func Send(ctx context.Context, in *pb.SendMailRequest) (reply *pb.SendMailReply, err error) {
provider := strings.ToLower(in.GetProvider())
// 校验参数
if in.GetTemplateKey() == "" || provider == "" || in.GetTo() == "" {
return nil, errcode.ErrInvalidArgument
}
// 校验配置
cfg, ok := config.Spec.SMTP[provider]
if !ok || cfg == nil {
return nil, excode.ErrProviderIsNil
}
// 检验邮箱格式
if !ValidateEmail(in.GetTo()) {
return nil, excode.ErrEmail
}
// 获取模板
var tplRecord models.SenderTemplate
err = impl.DBService.Where("key=?", in.GetTemplateKey()).First(&tplRecord).Error
if err != nil {
return nil, errcode.ErrNotFound(1404, "template")
}
// 解析模板
tmpl, err := template.New("page").Parse(tplRecord.Body)
if err != nil {
return nil, excode.ErrTemplate
}
// 发送邮件
switch provider {
case "qq":
err = QQ(cfg, tmpl, in.GetTo(), tplRecord.Subjet, in.GetParamters())
default:
return nil, excode.ErrNotProvider
}
if err != nil {
return nil, err
}
return &pb.SendMailReply{
Data: vars.OK,
}, nil
}
func ValidateEmail(s string) bool {
_, err := mail.ParseAddress(s)
return err == nil
}
func QQ(cfg *config.SmtpConf, tmpl *template.Template, to string, subject string, args map[string]string) error {
// 建立TLS加密连接
conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", cfg.Endpoint, cfg.Port), &tls.Config{
ServerName: cfg.Endpoint,
MinVersion: tls.VersionTLS12, // 强制TLS1.2+
InsecureSkipVerify: false,
})
if err != nil {
fmt.Println("TLS连接失败: ", err)
return err
}
// 创建SMTP客户端带超时控制
client, err := smtp.NewClient(conn, cfg.Endpoint)
if err != nil {
client.Close()
fmt.Println("SMTP客户端初始化失败: ", err)
return err
}
// 设置认证
auth := smtp.PlainAuth("", cfg.Username, cfg.Password, cfg.Endpoint)
if err := client.Auth(auth); err != nil {
client.Close()
fmt.Println("认证失败: ", err)
return err
}
// 设置发件人和收件人
err = client.Mail(cfg.FromAddress)
if err != nil {
client.Close()
fmt.Println("发件人设置失败: ", err)
return err
}
err = client.Rcpt(to)
if err != nil {
fmt.Println("发件人设置失败: ", err)
client.Close()
return err
}
// 创建一个写入SMTP服务器的标准写入器
writer, err := client.Data()
if err != nil {
client.Close()
return err
}
defer writer.Close()
// 构建邮件正文
mailBody := "From: " + cfg.FromName + "<" + cfg.FromAddress + ">\n"
mailBody += "To: " + to + "\n"
mailBody += "Subject: " + subject + "\n\n"
// 执行模板,将结果写入邮件正文
var buf bytes.Buffer
err = tmpl.Execute(&buf, args)
if err != nil {
return err
}
mailBody += buf.String()
// 将邮件正文发送到SMTP服务器
if _, err := writer.Write([]byte(mailBody)); err != nil {
client.Close()
fmt.Printf("写入邮件内容失败: %v", err)
return err
}
if err := writer.Close(); err != nil {
client.Close()
fmt.Printf("关闭数据流失败: %v", err)
return err
}
return nil
}