mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 05:40:50 +01:00
Fix Attach/EmbedReader and implement Attach/EmbedReadSeeker
This PR addresses #110. `Msg.AttachReader()` would not output the attached file after consecutive writes (e.g. a write to a file and then send via Client). This PR fixes this behaviour by first reading the io.Reader into memory and then creating a new `bytes.Reader`, which does support seeking. In the writeFunc we then seek to position 0 after a successful `io.Copy`. This is probably not the most memory efficient way of handling this, but otherwise we'll have to break the `io.Reader` interface. Additionally, a new way of attaching/embedding files has been added: `Msg.AttachReadSeeker()` and `Msg.EmbedReadSeeker()` which take a ´io.ReadSeeker` as argument instead. These two methods will skip the reading into memory and make use of the `Seek` method of the corresponding interface instead.
This commit is contained in:
parent
cfaeb51bef
commit
e66ad2be1a
1 changed files with 39 additions and 5 deletions
44
msg.go
44
msg.go
|
@ -719,6 +719,12 @@ func (m *Msg) AttachReader(n string, r io.Reader, o ...FileOption) {
|
|||
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)
|
||||
|
@ -767,6 +773,12 @@ func (m *Msg) EmbedReader(n string, r io.Reader, o ...FileOption) {
|
|||
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)
|
||||
|
@ -1114,15 +1126,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
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue