smtp支持ssl

This commit is contained in:
Yun
2025-10-30 14:13:18 +08:00
parent 4522af82f3
commit e0939d8728
3 changed files with 115 additions and 18 deletions
+83 -1
View File
@@ -3,6 +3,7 @@ package smtp
import (
"bytes"
"context"
"crypto/tls"
"encoding/base64"
"errors"
"fmt"
@@ -45,7 +46,6 @@ func (l *Smtp) SetOption(ctx context.Context, opt ...interfaces.Option) (interfa
return nil, errors.New("not smtp")
}
l.auth = smtp.PlainAuth("", l.Options.Smtp.Username, l.Options.Smtp.Password, l.Options.Smtp.Host)
return l, nil
}
@@ -53,6 +53,16 @@ func (l *Smtp) Send(ctx context.Context, message interfaces.Message) error {
if l.Options.Smtp == nil {
return errors.New("not init")
}
if l.Options.Smtp.IsSSL {
//
return l.SendSSL(ctx, message)
}
return l.SendPlain(ctx, message)
}
// 明文
func (l *Smtp) SendPlain(ctx context.Context, message interfaces.Message) error {
// .Auth()
buffer := bytes.NewBuffer(nil)
boundary := "YunBoundaryYun"
@@ -148,10 +158,82 @@ func (l *Smtp) Send(ctx context.Context, message interfaces.Message) error {
buffer.WriteString("\r\n--" + boundary + "--\r\n")
b := buffer.Bytes()
l.auth = smtp.PlainAuth("", l.Options.Smtp.Username, l.Options.Smtp.Password, l.Options.Smtp.Host)
err := smtp.SendMail(l.Options.Smtp.Host+":"+l.Options.Smtp.Port, l.auth, l.Options.Smtp.Username, message.To, b)
return err
}
// SSL
func (l *Smtp) SendSSL(ctx context.Context, message interfaces.Message) error {
// 邮件内容格式(必须符合SMTP协议规范)
contentType := "Content-Type: text/html; charset=UTF-8"
msg := []byte("To: " + message.To[0] + "\r\n" +
"From: " + message.Form + "\r\n" +
"Subject: " + message.Subject + "\r\n" +
contentType + "\r\n\r\n" +
message.Body)
// 解析收件人(支持多个)
// toList := strings.Split(message.To, ",")
// 1. 建立TCP连接(SSL通常用465端口)
if l.Options.Smtp.Port == "" {
l.Options.Smtp.Port = "465"
}
host := l.Options.Smtp.Host + ":" + l.Options.Smtp.Port
conn, err := tls.Dial("tcp", host, &tls.Config{
InsecureSkipVerify: false, // 生产环境不建议跳过证书验证
ServerName: strings.Split(host, ":")[0], // 服务器域名(用于证书验证)
})
if err != nil {
return fmt.Errorf("连接服务器失败: %v", err)
}
defer conn.Close()
// 2. 创建SMTP客户端
client, err := smtp.NewClient(conn, strings.Split(host, ":")[0])
if err != nil {
return fmt.Errorf("创建SMTP客户端失败: %v", err)
}
// 3. 身份验证(使用登录邮箱和授权码)
auth := smtp.PlainAuth("", l.Options.Smtp.Username, l.Options.Smtp.Password, strings.Split(host, ":")[0])
if err := client.Auth(auth); err != nil {
return fmt.Errorf("身份验证失败: %v", err)
}
// 4. 设置发件人
if err := client.Mail(l.Options.Smtp.Username); err != nil {
return fmt.Errorf("设置发件人失败: %v", err)
}
// 5. 设置收件人(支持多个)
for _, addr := range message.To {
if err := client.Rcpt(addr); err != nil {
return fmt.Errorf("设置收件人 %s 失败: %v", addr, err)
}
}
// 6. 发送邮件内容
w, err := client.Data()
if err != nil {
return fmt.Errorf("获取数据写入流失败: %v", err)
}
_, err = w.Write(msg)
if err != nil {
return fmt.Errorf("写入邮件内容失败: %v", err)
}
err = w.Close()
if err != nil {
return fmt.Errorf("关闭写入流失败: %v", err)
}
// 7. 退出SMTP会话
return client.Quit()
}
// 格式化header
func (l *Smtp) writeHeader(buffer *bytes.Buffer, Header map[string]string) string {
header := ""