Merge pull request #82 from wneessen/bugfix/81_error-from-body-writer-is-ignored

#81: Fix error handling in body writer
This commit is contained in:
Winni Neessen 2022-11-19 10:03:26 +01:00 committed by GitHub
commit 02c47184c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 7 deletions

View file

@ -8,6 +8,7 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"embed" "embed"
"errors"
"fmt" "fmt"
htpl "html/template" htpl "html/template"
"io" "io"
@ -1652,7 +1653,7 @@ func TestMsg_WriteTo(t *testing.T) {
} }
} }
// TestMsg_WriteTo tests the WriteTo() method of the Msg // TestMsg_WriteToSkipMiddleware tests the WriteTo() method of the Msg
func TestMsg_WriteToSkipMiddleware(t *testing.T) { func TestMsg_WriteToSkipMiddleware(t *testing.T) {
m := NewMsg(WithMiddleware(encodeMiddleware{}), WithMiddleware(uppercaseMiddleware{})) m := NewMsg(WithMiddleware(encodeMiddleware{}), WithMiddleware(uppercaseMiddleware{}))
m.Subject("This is a test") m.Subject("This is a test")
@ -1684,6 +1685,30 @@ func TestMsg_WriteToSkipMiddleware(t *testing.T) {
} }
} }
// TestMsg_WriteTo_fails tests the WriteTo() method of the Msg but with a failing body writer function
func TestMsg_WriteTo_fails(t *testing.T) {
m := NewMsg()
m.SetBodyWriter(TypeTextPlain, func(io.Writer) (int64, error) {
return 0, errors.New("failed")
})
_, err := m.WriteTo(io.Discard)
if err == nil {
t.Errorf("WriteTo() with failing BodyWriter function was supposed to fail, but didn't")
return
}
// NoEncoding handles the errors separately
m = NewMsg(WithEncoding(NoEncoding))
m.SetBodyWriter(TypeTextPlain, func(io.Writer) (int64, error) {
return 0, errors.New("failed")
})
_, err = m.WriteTo(io.Discard)
if err == nil {
t.Errorf("WriteTo() (no encoding) with failing BodyWriter function was supposed to fail, but didn't")
return
}
}
// TestMsg_Write tests the Write() method of the Msg // TestMsg_Write tests the Write() method of the Msg
func TestMsg_Write(t *testing.T) { func TestMsg_Write(t *testing.T) {
m := NewMsg() m := NewMsg()

View file

@ -282,6 +282,7 @@ func (mw *msgWriter) writeBody(f func(io.Writer) (int64, error), e Encoding) {
var w io.Writer var w io.Writer
var ew io.WriteCloser var ew io.WriteCloser
var n int64 var n int64
var err error
if mw.d == 0 { if mw.d == 0 {
w = mw.w w = mw.w
} }
@ -298,8 +299,14 @@ func (mw *msgWriter) writeBody(f func(io.Writer) (int64, error), e Encoding) {
case EncodingB64: case EncodingB64:
ew = base64.NewEncoder(base64.StdEncoding, &lb) ew = base64.NewEncoder(base64.StdEncoding, &lb)
case NoEncoding: case NoEncoding:
_, mw.err = f(&wbuf) _, err = f(&wbuf)
n, mw.err = io.Copy(w, &wbuf) if err != nil {
mw.err = fmt.Errorf("bodyWriter function: %w", err)
}
n, err = io.Copy(w, &wbuf)
if err != nil && mw.err == nil {
mw.err = fmt.Errorf("bodyWriter io.Copy: %w", err)
}
if mw.d == 0 { if mw.d == 0 {
mw.n += n mw.n += n
} }
@ -308,10 +315,22 @@ func (mw *msgWriter) writeBody(f func(io.Writer) (int64, error), e Encoding) {
ew = quotedprintable.NewWriter(w) ew = quotedprintable.NewWriter(w)
} }
_, mw.err = f(ew) _, err = f(ew)
mw.err = ew.Close() if err != nil {
mw.err = lb.Close() mw.err = fmt.Errorf("bodyWriter function: %w", err)
n, mw.err = io.Copy(w, &wbuf) }
err = ew.Close()
if err != nil && mw.err == nil {
mw.err = fmt.Errorf("bodyWriter close encoded writer: %w", err)
}
err = lb.Close()
if err != nil && mw.err == nil {
mw.err = fmt.Errorf("bodyWriter close linebreaker: %w", err)
}
n, err = io.Copy(w, &wbuf)
if err != nil && mw.err == nil {
mw.err = fmt.Errorf("bodyWriter io.Copy: %w", err)
}
// Since the part writer uses the WriteTo() method, we don't need to add the // Since the part writer uses the WriteTo() method, we don't need to add the
// bytes twice // bytes twice