mirror of
https://github.com/wneessen/go-mail.git
synced 2024-12-23 02:50:39 +01:00
Merge branch 'main' into feature/107_provide-more-ways-for-middleware-to-interact-with-mail-parts
This commit is contained in:
commit
d33f0e8004
2 changed files with 173 additions and 5 deletions
54
msg.go
54
msg.go
|
@ -746,11 +746,22 @@ func (m *Msg) AttachFile(n string, o ...FileOption) {
|
|||
}
|
||||
|
||||
// AttachReader adds an attachment File via io.Reader to the Msg
|
||||
//
|
||||
// CAVEAT: For AttachReader to work it has to read all data of the io.Reader
|
||||
// into memory first, so it can seek through it. Using larger amounts of
|
||||
// data on the io.Reader should be avoided. For such, it is recommeded to
|
||||
// either use AttachFile or AttachReadSeeker instead
|
||||
func (m *Msg) AttachReader(n string, r io.Reader, o ...FileOption) {
|
||||
f := fileFromReader(n, r)
|
||||
m.attachments = m.appendFile(m.attachments, f, o...)
|
||||
}
|
||||
|
||||
// AttachReadSeeker adds an attachment File via io.ReadSeeker to the Msg
|
||||
func (m *Msg) AttachReadSeeker(n string, r io.ReadSeeker, o ...FileOption) {
|
||||
f := fileFromReadSeeker(n, r)
|
||||
m.attachments = m.appendFile(m.attachments, f, o...)
|
||||
}
|
||||
|
||||
// AttachHTMLTemplate adds the output of a html/template.Template pointer as File attachment to the Msg
|
||||
func (m *Msg) AttachHTMLTemplate(n string, t *ht.Template, d interface{}, o ...FileOption) error {
|
||||
f, err := fileFromHTMLTemplate(n, t, d)
|
||||
|
@ -794,11 +805,22 @@ func (m *Msg) EmbedFile(n string, o ...FileOption) {
|
|||
}
|
||||
|
||||
// EmbedReader adds an embedded File from an io.Reader to the Msg
|
||||
//
|
||||
// CAVEAT: For AttachReader to work it has to read all data of the io.Reader
|
||||
// into memory first, so it can seek through it. Using larger amounts of
|
||||
// data on the io.Reader should be avoided. For such, it is recommeded to
|
||||
// either use AttachFile or AttachReadSeeker instead
|
||||
func (m *Msg) EmbedReader(n string, r io.Reader, o ...FileOption) {
|
||||
f := fileFromReader(n, r)
|
||||
m.embeds = m.appendFile(m.embeds, f, o...)
|
||||
}
|
||||
|
||||
// EmbedReadSeeker adds an embedded File from an io.ReadSeeker to the Msg
|
||||
func (m *Msg) EmbedReadSeeker(n string, r io.ReadSeeker, o ...FileOption) {
|
||||
f := fileFromReadSeeker(n, r)
|
||||
m.embeds = m.appendFile(m.embeds, f, o...)
|
||||
}
|
||||
|
||||
// EmbedHTMLTemplate adds the output of a html/template.Template pointer as embedded File to the Msg
|
||||
func (m *Msg) EmbedHTMLTemplate(n string, t *ht.Template, d interface{}, o ...FileOption) error {
|
||||
f, err := fileFromHTMLTemplate(n, t, d)
|
||||
|
@ -1151,15 +1173,37 @@ func fileFromFS(n string) *File {
|
|||
|
||||
// fileFromReader returns a File pointer from a given io.Reader
|
||||
func fileFromReader(n string, r io.Reader) *File {
|
||||
d, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return &File{}
|
||||
}
|
||||
br := bytes.NewReader(d)
|
||||
return &File{
|
||||
Name: filepath.Base(n),
|
||||
Name: n,
|
||||
Header: make(map[string][]string),
|
||||
Writer: func(w io.Writer) (int64, error) {
|
||||
nb, err := io.Copy(w, r)
|
||||
if err != nil {
|
||||
return nb, err
|
||||
rb, cerr := io.Copy(w, br)
|
||||
if cerr != nil {
|
||||
return rb, cerr
|
||||
}
|
||||
return nb, nil
|
||||
_, cerr = br.Seek(0, io.SeekStart)
|
||||
return rb, cerr
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// fileFromReadSeeker returns a File pointer from a given io.ReadSeeker
|
||||
func fileFromReadSeeker(n string, r io.ReadSeeker) *File {
|
||||
return &File{
|
||||
Name: n,
|
||||
Header: make(map[string][]string),
|
||||
Writer: func(w io.Writer) (int64, error) {
|
||||
rb, err := io.Copy(w, r)
|
||||
if err != nil {
|
||||
return rb, err
|
||||
}
|
||||
_, err = r.Seek(0, io.SeekStart)
|
||||
return rb, err
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
124
msg_test.go
124
msg_test.go
|
@ -2667,3 +2667,127 @@ func TestMsg_GetBccString(t *testing.T) {
|
|||
`"Toni Cc" <bcc@example.com>"`, fh[0])
|
||||
}
|
||||
}
|
||||
|
||||
// TestMsg_AttachEmbedReader_consecutive tests the Msg.AttachReader and Msg.EmbedReader
|
||||
// methods with consecutive calls to Msg.WriteTo to make sure the attachments are not
|
||||
// lost (see Github issue #110)
|
||||
func TestMsg_AttachEmbedReader_consecutive(t *testing.T) {
|
||||
ts1 := "This is a test string"
|
||||
ts2 := "Another test string"
|
||||
m := NewMsg()
|
||||
m.AttachReader("attachment.txt", bytes.NewBufferString(ts1))
|
||||
m.EmbedReader("embeded.txt", bytes.NewBufferString(ts2))
|
||||
obuf1 := &bytes.Buffer{}
|
||||
obuf2 := &bytes.Buffer{}
|
||||
_, err := m.WriteTo(obuf1)
|
||||
if err != nil {
|
||||
t.Errorf("WriteTo to first output buffer failed: %s", err)
|
||||
}
|
||||
_, err = m.WriteTo(obuf2)
|
||||
if err != nil {
|
||||
t.Errorf("WriteTo to second output buffer failed: %s", err)
|
||||
}
|
||||
if !strings.Contains(obuf1.String(), "VGhpcyBpcyBhIHRlc3Qgc3RyaW5n") {
|
||||
t.Errorf("Expected file attachment string not found in first output buffer")
|
||||
}
|
||||
if !strings.Contains(obuf2.String(), "VGhpcyBpcyBhIHRlc3Qgc3RyaW5n") {
|
||||
t.Errorf("Expected file attachment string not found in second output buffer")
|
||||
}
|
||||
if !strings.Contains(obuf1.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
||||
t.Errorf("Expected embeded file string not found in first output buffer")
|
||||
}
|
||||
if !strings.Contains(obuf2.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
||||
t.Errorf("Expected embded file string not found in second output buffer")
|
||||
}
|
||||
}
|
||||
|
||||
// TestMsg_AttachEmbedReadSeeker_consecutive tests the Msg.AttachReadSeeker and
|
||||
// Msg.EmbedReadSeeker methods with consecutive calls to Msg.WriteTo to make
|
||||
// sure the attachments are not lost (see Github issue #110)
|
||||
func TestMsg_AttachEmbedReadSeeker_consecutive(t *testing.T) {
|
||||
ts1 := []byte("This is a test string")
|
||||
ts2 := []byte("Another test string")
|
||||
m := NewMsg()
|
||||
m.AttachReadSeeker("attachment.txt", bytes.NewReader(ts1))
|
||||
m.EmbedReadSeeker("embeded.txt", bytes.NewReader(ts2))
|
||||
obuf1 := &bytes.Buffer{}
|
||||
obuf2 := &bytes.Buffer{}
|
||||
_, err := m.WriteTo(obuf1)
|
||||
if err != nil {
|
||||
t.Errorf("WriteTo to first output buffer failed: %s", err)
|
||||
}
|
||||
_, err = m.WriteTo(obuf2)
|
||||
if err != nil {
|
||||
t.Errorf("WriteTo to second output buffer failed: %s", err)
|
||||
}
|
||||
if !strings.Contains(obuf1.String(), "VGhpcyBpcyBhIHRlc3Qgc3RyaW5n") {
|
||||
t.Errorf("Expected file attachment string not found in first output buffer")
|
||||
}
|
||||
if !strings.Contains(obuf2.String(), "VGhpcyBpcyBhIHRlc3Qgc3RyaW5n") {
|
||||
t.Errorf("Expected file attachment string not found in second output buffer")
|
||||
}
|
||||
if !strings.Contains(obuf1.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
||||
t.Errorf("Expected embeded file string not found in first output buffer")
|
||||
}
|
||||
if !strings.Contains(obuf2.String(), "QW5vdGhlciB0ZXN0IHN0cmluZw==") {
|
||||
t.Errorf("Expected embded file string not found in second output buffer")
|
||||
}
|
||||
}
|
||||
|
||||
// TestMsg_AttachReadSeeker tests the Msg.AttachReadSeeker method
|
||||
func TestMsg_AttachReadSeeker(t *testing.T) {
|
||||
m := NewMsg()
|
||||
ts := []byte("This is a test string")
|
||||
r := bytes.NewReader(ts)
|
||||
m.AttachReadSeeker("testfile.txt", r)
|
||||
if len(m.attachments) != 1 {
|
||||
t.Errorf("AttachReadSeeker() failed. Number of attachments expected: %d, got: %d", 1,
|
||||
len(m.attachments))
|
||||
return
|
||||
}
|
||||
file := m.attachments[0]
|
||||
if file == nil {
|
||||
t.Errorf("AttachReadSeeker() failed. Attachment file pointer is nil")
|
||||
return
|
||||
}
|
||||
if file.Name != "testfile.txt" {
|
||||
t.Errorf("AttachReadSeeker() failed. Expected file name: %s, got: %s", "testfile.txt",
|
||||
file.Name)
|
||||
}
|
||||
wbuf := bytes.Buffer{}
|
||||
if _, err := file.Writer(&wbuf); err != nil {
|
||||
t.Errorf("execute WriterFunc failed: %s", err)
|
||||
}
|
||||
if wbuf.String() != string(ts) {
|
||||
t.Errorf("AttachReadSeeker() failed. Expected string: %q, got: %q", ts, wbuf.String())
|
||||
}
|
||||
}
|
||||
|
||||
// TestMsg_EmbedReadSeeker tests the Msg.EmbedReadSeeker method
|
||||
func TestMsg_EmbedReadSeeker(t *testing.T) {
|
||||
m := NewMsg()
|
||||
ts := []byte("This is a test string")
|
||||
r := bytes.NewReader(ts)
|
||||
m.EmbedReadSeeker("testfile.txt", r)
|
||||
if len(m.embeds) != 1 {
|
||||
t.Errorf("EmbedReadSeeker() failed. Number of attachments expected: %d, got: %d", 1,
|
||||
len(m.embeds))
|
||||
return
|
||||
}
|
||||
file := m.embeds[0]
|
||||
if file == nil {
|
||||
t.Errorf("EmbedReadSeeker() failed. Embedded file pointer is nil")
|
||||
return
|
||||
}
|
||||
if file.Name != "testfile.txt" {
|
||||
t.Errorf("EmbedReadSeeker() failed. Expected file name: %s, got: %s", "testfile.txt",
|
||||
file.Name)
|
||||
}
|
||||
wbuf := bytes.Buffer{}
|
||||
if _, err := file.Writer(&wbuf); err != nil {
|
||||
t.Errorf("execute WriterFunc failed: %s", err)
|
||||
}
|
||||
if wbuf.String() != string(ts) {
|
||||
t.Errorf("EmbedReadSeeker() failed. Expected string: %q, got: %q", ts, wbuf.String())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue