package mailclient import ( "bytes" "encoding/base64" "fmt" "net/http" "os" "path/filepath" "strings" ) type Message struct { To []string From string Subject string Body string Attachments []Attachment } type Attachment struct { Name string Data []byte } func NewMessage(subject, body string) *Message { if subject == "" { subject = "Вам пришла заявка с PenaQuiz" } return &Message{Subject: subject, Body: body, Attachments: []Attachment{}} } func (m *Message) AttachFile(src string) error { data, err := os.ReadFile(src) if err != nil { return err } _, filename := filepath.Split(src) m.Attachments = append(m.Attachments, Attachment{Name: filename, Data: data}) return nil } func (m *Message) AttachBytesFile(filename string, data []byte) { m.Attachments = append(m.Attachments, Attachment{Name: filename, Data: data}) } func (m *Message) ToBytes() []byte { buf := bytes.NewBuffer(nil) buf.WriteString("MIME-Version: 1.0\r\n") fmt.Fprintf(buf, "From: %s\r\n", m.From) fmt.Fprintf(buf, "Subject: %s\r\n", m.Subject) fmt.Fprintf(buf, "To: %s\r\n", strings.Join(m.To, ",")) boundary := randomBoundary() if len(m.Attachments) > 0 { buf.WriteString("Content-Type: multipart/mixed;\r\n") fmt.Fprintf(buf, " boundary=\"%s\"\r\n", boundary) fmt.Fprintf(buf, "\r\n--%s", boundary) for _, attachment := range m.Attachments { buf.WriteString("\r\n") switch strings.Split(attachment.Name, ".")[1] { case "htmlmsg": buf.WriteString("Content-Type: text/html; charset=\"utf-8\"\r\n") buf.WriteString("Content-Transfer-Encoding: base64\r\n") case "docx": buf.WriteString("Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document\r\n") buf.WriteString("Content-Transfer-Encoding: base64\r\n") fmt.Fprintf(buf, "Content-Disposition: attachment; filename=\"%s\"\r\n", attachment.Name) default: fmt.Fprintf(buf, "Content-Type: %s\r\n", http.DetectContentType(attachment.Data)) buf.WriteString("Content-Transfer-Encoding: base64\r\n") fmt.Fprintf(buf, "Content-Disposition: attachment; filename=\"%s\"\r\n", attachment.Name) } buf.WriteString("\r\n") b := make([]byte, base64.StdEncoding.EncodedLen(len(attachment.Data))) base64.StdEncoding.Encode(b, attachment.Data) writer := NewLineWriter(buf, 76) _, err := writer.Write(b) if err != nil { fmt.Println("mailclient-client err:", err) } fmt.Fprintf(buf, "\r\n\r\n--%s", boundary) } buf.WriteString("--") } else { buf.WriteString("Content-Type: text/plain; charset=utf-8\r\n") buf.WriteString(m.Body) } return buf.Bytes() }