Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 81 additions & 48 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

const crlf = "\r\n"

var ErrMissingRecipient = errors.New("No recipient specified. At one To, Cc, or Bcc recipient is required.")
var ErrMissingRecipient = errors.New("No recipient specified. At least one To, Cc, or Bcc recipient is required.")
var ErrMissingFromAddress = errors.New("No from address specified.")

// A Message represents an email message.
Expand Down Expand Up @@ -177,88 +177,122 @@ func (m *Message) Bytes() ([]byte, error) {
header[k] = v
}

// Top level multipart writer for our `multipart/mixed` body.
mixedw := multipart.NewWriter(buffer)

header.Add("MIME-Version", "1.0")
header.Add("Content-Type", fmt.Sprintf("multipart/mixed;%s boundary=%s", crlf, mixedw.Boundary()))

err = writeHeader(buffer, header)
if err != nil {
return nil, err
}

// Write the start of our `multipart/mixed` body.
_, err = fmt.Fprintf(buffer, "--%s%s", mixedw.Boundary(), crlf)
if err != nil {
return nil, err
var mixedw *multipart.Writer
var hasAttachments = m.Attachments != nil && len(m.Attachments) > 0
if hasAttachments {
// Top level multipart writer for our `multipart/mixed` body.
// only needed if we have attachments
mixedw = multipart.NewWriter(buffer)
header.Add("Content-Type", fmt.Sprintf("multipart/mixed;%s boundary=%s", crlf, mixedw.Boundary()))
err = writeHeader(buffer, header)
if err != nil {
return nil, err
}
header = textproto.MIMEHeader{}
// Write the start of our `multipart/mixed` body.
_, err = fmt.Fprintf(buffer, "--%s%s", mixedw.Boundary(), crlf)
if err != nil {
return nil, err
}
}

// Does the message have a body?
if m.Body != "" || m.HTMLBody != "" {

var altw *multipart.Writer
if m.Body != "" && m.HTMLBody != "" {
// Nested multipart writer for our `multipart/alternative` body.
altw := multipart.NewWriter(buffer)
altw = multipart.NewWriter(buffer)

header = textproto.MIMEHeader{}
header.Add("Content-Type", fmt.Sprintf("multipart/alternative;%s boundary=%s", crlf, altw.Boundary()))
err := writeHeader(buffer, header)
if err != nil {
return nil, err
}
}

if m.Body != "" {
// Only include an empty plain text body if the html body is also empty.
if m.Body != "" || m.Body == "" && m.HTMLBody == "" {
if altw != nil {
header = textproto.MIMEHeader{}
header.Add("Content-Type", "text/plain; charset=utf-8")
header.Add("Content-Transfer-Encoding", "quoted-printable")
//header.Add("Content-Transfer-Encoding", "base64")
}
header.Add("Content-Type", "text/plain; charset=utf-8")
header.Add("Content-Transfer-Encoding", "quoted-printable")
//header.Add("Content-Transfer-Encoding", "base64")

var writer io.Writer
if altw != nil {
partw, err := altw.CreatePart(header)
if err != nil {
return nil, err
}

bodyBytes := []byte(m.Body)
//encoder := NewBase64MimeEncoder(partw)
encoder := qprintable.NewEncoder(qprintable.DetectEncoding(m.Body), partw)
_, err = encoder.Write(bodyBytes)
if err != nil {
return nil, err
}
err = encoder.Close()
writer = partw
} else {
writer = buffer
err = writeHeader(buffer, header)
if err != nil {
return nil, err
}
}

if m.HTMLBody != "" {
bodyBytes := []byte(m.Body)
//encoder := NewBase64MimeEncoder(writer)
encoder := qprintable.NewEncoder(qprintable.DetectEncoding(m.Body), writer)
_, err = encoder.Write(bodyBytes)
if err != nil {
return nil, err
}
err = encoder.Close()
if err != nil {
return nil, err
}
}

if m.HTMLBody != "" {
if altw != nil {
header = textproto.MIMEHeader{}
header.Add("Content-Type", "text/html; charset=utf-8")
//header.Add("Content-Transfer-Encoding", "quoted-printable")
header.Add("Content-Transfer-Encoding", "base64")
}
header.Add("Content-Type", "text/html; charset=utf-8")
//header.Add("Content-Transfer-Encoding", "quoted-printable")
header.Add("Content-Transfer-Encoding", "base64")

var writer io.Writer
if altw != nil {
partw, err := altw.CreatePart(header)
if err != nil {
return nil, err
}

htmlBodyBytes := []byte(m.HTMLBody)
encoder := NewBase64MimeEncoder(partw)
//encoder := qprintable.NewEncoder(qprintable.DetectEncoding(m.HTMLBody), partw)
_, err = encoder.Write(htmlBodyBytes)
if err != nil {
return nil, err
}
err = encoder.Close()
writer = partw
} else {
writer = buffer
err = writeHeader(buffer, header)
if err != nil {
return nil, err
}
}

htmlBodyBytes := []byte(m.HTMLBody)
encoder := NewBase64MimeEncoder(writer)
//encoder := qprintable.NewEncoder(qprintable.DetectEncoding(m.HTMLBody), writer)
_, err = encoder.Write(htmlBodyBytes)
if err != nil {
return nil, err
}
err = encoder.Close()
if err != nil {
return nil, err
}
}

if altw != nil {
altw.Close()
} else {
_, err = fmt.Fprintf(buffer, "%s", crlf)
if err != nil {
return nil, err
}
}

if m.Attachments != nil && len(m.Attachments) > 0 {
if hasAttachments {

for _, attachment := range m.Attachments {

Expand Down Expand Up @@ -293,10 +327,9 @@ func (m *Message) Bytes() ([]byte, error) {
}
}

mixedw.Close()
}

mixedw.Close()

return buffer.Bytes(), nil
}

Expand Down
Loading