mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-09 23:42:55 +01:00
Added WriteToSendmail()/WriteToSendmailWithContext() to allow sending mails via local sendmail binary
This commit is contained in:
parent
3e43819b57
commit
54da622bd1
1 changed files with 64 additions and 0 deletions
64
msg.go
64
msg.go
|
@ -1,7 +1,9 @@
|
||||||
package mail
|
package mail
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -9,6 +11,7 @@ import (
|
||||||
"mime"
|
"mime"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -54,6 +57,9 @@ type Msg struct {
|
||||||
embeds []*File
|
embeds []*File
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendmailPath is the default system path to the sendmail binary
|
||||||
|
const SendmailPath = "/usr/bin/sendmail"
|
||||||
|
|
||||||
// MsgOption returns a function that can be used for grouping Msg options
|
// MsgOption returns a function that can be used for grouping Msg options
|
||||||
type MsgOption func(*Msg)
|
type MsgOption func(*Msg)
|
||||||
|
|
||||||
|
@ -450,6 +456,64 @@ func (m *Msg) appendFile(c []*File, f *File, o ...FileOption) []*File {
|
||||||
return append(c, f)
|
return append(c, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteToSendmail returns WriteToSendmailWithContext with a default timeout of 5 seconds
|
||||||
|
func (m *Msg) WriteToSendmail() error {
|
||||||
|
tctx, tcfn := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
|
defer tcfn()
|
||||||
|
return m.WriteToSendmailWithContext(tctx, SendmailPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteToSendmailWithContext opens an pipe to the local sendmail binary and tries to send the
|
||||||
|
// mail though that. It takes a context.Context, the path to the sendmail binary and additional
|
||||||
|
// arguments for the sendmail binary as parameters
|
||||||
|
func (m *Msg) WriteToSendmailWithContext(ctx context.Context, sp string, a ...string) error {
|
||||||
|
ec := exec.CommandContext(ctx, sp)
|
||||||
|
ec.Args = append(ec.Args, "-oi", "-t")
|
||||||
|
ec.Args = append(ec.Args, a...)
|
||||||
|
|
||||||
|
var ebuf bytes.Buffer
|
||||||
|
ec.Stderr = &ebuf
|
||||||
|
ses := bufio.NewScanner(&ebuf)
|
||||||
|
|
||||||
|
si, err := ec.StdinPipe()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to set STDIN pipe: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the execution and write to STDIN
|
||||||
|
if err := ec.Start(); err != nil {
|
||||||
|
return fmt.Errorf("could not start sendmail execution: %w", err)
|
||||||
|
}
|
||||||
|
_, err = m.Write(si)
|
||||||
|
_, err = si.Write([]byte(".\r\n"))
|
||||||
|
if err != nil {
|
||||||
|
_ = si.Close()
|
||||||
|
return fmt.Errorf("failed to write mail to buffer: %w", err)
|
||||||
|
}
|
||||||
|
if err := si.Close(); err != nil {
|
||||||
|
return fmt.Errorf("failed to close STDIN pipe: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the stderr buffer for possible errors
|
||||||
|
var serr string
|
||||||
|
for ses.Scan() {
|
||||||
|
serr += ses.Text()
|
||||||
|
}
|
||||||
|
if err := ses.Err(); err != nil {
|
||||||
|
return fmt.Errorf("failed to read STDERR pipe: %w", err)
|
||||||
|
}
|
||||||
|
if serr != "" {
|
||||||
|
return fmt.Errorf("sendmail execution failed: %s", serr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for completion or cancellation of the sendmail executable
|
||||||
|
if err := ec.Wait(); err != nil {
|
||||||
|
return fmt.Errorf("sendmail command execution failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// encodeString encodes a string based on the configured message encoder and the corresponding
|
// encodeString encodes a string based on the configured message encoder and the corresponding
|
||||||
// charset for the Msg
|
// charset for the Msg
|
||||||
func (m *Msg) encodeString(s string) string {
|
func (m *Msg) encodeString(s string) string {
|
||||||
|
|
Loading…
Reference in a new issue