186 lines
4.5 KiB
Go
186 lines
4.5 KiB
Go
package smtp
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"net/smtp"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"code.yun.ink/pkg/mailx/interfaces"
|
|
)
|
|
|
|
// 邮件发送的封装
|
|
// 1. 支持文本
|
|
// 2. 支持文件
|
|
|
|
type Smtp struct {
|
|
interfaces.DefaultEmail
|
|
// params *interfaces.EmailConfigDataSmtp
|
|
auth smtp.Auth
|
|
// logger loggerx.LoggerInterface
|
|
}
|
|
|
|
func NewSmtp() *Smtp {
|
|
smtp := &Smtp{}
|
|
smtp.Options = interfaces.DefaultOptions()
|
|
smtp.EmailType = "Smtp"
|
|
return smtp
|
|
}
|
|
|
|
func (l *Smtp) SetOption(ctx context.Context, opt ...interfaces.Option) (interfaces.EmailInterface, error) {
|
|
|
|
for _, o := range opt {
|
|
o(&l.Options)
|
|
}
|
|
|
|
l.Options.Logger.Infof(ctx, "params:%+v", l.Options.Smtp)
|
|
|
|
if l.Options.Smtp == nil {
|
|
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
|
|
}
|
|
|
|
func (l *Smtp) Send(ctx context.Context, message interfaces.Message) error {
|
|
if l.Options.Smtp == nil {
|
|
return errors.New("not init")
|
|
}
|
|
// .Auth()
|
|
buffer := bytes.NewBuffer(nil)
|
|
boundary := "YunBoundaryYun"
|
|
|
|
Header := make(map[string]string)
|
|
// Header["From"] = "BOP<" + message.Form + ">"
|
|
|
|
if message.Form != "" {
|
|
Header["From"] = message.Form
|
|
} else {
|
|
Header["From"] = l.Options.Smtp.Username
|
|
}
|
|
|
|
if len(message.To) > 0 {
|
|
str := ""
|
|
for _, val := range message.To {
|
|
name := ""
|
|
s := strings.Split(val, "@")
|
|
if len(s) > 0 {
|
|
name = s[0]
|
|
}
|
|
str = str + "," + name + "<" + val + ">"
|
|
}
|
|
Header["To"] = strings.Trim(str, ",")
|
|
// Header["To"] = strings.Join(message.To, ",")
|
|
}
|
|
if len(message.Cc) > 0 {
|
|
str := ""
|
|
for _, val := range message.Cc {
|
|
name := ""
|
|
s := strings.Split(val, "@")
|
|
if len(s) > 0 {
|
|
name = s[0]
|
|
}
|
|
str = str + "," + name + "<" + val + ">"
|
|
}
|
|
Header["Cc"] = strings.Trim(str, ",")
|
|
// Header["Cc"] = strings.Join(message.Cc, ",")
|
|
}
|
|
if len(message.Bcc) > 0 {
|
|
str := ""
|
|
for _, val := range message.Bcc {
|
|
name := ""
|
|
s := strings.Split(val, "@")
|
|
if len(s) > 0 {
|
|
name = s[0]
|
|
}
|
|
str = str + "," + name + "<" + val + ">"
|
|
}
|
|
Header["Bcc"] = strings.Trim(str, ",")
|
|
// Header["Bcc"] = strings.Join(message.Bcc, ",")
|
|
}
|
|
|
|
Header["Subject"] = message.Subject
|
|
Header["Content-Type"] = "multipart/mixed; charset=UTF-8; boundary=" + boundary
|
|
Header["Date"] = time.Now().String()
|
|
Header["Reply-To"] = message.ReplyTo
|
|
|
|
Header["X-Priority"] = "3"
|
|
l.writeHeader(buffer, Header)
|
|
|
|
body := "--" + boundary + "\r\n"
|
|
// body += "Content-Type: text/plain; charset=UTF-8 \r\n"
|
|
body += "Content-Type: text/html;charset=utf-8\r\n"
|
|
body += "Content-Transfer-Encoding:quoted-printable\r\n\r\n"
|
|
// body += "<html><body><h1>huang</h1><h2>xin</h2></body></html>\r\n"
|
|
|
|
// body += "<html><body>" + message.Body + "</body></html>\r\n"
|
|
|
|
body += message.Body + "\r\n"
|
|
|
|
// body += "--" + boundary + "--\r\n\r\n"
|
|
buffer.WriteString(body)
|
|
|
|
for _, value := range message.Attachment {
|
|
newBuf := bytes.NewBuffer(nil)
|
|
err := l.writeFile(newBuf, value.Content)
|
|
if err != nil {
|
|
fmt.Println("file err:", err)
|
|
continue
|
|
}
|
|
|
|
f_name := path.Base(value.Content)
|
|
attachment := "--" + boundary + "\r\n"
|
|
attachment += "Content-Transfer-Encoding:base64\r\n"
|
|
attachment += "Content-Disposition:attachment;filename=" + f_name + "\r\n"
|
|
attachment += "Content-Type: application/octet-stream;charset=utf-8;name=" + f_name + "\r\n"
|
|
// attachment += "Contment-Type:" + message.attachment.contentType + ";name=\"" + message.attachment.name + "\"\r\n"
|
|
buffer.WriteString(attachment)
|
|
|
|
buffer.WriteString(newBuf.String())
|
|
}
|
|
|
|
buffer.WriteString("\r\n--" + boundary + "--\r\n")
|
|
b := buffer.Bytes()
|
|
err := smtp.SendMail(l.Options.Smtp.Host+":"+l.Options.Smtp.Port, l.auth, l.Options.Smtp.Username, message.To, b)
|
|
return err
|
|
}
|
|
|
|
// 格式化header
|
|
func (l *Smtp) writeHeader(buffer *bytes.Buffer, Header map[string]string) string {
|
|
header := ""
|
|
// header := "Content-Type: multipart/mixed;charset=UTF-8;boundary=\"YunBoundaryYun\" \r\n"
|
|
for key, value := range Header {
|
|
if value != "" {
|
|
header += key + ": " + value + "\r\n"
|
|
}
|
|
}
|
|
header += "\r\n"
|
|
buffer.WriteString(header)
|
|
return header
|
|
}
|
|
|
|
// 格式化文件
|
|
func (l *Smtp) writeFile(buffer *bytes.Buffer, fileName string) error {
|
|
file, err := os.ReadFile(fileName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
payload := make([]byte, base64.StdEncoding.EncodedLen(len(file)))
|
|
base64.StdEncoding.Encode(payload, file)
|
|
buffer.WriteString("\r\n")
|
|
for index, line := 0, len(payload); index < line; index++ {
|
|
buffer.WriteByte(payload[index])
|
|
if (index+1)%76 == 0 {
|
|
buffer.WriteString("\r\n")
|
|
}
|
|
}
|
|
return nil
|
|
}
|