1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2025-03-21 06:36:27 +02:00
pocketbase/tools/mailer/sendmail.go

100 lines
2.0 KiB
Go
Raw Normal View History

2022-07-07 00:19:05 +03:00
package mailer
import (
"bytes"
"errors"
"mime"
"net/http"
"os/exec"
"strings"
2024-09-29 19:23:19 +03:00
"github.com/pocketbase/pocketbase/tools/hook"
2022-07-07 00:19:05 +03:00
)
var _ Mailer = (*Sendmail)(nil)
// Sendmail implements [mailer.Mailer] interface and defines a mail
// client that sends emails via the "sendmail" *nix command.
2022-07-07 00:19:05 +03:00
//
// This client is usually recommended only for development and testing.
type Sendmail struct {
2024-09-29 19:23:19 +03:00
onSend *hook.Hook[*SendEvent]
}
// OnSend implements [mailer.SendInterceptor] interface.
func (c *Sendmail) OnSend() *hook.Hook[*SendEvent] {
if c.onSend == nil {
c.onSend = &hook.Hook[*SendEvent]{}
}
return c.onSend
2022-07-07 00:19:05 +03:00
}
2024-09-29 19:23:19 +03:00
// Send implements [mailer.Mailer] interface.
func (c *Sendmail) Send(m *Message) error {
2024-09-29 19:23:19 +03:00
if c.onSend != nil {
return c.onSend.Trigger(&SendEvent{Message: m}, func(e *SendEvent) error {
return c.send(e.Message)
})
}
return c.send(m)
}
func (c *Sendmail) send(m *Message) error {
toAddresses := addressesToStrings(m.To, false)
2022-07-07 00:19:05 +03:00
headers := make(http.Header)
headers.Set("Subject", mime.QEncoding.Encode("utf-8", m.Subject))
headers.Set("From", m.From.String())
2022-07-07 00:19:05 +03:00
headers.Set("Content-Type", "text/html; charset=UTF-8")
headers.Set("To", strings.Join(toAddresses, ","))
2022-07-07 00:19:05 +03:00
cmdPath, err := findSendmailPath()
if err != nil {
return err
}
var buffer bytes.Buffer
// write
// ---
if err := headers.Write(&buffer); err != nil {
return err
}
if _, err := buffer.Write([]byte("\r\n")); err != nil {
return err
}
if m.HTML != "" {
if _, err := buffer.Write([]byte(m.HTML)); err != nil {
return err
}
} else {
if _, err := buffer.Write([]byte(m.Text)); err != nil {
return err
}
2022-07-07 00:19:05 +03:00
}
// ---
sendmail := exec.Command(cmdPath, strings.Join(toAddresses, ","))
2022-07-07 00:19:05 +03:00
sendmail.Stdin = &buffer
return sendmail.Run()
}
func findSendmailPath() (string, error) {
options := []string{
"/usr/sbin/sendmail",
"/usr/bin/sendmail",
"sendmail",
}
for _, option := range options {
path, err := exec.LookPath(option)
if err == nil {
return path, err
}
}
2024-09-29 19:23:19 +03:00
return "", errors.New("Failed to locate a sendmail executable path.")
2022-07-07 00:19:05 +03:00
}