diff --git a/b64linebreaker.go b/b64linebreaker.go index ff99696..f471fe5 100644 --- a/b64linebreaker.go +++ b/b64linebreaker.go @@ -4,7 +4,13 @@ package mail -import "io" +import ( + "fmt" + "io" +) + +// ErrNoOutWriter is an error message that should be used if a Base64LineBreaker has no out io.Writer set +const ErrNoOutWriter = "no io.Writer set for Base64LineBreaker" // Base64LineBreaker is a io.WriteCloser that writes Base64 encoded data streams // with line breaks at a given line length @@ -19,6 +25,10 @@ var nl = []byte(SingleNewLine) // Write writes the data stream and inserts a SingleNewLine when the maximum // line length is reached func (l *Base64LineBreaker) Write(b []byte) (n int, err error) { + if l.out == nil { + err = fmt.Errorf(ErrNoOutWriter) + return + } if l.used+len(b) < MaxBodyLength { copy(l.line[l.used:], b) l.used += len(b) diff --git a/b64linebreaker_test.go b/b64linebreaker_test.go index 05c61c3..f2b3891 100644 --- a/b64linebreaker_test.go +++ b/b64linebreaker_test.go @@ -7,6 +7,7 @@ package mail import ( "bytes" "encoding/base64" + "fmt" "io" "os" "testing" @@ -410,6 +411,31 @@ func TestBase64LineBreaker(t *testing.T) { } } +// TestBase64LineBreakerFailures tests the cases in which the Base64LineBreaker would fail +func TestBase64LineBreakerFailures(t *testing.T) { + stt := []byte("short") + ltt := []byte(logoB64) + + // No output writer defined + lb := Base64LineBreaker{} + if _, err := lb.Write(stt); err == nil { + t.Errorf("writing to Base64LineBreaker with no output io.Writer was supposed to failed, but didn't") + } + if err := lb.Close(); err != nil { + t.Errorf("failed to close Base64LineBreaker: %s", err) + } + + // Closed output writer + wbuf := errorWriter{} + fb := Base64LineBreaker{out: wbuf} + if _, err := fb.Write(ltt); err == nil { + t.Errorf("writing to Base64LineBreaker with errorWriter was supposed to failed, but didn't") + } + if err := fb.Close(); err != nil { + t.Errorf("failed to close Base64LineBreaker: %s", err) + } +} + // removeNewLines removes any newline characters from the given data func removeNewLines(data []byte) []byte { result := make([]byte, len(data)) @@ -425,3 +451,13 @@ func removeNewLines(data []byte) []byte { return result[0:n] } + +type errorWriter struct{} + +func (e errorWriter) Write([]byte) (int, error) { + return 0, fmt.Errorf("supposed to always fail") +} + +func (e errorWriter) Close() error { + return fmt.Errorf("supposed to always fail") +} diff --git a/msg_nowin_test.go b/msg_nowin_test.go index 965b6f3..9eec2eb 100644 --- a/msg_nowin_test.go +++ b/msg_nowin_test.go @@ -9,6 +9,7 @@ package mail import ( "context" + "os" "testing" "time" ) @@ -38,3 +39,19 @@ func TestMsg_WriteToSendmailWithContext(t *testing.T) { }) } } + +// TestMsg_WriteToSendmail will test the output to the local sendmail command +func TestMsg_WriteToSendmail(t *testing.T) { + _, err := os.Stat(SendmailPath) + if err != nil { + t.Skipf("local sendmail command not found in expected path. Skipping") + } + + m := NewMsg() + _ = m.From("Toni Tester ") + _ = m.To(TestRcpt) + m.SetBodyString(TypeTextPlain, "This is a test") + if err := m.WriteToSendmail(); err != nil { + t.Errorf("WriteToSendmail failed: %s", err) + } +} diff --git a/msg_test.go b/msg_test.go index ed70a73..14178e8 100644 --- a/msg_test.go +++ b/msg_test.go @@ -617,7 +617,7 @@ func TestMsg_SetMessageIDWithValue(t *testing.T) { } } -// TestMsg_FromFormat tests the FromFormat() method for the Msg object +// TestMsg_FromFormat tests the FromFormat and EnvelopeFrom methods for the Msg object func TestMsg_FromFormat(t *testing.T) { tests := []struct { tname string @@ -641,6 +641,10 @@ func TestMsg_FromFormat(t *testing.T) { t.Errorf("failed to FromFormat(): %s", err) return } + if err := m.EnvelopeFromFormat(tt.name, tt.addr); err != nil && !tt.fail { + t.Errorf("failed to EnvelopeFromFormat(): %s", err) + return + } var fa *mail.Address f, ok := m.addrHeader[HeaderFrom]