forked from tildetown/town
100 lines
1.6 KiB
Go
100 lines
1.6 KiB
Go
package email
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net/smtp"
|
|
"os/exec"
|
|
)
|
|
|
|
const (
|
|
from = "root@tilde.town"
|
|
SMTPHost = "smtp.migadu.com"
|
|
SMTPPort = 465
|
|
)
|
|
|
|
func SendLocalEmail(username, subject, body string) error {
|
|
cmd := exec.Command("/usr/sbin/sendmail", username)
|
|
cmd.Stdin = bytes.NewBufferString(fmt.Sprintf("Subject: %s\n\n%s", subject, body))
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("failed to send local email: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type ExternalMailer struct {
|
|
Password string
|
|
}
|
|
|
|
func NewExternalMailer(pw string) *ExternalMailer {
|
|
if pw == "" {
|
|
panic("why?")
|
|
}
|
|
return &ExternalMailer{
|
|
Password: pw,
|
|
}
|
|
}
|
|
|
|
func (m *ExternalMailer) Send(address, subject, body string) error {
|
|
headers := map[string]string{
|
|
"From": from,
|
|
"To": address,
|
|
"Subject": subject,
|
|
}
|
|
|
|
message := ""
|
|
for k, v := range headers {
|
|
message += fmt.Sprintf("%s: %s\r\n", k, v)
|
|
}
|
|
message += "\r\n" + body
|
|
|
|
auth := smtp.PlainAuth("", from, m.Password, SMTPHost)
|
|
|
|
server := fmt.Sprintf("%s:%d", SMTPHost, SMTPPort)
|
|
|
|
tlsconf := &tls.Config{
|
|
InsecureSkipVerify: true,
|
|
ServerName: server,
|
|
}
|
|
|
|
conn, err := tls.Dial("tcp", server, tlsconf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c, err := smtp.NewClient(conn, SMTPHost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = c.Auth(auth); err != nil {
|
|
return fmt.Errorf("auth failed for smtp: %w", err)
|
|
}
|
|
|
|
if err = c.Mail(from); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = c.Rcpt(address); err != nil {
|
|
return err
|
|
}
|
|
|
|
w, err := c.Data()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = w.Write([]byte(message))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
w.Close()
|
|
c.Quit()
|
|
|
|
return nil
|
|
}
|