How to create and send MIME messages with attachments in Go using the net/smtp package?

To create and send MIME messages with attachments in Go using the net/smtp package, you can follow the steps below:

  1. Import necessary packages:
package main import ( "net/smtp" "net/textproto" "mime/multipart" "mime/quotedprintable" "bytes" "io/ioutil" )
  1. Define your email message struct:
type EmailMessage struct { From string To []string Subject string TextBody string HTMLBody string Attachment []Attachment }
  1. Define your attachment struct:
type Attachment struct { Filename string Content []byte }
  1. Create a function to send the email:
func SendEmailMessage(smtpHost string, smtpPort int, smtpUsername string, smtpPassword string, message *EmailMessage) error { auth := smtp.PlainAuth("", smtpUsername, smtpPassword, smtpHost) // Convert the email message into MIME format mimeMessage := messageToMIME(message) // Connect to the SMTP server smtpAddr := fmt.Sprintf("%s:%d", smtpHost, smtpPort) client, err := smtp.Dial(smtpAddr) if err != nil { return err } defer client.Close() if err = client.Auth(auth); err != nil { return err } if err = client.Mail(message.From); err != nil { return err } // Loop through the recipients and add them to the email for _, recipient := range message.To { if err = client.Rcpt(recipient); err != nil { return err } } // Create a data writer to write the email data dataWriter, err := client.Data() if err != nil { return err } defer dataWriter.Close() // Write the MIME message to the data writer _, err = dataWriter.Write(mimeMessage.Bytes()) if err != nil { return err } return nil }
  1. Create a function to convert the email message into MIME format:
func messageToMIME(message *EmailMessage) *bytes.Buffer { buffer := new(bytes.Buffer) writer := multipart.NewWriter(buffer) // Create a new text/plain part for the email body textPart, _ := writer.CreatePart(textproto.MIMEHeader{ "Content-Type": []string{"text/plain; charset=utf-8"}, }) textPart.Write([]byte(message.TextBody)) // Create a new text/html part for the email body if HTML body is present if message.HTMLBody != "" { htmlPart, _ := writer.CreatePart(textproto.MIMEHeader{ "Content-Type": []string{"text/html; charset=utf-8"}, }) htmlPart.Write([]byte(message.HTMLBody)) } // Add attachments to the email for _, attachment := range message.Attachment { part, _ := writer.CreateFormFile("attachment", attachment.Filename) part.Write(attachment.Content) } writer.Close() return buffer }
  1. Test sending an email:
func main() { // Define the email message message := &EmailMessage{ From: "[email protected]", To: []string{"[email protected]"}, Subject: "Test Email with Attachment", TextBody: "This is a test email with an attachment.", HTMLBody: "<html><body><h1>This is a test email with an attachment.</h1></body></html>", Attachment: []Attachment{ { Filename: "example.txt", Content: []byte("This is the content of the attachment."), }, }, } // Call the send email function with your SMTP details err := SendEmailMessage("smtp.example.com", 587, "[email protected]", "password", message) if err != nil { fmt.Println("Error sending email:", err) } else { fmt.Println("Email sent successfully!") } }

Ensure that you replace the placeholders smtp.example.com with your SMTP server's address, 587 with the SMTP server's port, [email protected] with the sender's email address, and [email protected] with the recipient's email address.