Skip to content

Commit 069ffa0

Browse files
author
Winni Neessen
authored
Merge pull request #12 from wneessen/11-io-Reader
Msg.Read() to satisfy io.Reader
2 parents c001ac5 + dd02ac2 commit 069ffa0

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ Some of the features of this library:
3232
* [X] Support for common mail header field generation (Message-ID, Date, Bulk-Precedence, Priority, etc.)
3333
* [X] Reusing the same SMTP connection to send multiple mails
3434
* [X] Support for attachments and inline embeds
35-
* [X] Support for different encodings (existing but not fully tested)
35+
* [X] Support for different encodings
3636
* [X] Support sending mails via a local sendmail command
37+
* [X] Message object satisfies `io.WriteTo` and `io.Reader` interfaces
3738

3839
go-mail works like a programatic email client and provides lots of methods and functionalities you would consider
3940
standard in a MUA.

msg.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,16 @@ func (m *Msg) WriteToSendmailWithContext(ctx context.Context, sp string, a ...st
552552
return nil
553553
}
554554

555+
// Read outputs the length of p into p to satisfy the io.Reader interface
556+
func (m *Msg) Read(p []byte) (int, error) {
557+
wbuf := bytes.Buffer{}
558+
_, err := m.WriteTo(&wbuf)
559+
if err != nil {
560+
return 0, fmt.Errorf("failed to write message to internal write buffer: %w", err)
561+
}
562+
return wbuf.Read(p)
563+
}
564+
555565
// encodeString encodes a string based on the configured message encoder and the corresponding
556566
// charset for the Msg
557567
func (m *Msg) encodeString(s string) string {

msg_test.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,3 +1272,69 @@ func TestMsg_multipleWrites(t *testing.T) {
12721272
t.Errorf("second WriteTo() body does not contain unique string: %s", ts)
12731273
}
12741274
}
1275+
1276+
// TestMsg_Read tests the Msg.Read method that implements the io.Reader interface
1277+
func TestMsg_Read(t *testing.T) {
1278+
tests := []struct {
1279+
name string
1280+
plen int
1281+
}{
1282+
{"P length is bigger than the mail", 32000},
1283+
{"P length is smaller than the mail", 128},
1284+
}
1285+
1286+
m := NewMsg()
1287+
m.SetBodyString(TypeTextPlain, "TEST123")
1288+
wbuf := bytes.Buffer{}
1289+
_, err := m.Write(&wbuf)
1290+
if err != nil {
1291+
t.Errorf("failed to write message into temporary buffer: %s", err)
1292+
}
1293+
elen := wbuf.Len()
1294+
1295+
for _, tt := range tests {
1296+
t.Run(tt.name, func(t *testing.T) {
1297+
p := make([]byte, tt.plen)
1298+
n, err := m.Read(p)
1299+
if err != nil {
1300+
t.Errorf("failed to Read(): %s", err)
1301+
}
1302+
if n == 0 {
1303+
t.Errorf("failed to Read() - received 0 bytes of data")
1304+
}
1305+
if tt.plen >= elen && n != elen {
1306+
t.Errorf("failed to Read() - not all data received. Expected: %d, got: %d", elen, n)
1307+
}
1308+
if tt.plen < elen && n != tt.plen {
1309+
t.Errorf("failed to Read() - full length of p wasn't filled with data. Expected: %d, got: %d",
1310+
tt.plen, n)
1311+
}
1312+
})
1313+
}
1314+
}
1315+
1316+
// TestMsg_Read_ioCopy tests the Msg.Read method using io.Copy
1317+
func TestMsg_Read_ioCopy(t *testing.T) {
1318+
wbuf1 := bytes.Buffer{}
1319+
wbuf2 := bytes.Buffer{}
1320+
m := NewMsg()
1321+
m.SetBodyString(TypeTextPlain, "TEST123")
1322+
1323+
// First we use WriteTo to have something to compare to
1324+
_, err := m.WriteTo(&wbuf1)
1325+
if err != nil {
1326+
t.Errorf("failed to write body to buffer: %s", err)
1327+
}
1328+
1329+
// Then we write to wbuf2 via io.Copy
1330+
n, err := io.Copy(&wbuf2, m)
1331+
if err != nil {
1332+
t.Errorf("failed to use io.Copy on Msg: %s", err)
1333+
}
1334+
if n != int64(wbuf1.Len()) {
1335+
t.Errorf("message length of WriteTo and io.Copy differ. Expected: %d, got: %d", wbuf1.Len(), n)
1336+
}
1337+
if wbuf1.String() != wbuf2.String() {
1338+
t.Errorf("message content of WriteTo and io.Copy differ")
1339+
}
1340+
}

0 commit comments

Comments
 (0)