title: How to create a nested multipart / MIME envelope for Email in Go?
body: <p>I'm trying to figure out how to build <a href="https://stackoverflow.com/questions/3902455/mail-multipart-alternative-vs-multipart-mixed">multipart/mime envelopes</a> for emails in Go. The following code generates correctly-nested bodies - but the boundaries are not inserted correctly. </p>
  
  <p>You can see a demo on <a href="https://play.golang.org/p/XLc4DQFObRn" rel="noreferrer">https://play.golang.org/p/XLc4DQFObRn</a></p>
  
  <pre><code>package main
  
  import (
      "bytes"
      "fmt"
      "io"
      "log"
      "math/rand"
      "mime/multipart"
      "mime/quotedprintable"
      "net/textproto"
  )
  
  //  multipart/mixed
  //  |- multipart/related
  //  |  |- multipart/alternative
  //  |  |  |- text/plain
  //  |  |  `- text/html
  //  |  `- inlines..
  //  `- attachments..
  
  
  func main() {
  
      body := &amp;bytes.Buffer{}
      writer := multipart.NewWriter(body)
  
      var part io.Writer
      var err error
  
      // Text Content
      part, err = writer.CreatePart(textproto.MIMEHeader{"Content-Type": {"multipart/alternative"}})
      if err != nil {
          log.Fatal(err)
      }
  
      childWriter := multipart.NewWriter(part)
  
      var subpart io.Writer
      for _, contentType := range []string{"text/plain", "text/html"} {
          subpart, err = CreateQuoteTypePart(childWriter, contentType)
          if err != nil {
              log.Fatal(err)
          }
          _, err := subpart.Write([]byte("This is a line of text that needs to be wrapped by quoted-printable before it goes to far.\r\n\r\n"))
          if err != nil {
              log.Fatal(err)
          }
      }
  
      // Attachments
      filename := fmt.Sprintf("File_%d.jpg", rand.Int31())
      part, err = writer.CreatePart(textproto.MIMEHeader{"Content-Type": {"application/octet-stream"}, "Content-Disposition": {"attachment; filename=" + filename}})
      if err != nil {
          log.Fatal(err)
      }
      part.Write([]byte("AABBCCDDEEFF"))
  
      writer.Close()
  
      fmt.Print(`From: Bob &lt;bob@example.com&gt;
  To: Alice &lt;alias@example.com&gt;
  Subject: Formatted text mail
  MIME-Version: 1.0
  Content-Type: multipart/mixed; boundary=`)
      fmt.Println(writer.Boundary())
      fmt.Println(body.String())
  
  }
  
  // https://github.com/domodwyer/mailyak/blob/master/attachments.go#L142
  func CreateQuoteTypePart(writer *multipart.Writer, contentType string) (part io.Writer, err error) {
      header := textproto.MIMEHeader{
          "Content-Type":              []string{contentType},
          "Content-Transfer-Encoding": []string{"quoted-printable"},
      }
  
      part, err = writer.CreatePart(header)
      if err != nil {
          return
      }
      part = quotedprintable.NewWriter(part)
      return
  }
  </code></pre>
  
  <p>I want to stick to answers from the standard library (stdlib) and avoid <a href="https://github.com/domodwyer/mailyak/blob/master/mime.go#L57" rel="noreferrer">third</a> party <a href="https://github.com/scorredoira/email/blob/master/email.go#L171" rel="noreferrer">attempts</a> to wing it.</p>