diff --git a/message.go b/message.go index 4bffb1e..7733e5e 100644 --- a/message.go +++ b/message.go @@ -240,6 +240,7 @@ func SetPartEncoding(e Encoding) PartSetting { type file struct { Name string + originalName string Header map[string][]string CopyFunc func(w io.Writer) error } @@ -285,6 +286,7 @@ func SetCopyFunc(f func(io.Writer) error) FileSetting { func (m *Message) appendFile(list []*file, name string, settings []FileSetting) []*file { f := &file{ + originalName: filepath.Base(name), Name: filepath.Base(name), Header: make(map[string][]string), CopyFunc: func(w io.Writer) error { diff --git a/message_test.go b/message_test.go index acceff2..ea3d7f5 100644 --- a/message_test.go +++ b/message_test.go @@ -1,6 +1,7 @@ package gomail import ( + "os" "bytes" "encoding/base64" "io" @@ -256,6 +257,9 @@ func TestAttachmentOnly(t *testing.T) { } testMessage(t, m, 0, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } } func TestAttachment(t *testing.T) { @@ -288,6 +292,9 @@ func TestAttachment(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } } func TestRename(t *testing.T) { @@ -297,6 +304,8 @@ func TestRename(t *testing.T) { m.SetBody("text/plain", "Test") name, copy := mockCopyFile("/tmp/test.pdf") rename := Rename("another.pdf") + + m.Attach(name, copy, rename) want := &message{ @@ -322,6 +331,9 @@ func TestRename(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } } func TestAttachmentsOnly(t *testing.T) { @@ -355,6 +367,12 @@ func TestAttachmentsOnly(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } + if err := teardownFile("/tmp/test.zip"); err != nil { + panic(err) + } } func TestAttachments(t *testing.T) { @@ -394,6 +412,12 @@ func TestAttachments(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("/tmp/test.pdf"); err != nil { + panic(err) + } + if err := teardownFile("/tmp/test.zip"); err != nil { + panic(err) + } } func TestEmbedded(t *testing.T) { @@ -435,6 +459,12 @@ func TestEmbedded(t *testing.T) { } testMessage(t, m, 1, want) + if err := teardownFile("image1.jpg"); err != nil { + panic(err) + } + if err := teardownFile("image2.jpg"); err != nil { + panic(err) + } } func TestFullMessage(t *testing.T) { @@ -494,6 +524,14 @@ func TestFullMessage(t *testing.T) { testMessage(t, m, 3, want) + if err := teardownFile("test.pdf"); err != nil { + panic(err) + } + if err := teardownFile("image.jpg"); err != nil { + panic(err) + } + + want = &message{ from: "from@example.com", to: []string{"to@example.com"}, @@ -705,6 +743,7 @@ func getBoundaries(t *testing.T, count int, m string) []string { var boundaryRegExp = regexp.MustCompile("boundary=(\\w+)") func mockCopyFile(name string) (string, FileSetting) { + os.Create(filepath.Base(name)) return name, SetCopyFunc(func(w io.Writer) error { _, err := w.Write([]byte("Content of " + filepath.Base(name))) return err @@ -716,6 +755,10 @@ func mockCopyFileWithHeader(m *Message, name string, h map[string][]string) (str return name, f, SetHeader(h) } +func teardownFile(name string) error { + return os.Remove(filepath.Base(name)) +} + func BenchmarkFull(b *testing.B) { discardFunc := SendFunc(func(from string, to []string, m io.WriterTo) error { _, err := m.WriteTo(ioutil.Discard) @@ -741,5 +784,11 @@ func BenchmarkFull(b *testing.B) { panic(err) } m.Reset() + if err := teardownFile("benchmark.txt"); err != nil { + panic(err) + } + if err := teardownFile("benchmark.jpg"); err != nil { + panic(err) + } } } diff --git a/send.go b/send.go index 9115ebe..99a6dd8 100644 --- a/send.go +++ b/send.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/mail" + "os" ) // Sender is the interface that wraps the Send method. @@ -54,6 +55,10 @@ func send(s Sender, m *Message) error { return err } + if err := m.checkEmbedsAndAttachments(); err != nil { + return err + } + if err := s.Send(from, to, m); err != nil { return err } @@ -97,6 +102,20 @@ func (m *Message) getRecipients() ([]string, error) { return list, nil } +func (m *Message) checkEmbedsAndAttachments() error { + for _, file := range m.embedded { + if _, err := os.Stat(file.originalName); err != nil { + return err + } + } + for _, file := range m.attachments { + if _, err := os.Stat(file.originalName); err != nil { + return err + } + } + return nil +} + func addAddress(list []string, addr string) []string { for _, a := range list { if addr == a { diff --git a/send_test.go b/send_test.go index ba59cd3..a5b426f 100644 --- a/send_test.go +++ b/send_test.go @@ -5,6 +5,7 @@ import ( "io" "reflect" "testing" + "strings" ) const ( @@ -50,6 +51,47 @@ func TestSend(t *testing.T) { } } +func TestSendValidatesEmbeds(t *testing.T) { + s := &mockSendCloser{ + mockSender: stubSend(t, testFrom, []string{testTo1, testTo2}, testMsg), + close: func() error { + t.Error("Close() should not be called in Send()") + return nil + }, + } + + m := getTestMessage() + m.Embed("this-file-does-not-exist") + + err := Send(s, m) + if err == nil || !strings.HasSuffix(err.Error(), + "no such file or directory") { + t.Errorf("Send(): expected stat error but got %v", err) + } +} + + +func TestSendValidatesAttachments(t *testing.T) { + s := &mockSendCloser{ + mockSender: stubSend(t, testFrom, []string{testTo1, testTo2}, testMsg), + close: func() error { + t.Error("Close() should not be called in Send()") + return nil + }, + } + + m := getTestMessage() + m.Attach("this-file-does-not-exist") + + err := Send(s, m) + if err == nil || !strings.HasSuffix(err.Error(), + "no such file or directory") { + t.Errorf("Send(): expected stat error but got %v", err) + } +} + + + func getTestMessage() *Message { m := NewMessage() m.SetHeader("From", testFrom)