package mailx import ( "bytes" "encoding/base64" "fmt" "net/smtp" "os" "path" "strings" "time" ) // 邮件发送的封装 // 1. 支持文本 // 2. 支持文件 type Mailx struct { user string password string host string port string auth smtp.Auth } type Attachment struct { Name string ContentType string WithFile bool } type Message struct { Form string To []string Cc []string Bcc []string Subject string Body string // ContentType string ReplyTo string Attachment []Attachment } func NewMailx(user, password, host, port string) *Mailx { m := &Mailx{ user: user, password: password, host: host, port: port, } m.auth = smtp.PlainAuth("", user, password, host) return m } func (m *Mailx) Send(message Message) error { // .Auth() buffer := bytes.NewBuffer(nil) boundary := "YunBoundaryYun" Header := make(map[string]string) // Header["From"] = "BOP<" + message.Form + ">" Header["From"] = m.user 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" m.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 += "--" + boundary + "--\r\n\r\n" buffer.WriteString(body) for _, value := range message.Attachment { newBuf := bytes.NewBuffer(nil) err := m.writeFile(newBuf, value.Name) if err != nil { fmt.Println("file err:", err) continue } f_name := path.Base(value.Name) 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") } if message.Form == "" { message.Form = m.user } imgBuf := bytes.NewBuffer(nil) err := m.writeFile(imgBuf, "./asset/余额宝.png") if err != nil { return fmt.Errorf("file err: %w", err) } f_name:= "f_name" attachment := "--" + boundary + "\r\n" attachment += "Content-Transfer-Encoding:base64\r\n" attachment += "Content-ID:myimage \r\n" attachment += "Content-Disposition:inline;filename=" + f_name + ".png \r\n" attachment += "Content-Type:image/png \r\n" buffer.WriteString(attachment) buffer.WriteString(imgBuf.String()) buffer.WriteString("\r\n--" + boundary + "--\r\n") b := buffer.Bytes() err = smtp.SendMail(m.host+":"+m.port, m.auth, message.Form, message.To, b) fmt.Println("发送结束:", err) fmt.Println(string(b)) return err } // 格式化header func (m *Mailx) 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 (m *Mailx) 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 }