168 lines
4.7 KiB
Go
168 lines
4.7 KiB
Go
package email
|
||
|
||
import (
|
||
"bytes"
|
||
"crypto/tls"
|
||
"fmt"
|
||
"mime"
|
||
"net/smtp"
|
||
"strings"
|
||
"time"
|
||
|
||
"sproutgate-backend/internal/storage"
|
||
)
|
||
|
||
func SendVerificationEmail(cfg storage.EmailConfig, to string, code string, expiresIn time.Duration) error {
|
||
if strings.TrimSpace(to) == "" {
|
||
return fmt.Errorf("email is required")
|
||
}
|
||
fromName := strings.TrimSpace(cfg.FromName)
|
||
if fromName == "" {
|
||
fromName = "萌芽账户认证中心"
|
||
}
|
||
fromAddress := strings.TrimSpace(cfg.FromAddress)
|
||
if fromAddress == "" {
|
||
return fmt.Errorf("from address is required")
|
||
}
|
||
username := strings.TrimSpace(cfg.Username)
|
||
if username == "" {
|
||
username = fromAddress
|
||
}
|
||
subject := "萌芽账户认证中心 - 邮箱验证"
|
||
encodedName := mime.QEncoding.Encode("UTF-8", fromName)
|
||
fromHeader := fmt.Sprintf("%s <%s>", encodedName, fromAddress)
|
||
|
||
body := fmt.Sprintf("您的验证码是:%s\n有效期:%d 分钟\n\n如非本人操作,请忽略此邮件。",
|
||
code, int(expiresIn.Minutes()))
|
||
|
||
var msg bytes.Buffer
|
||
msg.WriteString("From: " + fromHeader + "\r\n")
|
||
msg.WriteString("To: " + to + "\r\n")
|
||
msg.WriteString("Subject: " + mime.QEncoding.Encode("UTF-8", subject) + "\r\n")
|
||
msg.WriteString("MIME-Version: 1.0\r\n")
|
||
msg.WriteString("Content-Type: text/plain; charset=\"UTF-8\"\r\n")
|
||
msg.WriteString("Content-Transfer-Encoding: 8bit\r\n")
|
||
msg.WriteString("\r\n")
|
||
msg.WriteString(body)
|
||
|
||
addr := fmt.Sprintf("%s:%d", cfg.SMTPHost, cfg.SMTPPort)
|
||
auth := smtp.PlainAuth("", username, cfg.Password, cfg.SMTPHost)
|
||
encryption := strings.ToUpper(strings.TrimSpace(cfg.Encryption))
|
||
|
||
if cfg.SMTPPort == 465 || encryption == "SSL" {
|
||
tlsConfig := &tls.Config{
|
||
ServerName: cfg.SMTPHost,
|
||
MinVersion: tls.VersionTLS12,
|
||
InsecureSkipVerify: false,
|
||
}
|
||
conn, err := tls.Dial("tcp", addr, tlsConfig)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
client, err := smtp.NewClient(conn, cfg.SMTPHost)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer client.Close()
|
||
if err := client.Auth(auth); err != nil {
|
||
return err
|
||
}
|
||
if err := client.Mail(fromAddress); err != nil {
|
||
return err
|
||
}
|
||
if err := client.Rcpt(to); err != nil {
|
||
return err
|
||
}
|
||
writer, err := client.Data()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if _, err := writer.Write(msg.Bytes()); err != nil {
|
||
return err
|
||
}
|
||
if err := writer.Close(); err != nil {
|
||
return err
|
||
}
|
||
return client.Quit()
|
||
}
|
||
|
||
return smtp.SendMail(addr, auth, fromAddress, []string{to}, msg.Bytes())
|
||
}
|
||
|
||
func SendResetPasswordEmail(cfg storage.EmailConfig, to string, code string, expiresIn time.Duration) error {
|
||
if strings.TrimSpace(to) == "" {
|
||
return fmt.Errorf("email is required")
|
||
}
|
||
fromName := strings.TrimSpace(cfg.FromName)
|
||
if fromName == "" {
|
||
fromName = "萌芽账户认证中心"
|
||
}
|
||
fromAddress := strings.TrimSpace(cfg.FromAddress)
|
||
if fromAddress == "" {
|
||
return fmt.Errorf("from address is required")
|
||
}
|
||
username := strings.TrimSpace(cfg.Username)
|
||
if username == "" {
|
||
username = fromAddress
|
||
}
|
||
subject := "萌芽账户认证中心 - 重置密码"
|
||
encodedName := mime.QEncoding.Encode("UTF-8", fromName)
|
||
fromHeader := fmt.Sprintf("%s <%s>", encodedName, fromAddress)
|
||
|
||
body := fmt.Sprintf("您的重置密码验证码是:%s\n有效期:%d 分钟\n\n如非本人操作,请忽略此邮件。",
|
||
code, int(expiresIn.Minutes()))
|
||
|
||
var msg bytes.Buffer
|
||
msg.WriteString("From: " + fromHeader + "\r\n")
|
||
msg.WriteString("To: " + to + "\r\n")
|
||
msg.WriteString("Subject: " + mime.QEncoding.Encode("UTF-8", subject) + "\r\n")
|
||
msg.WriteString("MIME-Version: 1.0\r\n")
|
||
msg.WriteString("Content-Type: text/plain; charset=\"UTF-8\"\r\n")
|
||
msg.WriteString("Content-Transfer-Encoding: 8bit\r\n")
|
||
msg.WriteString("\r\n")
|
||
msg.WriteString(body)
|
||
|
||
addr := fmt.Sprintf("%s:%d", cfg.SMTPHost, cfg.SMTPPort)
|
||
auth := smtp.PlainAuth("", username, cfg.Password, cfg.SMTPHost)
|
||
encryption := strings.ToUpper(strings.TrimSpace(cfg.Encryption))
|
||
|
||
if cfg.SMTPPort == 465 || encryption == "SSL" {
|
||
tlsConfig := &tls.Config{
|
||
ServerName: cfg.SMTPHost,
|
||
MinVersion: tls.VersionTLS12,
|
||
InsecureSkipVerify: false,
|
||
}
|
||
conn, err := tls.Dial("tcp", addr, tlsConfig)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
client, err := smtp.NewClient(conn, cfg.SMTPHost)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer client.Close()
|
||
if err := client.Auth(auth); err != nil {
|
||
return err
|
||
}
|
||
if err := client.Mail(fromAddress); err != nil {
|
||
return err
|
||
}
|
||
if err := client.Rcpt(to); err != nil {
|
||
return err
|
||
}
|
||
writer, err := client.Data()
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if _, err := writer.Write(msg.Bytes()); err != nil {
|
||
return err
|
||
}
|
||
if err := writer.Close(); err != nil {
|
||
return err
|
||
}
|
||
return client.Quit()
|
||
}
|
||
|
||
return smtp.SendMail(addr, auth, fromAddress, []string{to}, msg.Bytes())
|
||
}
|