100 lines
2.7 KiB
Go
100 lines
2.7 KiB
Go
package backend
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net"
|
|
"net/smtp"
|
|
"strings"
|
|
)
|
|
|
|
// SMTP wird AUSSCHLIESSLICH fuers manuelle Weiterleiten einzelner Mails und
|
|
// App-Benachrichtigungen wie Passwort-Reset benutzt. Der Postfach-Umzug laeuft
|
|
// NIE ueber SMTP, sondern ueber IMAP APPEND (05-imap-target.go).
|
|
|
|
func SendPlainMail(to []string, subject, body string) error {
|
|
cfg := Cfg.ForwardSMTP
|
|
if strings.TrimSpace(cfg.Host) == "" || cfg.Port == 0 || strings.TrimSpace(cfg.From) == "" {
|
|
return fmt.Errorf("forward_smtp ist nicht vollstaendig konfiguriert")
|
|
}
|
|
from := cfg.From
|
|
if strings.TrimSpace(cfg.User) != "" {
|
|
from = cfg.User
|
|
}
|
|
message := []byte("From: " + cfg.From + "\r\n" +
|
|
"To: " + strings.Join(to, ", ") + "\r\n" +
|
|
"Subject: " + subject + "\r\n" +
|
|
"Content-Type: text/plain; charset=utf-8\r\n" +
|
|
"\r\n" + body)
|
|
addr := net.JoinHostPort(cfg.Host, fmt.Sprint(cfg.Port))
|
|
auth := smtp.Auth(nil)
|
|
if cfg.User != "" || cfg.Pass != "" {
|
|
auth = smtp.PlainAuth("", cfg.User, cfg.Pass, cfg.Host)
|
|
}
|
|
if cfg.Port == 465 {
|
|
return sendTLS(addr, cfg.Host, auth, from, to, message)
|
|
}
|
|
return sendStartTLS(addr, cfg.Host, auth, from, to, message)
|
|
}
|
|
|
|
func sendStartTLS(addr, host string, auth smtp.Auth, from string, to []string, message []byte) error {
|
|
c, err := smtp.Dial(addr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer c.Close()
|
|
if ok, _ := c.Extension("STARTTLS"); ok {
|
|
if err := c.StartTLS(&tls.Config{ServerName: host, MinVersion: tls.VersionTLS12}); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return smtpClientSend(c, auth, from, to, message)
|
|
}
|
|
|
|
func sendTLS(addr, host string, auth smtp.Auth, from string, to []string, message []byte) error {
|
|
conn, err := tls.Dial("tcp", addr, &tls.Config{ServerName: host, MinVersion: tls.VersionTLS12})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c, err := smtp.NewClient(conn, host)
|
|
if err != nil {
|
|
_ = conn.Close()
|
|
return err
|
|
}
|
|
defer c.Close()
|
|
return smtpClientSend(c, auth, from, to, message)
|
|
}
|
|
|
|
func smtpClientSend(c *smtp.Client, auth smtp.Auth, from string, to []string, message []byte) error {
|
|
if auth != nil {
|
|
if err := c.Auth(auth); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := c.Mail(from); err != nil {
|
|
return err
|
|
}
|
|
for _, rcpt := range to {
|
|
if err := c.Rcpt(rcpt); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
w, err := c.Data()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := w.Write(message); err != nil {
|
|
_ = w.Close()
|
|
return err
|
|
}
|
|
if err := w.Close(); err != nil {
|
|
return err
|
|
}
|
|
return c.Quit()
|
|
}
|
|
|
|
// ForwardMessage leitet den mbox-Rohtext an einen Empfaenger weiter.
|
|
func ForwardMessage(rawMessage []byte, to []string, extraNote string) error {
|
|
body := extraNote + "\n\n" + string(rawMessage)
|
|
return SendPlainMail(to, "Weitergeleitete Nachricht aus Mail-Graveyard", body)
|
|
}
|