support send email use TLS

This commit is contained in:
RockYang 2024-04-19 12:04:59 +08:00
parent 336a7d5b56
commit b584b4bfb6
2 changed files with 85 additions and 4 deletions

View File

@ -30,6 +30,7 @@ type AppConfig struct {
} }
type SmtpConfig struct { type SmtpConfig struct {
UseTls bool // 是否使用 TLS 发送
Host string Host string
Port int Port int
AppName string // 应用名称 AppName string // 应用名称

View File

@ -3,9 +3,11 @@ package service
import ( import (
"bytes" "bytes"
"chatplus/core/types" "chatplus/core/types"
"crypto/tls"
"fmt" "fmt"
"mime" "mime"
"net/smtp" "net/smtp"
"net/textproto"
) )
type SmtpService struct { type SmtpService struct {
@ -19,12 +21,18 @@ func NewSmtpService(appConfig *types.AppConfig) *SmtpService {
} }
func (s *SmtpService) SendVerifyCode(to string, code int) error { func (s *SmtpService) SendVerifyCode(to string, code int) error {
subject := "ChatPlus注册验证码" subject := "Geek-AI 注册验证码"
body := fmt.Sprintf("您正在注册 ChatPlus AI 助手账户,注册验证码为 %d请不要告诉他人。如非本人操作请忽略此邮件。", code) body := fmt.Sprintf("您正在注册 Geek-AI 助手账户,注册验证码为 %d请不要告诉他人。如非本人操作请忽略此邮件。", code)
// 设置SMTP客户端配置
auth := smtp.PlainAuth("", s.config.From, s.config.Password, s.config.Host) auth := smtp.PlainAuth("", s.config.From, s.config.Password, s.config.Host)
if s.config.UseTls {
return s.sendTLS(auth, to, subject, body)
} else {
return s.send(auth, to, subject, body)
}
}
func (s *SmtpService) send(auth smtp.Auth, to string, subject string, body string) error {
// 对主题进行MIME编码 // 对主题进行MIME编码
encodedSubject := mime.QEncoding.Encode("UTF-8", subject) encodedSubject := mime.QEncoding.Encode("UTF-8", subject)
// 组装邮件 // 组装邮件
@ -34,11 +42,83 @@ func (s *SmtpService) SendVerifyCode(to string, code int) error {
message.WriteString(fmt.Sprintf("Subject: %s\r\n", encodedSubject)) message.WriteString(fmt.Sprintf("Subject: %s\r\n", encodedSubject))
message.WriteString("\r\n" + body) message.WriteString("\r\n" + body)
// 发送邮件
// 发送邮件 // 发送邮件
err := smtp.SendMail(s.config.Host+":"+fmt.Sprint(s.config.Port), auth, s.config.From, []string{to}, message.Bytes()) err := smtp.SendMail(s.config.Host+":"+fmt.Sprint(s.config.Port), auth, s.config.From, []string{to}, message.Bytes())
if err != nil { if err != nil {
return fmt.Errorf("error sending email: %v", err) return fmt.Errorf("error sending email: %v", err)
} }
return err
}
func (s *SmtpService) sendTLS(auth smtp.Auth, to string, subject string, body string) error {
// TLS配置
tlsConfig := &tls.Config{
ServerName: s.config.Host,
}
// 建立TLS连接
conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", s.config.Host, s.config.Port), tlsConfig)
if err != nil {
return fmt.Errorf("error connecting to SMTP server: %v", err)
}
defer conn.Close()
client, err := smtp.NewClient(conn, s.config.Host)
if err != nil {
return fmt.Errorf("error creating SMTP client: %v", err)
}
defer client.Quit()
// 身份验证
if err = client.Auth(auth); err != nil {
return fmt.Errorf("error authenticating: %v", err)
}
// 设置寄件人
if err = client.Mail(s.config.From); err != nil {
return fmt.Errorf("error setting sender: %v", err)
}
// 设置收件人
if err = client.Rcpt(to); err != nil {
return fmt.Errorf("error setting recipient: %v", err)
}
// 发送邮件内容
wc, err := client.Data()
if err != nil {
return fmt.Errorf("error getting data writer: %v", err)
}
defer wc.Close()
header := make(textproto.MIMEHeader)
header.Set("From", s.config.From)
header.Set("To", to)
header.Set("Subject", subject)
// 将邮件头写入
for key, values := range header {
for _, value := range values {
_, err = fmt.Fprintf(wc, "%s: %s\r\n", key, value)
if err != nil {
return fmt.Errorf("error sending email header: %v", err)
}
}
}
_, _ = fmt.Fprintln(wc)
// 将邮件内容写入
_, err = fmt.Fprintf(wc, body)
if err != nil {
return fmt.Errorf("error sending email: %v", err)
}
// 发送完毕
err = wc.Close()
if err != nil {
return fmt.Errorf("error closing data writer: %v", err)
}
return nil return nil
} }