package smtp import ( "bytes" "context" "encoding/base64" "errors" "fmt" "net/smtp" "os" "path" "strings" "time" "code.yun.ink/pkg/mailx/interfaces" "github.com/yuninks/loggerx" ) // 邮件发送的封装 // 1. 支持文本 // 2. 支持文件 type Smtp struct { interfaces.DefaultEmail params *interfaces.EmailConfigDataSmtp auth smtp.Auth logger loggerx.LoggerInterface } func (l *Smtp) InitEmail(ctx context.Context, params interfaces.EmailConfigData, logger loggerx.LoggerInterface) (interfaces.Email, error) { if params.Smtp == nil { return nil, errors.New("not smtp") } l.logger.Infof(ctx, "params:%+v", params.Smtp) m := &Smtp{ params: params.Smtp, } m.auth = smtp.PlainAuth("", params.Smtp.Username, params.Smtp.Password, params.Smtp.Host) return m, nil } func (l *Smtp) Send(ctx context.Context, message interfaces.Message) error { if l.params == 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.params.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 += "

huang

xin

\r\n" // body += "" + message.Body + "\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.params.Host+":"+l.params.Port, l.auth, l.params.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 }