657 lines
18 KiB
Go
657 lines
18 KiB
Go
package mailyak
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"mime"
|
|
"mime/multipart"
|
|
"net/mail"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestMailYakFromHeader ensures the fromHeader method returns valid headers
|
|
func TestMailYakFromHeader(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
// Test description.
|
|
name string
|
|
// Receiver fields.
|
|
rfromAddr string
|
|
rfromName string
|
|
// Expected results.
|
|
want string
|
|
}{
|
|
{
|
|
"With name",
|
|
"dom@itsallbroken.com",
|
|
"Dom",
|
|
"From: Dom <dom@itsallbroken.com>\r\n",
|
|
},
|
|
{
|
|
"Without name",
|
|
"dom@itsallbroken.com",
|
|
"",
|
|
"From: dom@itsallbroken.com\r\n",
|
|
},
|
|
{
|
|
"Without either",
|
|
"",
|
|
"",
|
|
"From: \r\n",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := MailYak{
|
|
fromAddr: tt.rfromAddr,
|
|
fromName: tt.rfromName,
|
|
}
|
|
|
|
if got := m.fromHeader(); got != tt.want {
|
|
t.Errorf("%q. MailYak.fromHeader() = %v, want %v", tt.name, got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestMailYakWriteHeaders ensures the MIME-Version, Date, Reply-To, From, To and
|
|
// Subject headers are correctly wrote
|
|
func TestMailYakWriteHeaders(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Now().Format(time.RFC1123Z)
|
|
tests := []struct {
|
|
// Test description.
|
|
name string
|
|
// Receiver fields.
|
|
rtoAddrs []string
|
|
rccAddrs []string
|
|
rbccAddrs []string
|
|
rsubject string
|
|
rreplyTo string
|
|
rwriteBccHeader bool
|
|
// Expected results.
|
|
wantBuf string
|
|
}{
|
|
{
|
|
"All fields",
|
|
[]string{"test@itsallbroken.com"},
|
|
[]string{},
|
|
[]string{},
|
|
"Test",
|
|
"help@itsallbroken.com",
|
|
true,
|
|
"From: Dom <dom@itsallbroken.com>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nReply-To: help@itsallbroken.com\r\nSubject: Test\r\nTo: test@itsallbroken.com\r\n",
|
|
},
|
|
{
|
|
"No reply-to",
|
|
[]string{"test@itsallbroken.com"},
|
|
[]string{},
|
|
[]string{},
|
|
"",
|
|
"",
|
|
true,
|
|
"From: Dom <dom@itsallbroken.com>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: test@itsallbroken.com\r\n",
|
|
},
|
|
{
|
|
"Multiple To addresses",
|
|
[]string{"test@itsallbroken.com", "repairs@itsallbroken.com"},
|
|
[]string{},
|
|
[]string{},
|
|
"",
|
|
"",
|
|
true,
|
|
"From: Dom <dom@itsallbroken.com>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: test@itsallbroken.com,repairs@itsallbroken.com\r\n",
|
|
},
|
|
{
|
|
"Single Cc address, Multiple To addresses",
|
|
[]string{"test@itsallbroken.com", "repairs@itsallbroken.com"},
|
|
[]string{"cc@itsallbroken.com"},
|
|
[]string{},
|
|
"",
|
|
"",
|
|
true,
|
|
"From: Dom <dom@itsallbroken.com>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: test@itsallbroken.com,repairs@itsallbroken.com\r\nCC: cc@itsallbroken.com\r\n",
|
|
},
|
|
{
|
|
"Multiple Cc addresses, Multiple To addresses",
|
|
[]string{"test@itsallbroken.com", "repairs@itsallbroken.com"},
|
|
[]string{"cc1@itsallbroken.com", "cc2@itsallbroken.com"},
|
|
[]string{},
|
|
"",
|
|
"",
|
|
true,
|
|
"From: Dom <dom@itsallbroken.com>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: test@itsallbroken.com,repairs@itsallbroken.com\r\nCC: cc1@itsallbroken.com,cc2@itsallbroken.com\r\n",
|
|
},
|
|
{
|
|
"Single Bcc address, Multiple To addresses",
|
|
[]string{"test@itsallbroken.com", "repairs@itsallbroken.com"},
|
|
[]string{},
|
|
[]string{"bcc@itsallbroken.com"},
|
|
"",
|
|
"",
|
|
true,
|
|
"From: Dom <dom@itsallbroken.com>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: test@itsallbroken.com,repairs@itsallbroken.com\r\nBCC: bcc@itsallbroken.com\r\n",
|
|
},
|
|
{
|
|
"Multiple Bcc addresses, Multiple To addresses",
|
|
[]string{"test@itsallbroken.com", "repairs@itsallbroken.com"},
|
|
[]string{},
|
|
[]string{"bcc1@itsallbroken.com", "bcc2@itsallbroken.com"},
|
|
"",
|
|
"",
|
|
true,
|
|
"From: Dom <dom@itsallbroken.com>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: test@itsallbroken.com,repairs@itsallbroken.com\r\nBCC: bcc1@itsallbroken.com,bcc2@itsallbroken.com\r\n",
|
|
},
|
|
{
|
|
"Multiple Bcc addresses, Multiple To addresses",
|
|
[]string{"test@itsallbroken.com", "repairs@itsallbroken.com"},
|
|
[]string{},
|
|
[]string{"bcc1@itsallbroken.com", "bcc2@itsallbroken.com"},
|
|
"",
|
|
"",
|
|
false,
|
|
"From: Dom <dom@itsallbroken.com>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: test@itsallbroken.com,repairs@itsallbroken.com\r\n",
|
|
},
|
|
{
|
|
"All together now",
|
|
[]string{"test@itsallbroken.com", "repairs@itsallbroken.com"},
|
|
[]string{"cc1@itsallbroken.com", "cc2@itsallbroken.com"},
|
|
[]string{"bcc1@itsallbroken.com", "bcc2@itsallbroken.com"},
|
|
"",
|
|
"",
|
|
true,
|
|
"From: Dom <dom@itsallbroken.com>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: test@itsallbroken.com,repairs@itsallbroken.com\r\nCC: cc1@itsallbroken.com,cc2@itsallbroken.com\r\nBCC: bcc1@itsallbroken.com,bcc2@itsallbroken.com\r\n",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := MailYak{
|
|
toAddrs: tt.rtoAddrs,
|
|
subject: tt.rsubject,
|
|
fromAddr: "dom@itsallbroken.com",
|
|
fromName: "Dom",
|
|
replyTo: tt.rreplyTo,
|
|
ccAddrs: tt.rccAddrs,
|
|
bccAddrs: tt.rbccAddrs,
|
|
writeBccHeader: tt.rwriteBccHeader,
|
|
date: now,
|
|
}
|
|
|
|
buf := &bytes.Buffer{}
|
|
if err := m.writeHeaders(buf); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if gotBuf := buf.String(); gotBuf != tt.wantBuf {
|
|
t.Errorf("%q. MailYak.writeHeaders() = %v, want %v", tt.name, gotBuf, tt.wantBuf)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestMailYakWriteBody ensures the correct MIME parts are wrote for the body
|
|
func TestMailYakWriteBody(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
// Test description.
|
|
name string
|
|
// Receiver fields.
|
|
rHTML string
|
|
rPlain string
|
|
// Parameters.
|
|
boundary string
|
|
// Expected results.
|
|
wantW string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
"HTML",
|
|
"HTML",
|
|
"",
|
|
"t",
|
|
"--t\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Type: text/html; charset=UTF-8\r\n\r\nHTML\r\n--t--\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"Plain text",
|
|
"",
|
|
"Plain",
|
|
"t",
|
|
"--t\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\nPlain\r\n--t--\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"Both",
|
|
"HTML",
|
|
"Plain",
|
|
"t",
|
|
"--t\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\nPlain\r\n--t\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Type: text/html; charset=UTF-8\r\n\r\nHTML\r\n--t--\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"Both with long lines",
|
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
|
|
"t",
|
|
"--t\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tem=\r\npor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, q=\r\nuis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo cons=\r\nequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillu=\r\nm dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non pr=\r\noident, sunt in culpa qui officia deserunt mollit anim id est laborum.\r\n--t\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Type: text/html; charset=UTF-8\r\n\r\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tem=\r\npor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, q=\r\nuis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo cons=\r\nequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillu=\r\nm dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non pr=\r\noident, sunt in culpa qui officia deserunt mollit anim id est laborum.\r\n--t--\r\n",
|
|
false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := MailYak{}
|
|
m.HTML().WriteString(tt.rHTML)
|
|
m.Plain().WriteString(tt.rPlain)
|
|
|
|
w := &bytes.Buffer{}
|
|
if err := m.writeBody(w, tt.boundary); (err != nil) != tt.wantErr {
|
|
t.Fatalf("%q. MailYak.writeBody() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
|
}
|
|
|
|
if gotW := w.String(); gotW != tt.wantW {
|
|
t.Errorf("%q. MailYak.writeBody() = %v, want %v", tt.name, gotW, tt.wantW)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestMailYakBuildMime tests all the other mime-related bits combine in a sane way
|
|
func TestMailYakBuildMime(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
now := time.Now().Format(time.RFC1123Z)
|
|
tests := []struct {
|
|
// Test description.
|
|
name string
|
|
// Receiver fields.
|
|
rHTML []byte
|
|
rPlain []byte
|
|
rtoAddrs []string
|
|
rsubject string
|
|
rfromAddr string
|
|
rfromName string
|
|
rreplyTo string
|
|
rAttachemnt string
|
|
// Expected results.
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
"Empty",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"From: \r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: \r\n\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"HTML",
|
|
[]byte("HTML"),
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"From: \r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: \r\nContent-Type: multipart/mixed;\r\n\tboundary=\"mixed\"; charset=UTF-8\r\n\r\n--mixed\r\nContent-Type: multipart/alternative;\r\n\tboundary=\"alt\"\r\n\r\n--alt\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Type: text/html; charset=UTF-8\r\n\r\nHTML\r\n--alt--\r\n\r\n--mixed--\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"Plain",
|
|
[]byte{},
|
|
[]byte("Plain"),
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"From: \r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: \r\nContent-Type: multipart/mixed;\r\n\tboundary=\"mixed\"; charset=UTF-8\r\n\r\n--mixed\r\nContent-Type: multipart/alternative;\r\n\tboundary=\"alt\"\r\n\r\n--alt\r\nContent-Transfer-Encoding: quoted-printable\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\nPlain\r\n--alt--\r\n\r\n--mixed--\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"Attachemnt",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"attachment",
|
|
"From: \r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: \r\nContent-Type: multipart/mixed;\r\n\tboundary=\"mixed\"; charset=UTF-8\r\n\r\n--mixed\r\nContent-Disposition: attachment;\n\tfilename=\"testAttachment\"; name=\"testAttachment\"\r\nContent-ID: <testAttachment>\r\nContent-Transfer-Encoding: base64\r\nContent-Type: text/plain; charset=utf-8;\n\tfilename=\"testAttachment\"; name=\"testAttachment\"\r\n\r\nYXR0YWNobWVudA==\r\n--mixed--\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"Reply-To",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"reply",
|
|
"",
|
|
"From: \r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nReply-To: reply\r\nSubject: \r\nTo: \r\n\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"From name",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"name",
|
|
"",
|
|
"",
|
|
"From: name <>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: \r\n\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"From name + address",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"addr",
|
|
"name",
|
|
"",
|
|
"",
|
|
"From: name <addr>\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: \r\n\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"From",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"from",
|
|
"",
|
|
"",
|
|
"",
|
|
"From: from\r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: \r\n\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"Subject",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"subject",
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"From: \r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: subject\r\nTo: \r\n\r\n",
|
|
false,
|
|
},
|
|
{
|
|
"To addresses",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{"one", "two"},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
"From: \r\nMIME-Version: 1.0\r\nDate: " + now + "\r\nSubject: \r\nTo: one,two\r\n\r\n",
|
|
false,
|
|
},
|
|
}
|
|
|
|
regex := regexp.MustCompile("\r?\n")
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := &MailYak{
|
|
toAddrs: tt.rtoAddrs,
|
|
subject: tt.rsubject,
|
|
fromAddr: tt.rfromAddr,
|
|
fromName: tt.rfromName,
|
|
replyTo: tt.rreplyTo,
|
|
trimRegex: regex,
|
|
date: now,
|
|
}
|
|
m.HTML().Write(tt.rHTML)
|
|
m.Plain().Write(tt.rPlain)
|
|
if tt.rAttachemnt != "" {
|
|
m.Attach("testAttachment", strings.NewReader(tt.rAttachemnt))
|
|
}
|
|
|
|
buf := &bytes.Buffer{}
|
|
err := m.buildMimeWithBoundaries(buf, "mixed", "alt")
|
|
if (err != nil) != tt.wantErr {
|
|
t.Fatalf("%q. MailYak.buildMime() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
|
}
|
|
|
|
if buf.String() != tt.want {
|
|
t.Errorf("%q. MailYak.buildMime() = %v, want %v", tt.name, buf.String(), tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestMailYakBuildMime_withAttachments ensures attachments are correctly added to the MIME message
|
|
func TestMailYakBuildMime_withAttachments(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
// Test description.
|
|
name string
|
|
// Receiver fields.
|
|
rHTML []byte
|
|
rPlain []byte
|
|
rtoAddrs []string
|
|
rsubject string
|
|
rfromAddr string
|
|
rfromName string
|
|
rreplyTo string
|
|
rattachments []attachment
|
|
// Expected results.
|
|
wantAttach []string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
"No attachment",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
[]attachment{},
|
|
[]string{},
|
|
false,
|
|
},
|
|
{
|
|
"One attachment",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
[]attachment{
|
|
{"test.txt", strings.NewReader("content"), false, ""},
|
|
},
|
|
[]string{"Y29udGVudA=="},
|
|
false,
|
|
},
|
|
{
|
|
"One inline attachment",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
[]attachment{
|
|
{"test.txt", strings.NewReader("content"), true, ""},
|
|
},
|
|
[]string{"Y29udGVudA=="},
|
|
false,
|
|
},
|
|
{
|
|
"Two attachments",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
[]attachment{
|
|
{"test.txt", strings.NewReader("content"), false, ""},
|
|
{"another.txt", strings.NewReader("another"), false, ""},
|
|
},
|
|
[]string{"Y29udGVudA==", "YW5vdGhlcg=="},
|
|
false,
|
|
},
|
|
{
|
|
"Two inline attachments",
|
|
[]byte{},
|
|
[]byte{},
|
|
[]string{""},
|
|
"",
|
|
"",
|
|
"",
|
|
"",
|
|
[]attachment{
|
|
{"test.txt", strings.NewReader("content"), true, ""},
|
|
{"another.txt", strings.NewReader("another"), true, ""},
|
|
},
|
|
[]string{"Y29udGVudA==", "YW5vdGhlcg=="},
|
|
false,
|
|
},
|
|
}
|
|
|
|
regex := regexp.MustCompile("\r?\n")
|
|
|
|
for _, tt := range tests {
|
|
tt := tt
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
m := &MailYak{
|
|
toAddrs: tt.rtoAddrs,
|
|
subject: tt.rsubject,
|
|
fromAddr: tt.rfromAddr,
|
|
fromName: tt.rfromName,
|
|
replyTo: tt.rreplyTo,
|
|
attachments: tt.rattachments,
|
|
trimRegex: regex,
|
|
}
|
|
m.HTML().Write(tt.rHTML)
|
|
m.Plain().Write(tt.rPlain)
|
|
|
|
buf := &bytes.Buffer{}
|
|
err := m.buildMimeWithBoundaries(buf, "mixed", "alt")
|
|
if (err != nil) != tt.wantErr {
|
|
t.Fatalf("%q. MailYak.buildMime() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
|
}
|
|
|
|
seen := 0
|
|
msg, err := mail.ReadMessage(buf)
|
|
if err != nil {
|
|
t.Fatalf("%q. MailYak.buildMime() error %v", tt.name, err)
|
|
}
|
|
contentTypeHeader := msg.Header.Get("Content-Type")
|
|
if contentTypeHeader == "" {
|
|
if len(tt.rattachments) != 0 {
|
|
t.Errorf("%q. MailYak.buildMime() attachments were expected, but Content-Type header wasn't set", tt.name)
|
|
}
|
|
return
|
|
}
|
|
mediaType, mediaTypeParams, err := mime.ParseMediaType(contentTypeHeader)
|
|
if err != nil {
|
|
t.Fatalf("%q. MailYak.buildMime() error %v", tt.name, err)
|
|
}
|
|
if mediaType != "multipart/mixed" {
|
|
t.Fatalf("%q. MailYak.buildMime() Content-Type media type multipart/mixed was expected, but got %q", tt.name, mediaType)
|
|
}
|
|
mr := multipart.NewReader(msg.Body, mediaTypeParams["boundary"])
|
|
|
|
// Itterate over the mime parts, look for attachments
|
|
for contentTypeHeader != "" {
|
|
p, err := mr.NextPart()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
t.Errorf("%q. MailYak.buildMime() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
|
}
|
|
|
|
// Read the attachment data
|
|
slurp, err := ioutil.ReadAll(p)
|
|
if err != nil {
|
|
t.Errorf("%q. MailYak.buildMime() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
|
}
|
|
|
|
// Skip non-attachments
|
|
if p.Header.Get("Content-Disposition") == "" {
|
|
continue
|
|
}
|
|
|
|
// Run through our attachments looking for a match
|
|
for i, attch := range tt.rattachments {
|
|
// Check Disposition header
|
|
var disp string
|
|
if attch.inline {
|
|
disp = "inline; filename=%q; name=%q"
|
|
} else {
|
|
disp = "attachment; filename=%q; name=%q"
|
|
}
|
|
if p.Header.Get("Content-Disposition") != fmt.Sprintf(disp, attch.filename, attch.filename) {
|
|
continue
|
|
}
|
|
|
|
// Check data
|
|
if !bytes.Equal(slurp, []byte(tt.wantAttach[i])) {
|
|
fmt.Printf("Part %q: %q\n", p.Header.Get("Content-Disposition"), slurp)
|
|
continue
|
|
}
|
|
|
|
seen++
|
|
}
|
|
|
|
}
|
|
|
|
// Did we see all the expected attachments?
|
|
if seen != len(tt.rattachments) {
|
|
t.Errorf("%q. MailYak.buildMime() didn't find all attachments in mime body", tt.name)
|
|
}
|
|
})
|
|
}
|
|
}
|