backup/email.go

128 lines
3.5 KiB
Go
Raw Normal View History

2022-06-17 14:54:14 +02:00
package main
import (
"encoding/base64"
2023-06-29 22:58:24 +02:00
"fmt"
2022-06-17 14:54:14 +02:00
"net/smtp"
2023-07-31 10:20:31 +02:00
"sort"
2022-06-17 14:54:14 +02:00
"strings"
2023-06-29 22:58:24 +02:00
"sync"
2022-06-17 14:54:14 +02:00
"time"
2023-06-29 22:58:24 +02:00
log "github.com/sirupsen/logrus"
2022-06-17 14:54:14 +02:00
)
type Email struct {
startTime time.Time
items []string
2023-06-29 22:58:24 +02:00
mx sync.Mutex
2022-06-17 14:54:14 +02:00
}
type EmailConfig struct {
2022-06-19 06:33:24 +02:00
SmtpHost string `json:"smtp"`
FromEmail string `json:"email_from"`
ToEmail []string `json:"email_to"`
2022-06-17 14:54:14 +02:00
}
2023-06-29 22:58:24 +02:00
func NewEmail(now time.Time) *Email {
log.WithFields(log.Fields{"now": now}).Debugf("starting")
defer log.WithFields(log.Fields{"now": now}).Debugf("done")
return &Email{startTime: now, items: make([]string, 0)}
}
func (e *Email) AddItem(item string) {
log.WithFields(log.Fields{"item": item}).Debugf("starting")
defer log.WithFields(log.Fields{"item": item}).Debugf("done")
e.items = append(e.items, item)
}
func (e *Email) Send() error {
log.WithFields(log.Fields{}).Debugf("starting")
defer log.WithFields(log.Fields{}).Debugf("done")
2023-07-31 10:13:36 +02:00
if len(e.items) == 0 {
return nil
}
2023-07-31 10:20:31 +02:00
sort.Slice(e.items, func(i, j int) bool {
return e.items[i] < e.items[j]
})
body := e.items[0]
2023-06-29 22:58:24 +02:00
for _, item := range e.items[1:] {
body = body + "\r\n" + item
2022-06-19 06:13:52 +02:00
}
2023-06-29 22:58:24 +02:00
subject := fmt.Sprintf("Autobackup report (%s)", e.startTime)
if err := SendMail(cfg.Email.SmtpHost, cfg.Email.FromEmail, subject, body, cfg.Email.ToEmail); err != nil {
log.WithFields(log.Fields{"addr": cfg.Email.SmtpHost, "from": cfg.Email.FromEmail, "subject": subject, "call": "SendMail", "error": err}).Errorf("")
return err
}
return nil
}
func SendMail(addr, from, subject, body string, to []string) error {
log.WithFields(log.Fields{"addr": addr, "from": from, "subject": subject}).Debugf("starting")
defer log.WithFields(log.Fields{"addr": addr, "from": from, "subject": subject}).Debugf("done")
2022-06-17 14:54:14 +02:00
r := strings.NewReplacer("\r\n", "", "\r", "", "\n", "", "%0a", "", "%0d", "")
c, err := smtp.Dial(addr)
if err != nil {
2023-06-29 22:58:24 +02:00
log.WithFields(log.Fields{"addr": addr, "from": from, "subject": subject, "call": "smtp.Dial", "error": err}).Errorf("")
2022-06-17 14:54:14 +02:00
return err
}
2022-06-19 06:18:34 +02:00
2022-06-17 14:54:14 +02:00
defer c.Close()
2022-06-19 06:18:34 +02:00
2022-06-17 14:54:14 +02:00
if err = c.Mail(r.Replace(from)); err != nil {
2023-06-29 22:58:24 +02:00
log.WithFields(log.Fields{"addr": addr, "from": from, "subject": subject, "call": "client.Mail", "error": err}).Errorf("")
2022-06-17 14:54:14 +02:00
return err
}
2022-06-19 06:18:34 +02:00
2022-06-17 14:54:14 +02:00
for i := range to {
to[i] = r.Replace(to[i])
if err = c.Rcpt(to[i]); err != nil {
2023-06-29 22:58:24 +02:00
log.WithFields(log.Fields{"addr": addr, "from": from, "subject": subject, "call": "client.Rcpt", "attr": to[i], "error": err}).Errorf("")
2022-06-17 14:54:14 +02:00
return err
}
}
w, err := c.Data()
if err != nil {
2023-06-29 22:58:24 +02:00
log.WithFields(log.Fields{"addr": addr, "from": from, "subject": subject, "call": "client.Date", "error": err}).Errorf("")
2022-06-17 14:54:14 +02:00
return err
}
2022-10-08 05:15:09 +02:00
msg := "Date: " + time.Now().Format("Mon, 02 Jan 2006 15:04:05 -0700") + "\r\n" +
2022-10-08 04:49:28 +02:00
"To: " + strings.Join(to, ",") + "\r\n" +
2022-06-17 14:54:14 +02:00
"From: " + from + "\r\n" +
"Subject: " + subject + "\r\n" +
2022-10-08 05:15:09 +02:00
"Content-Type: text/plain; charset=\"UTF-8\"\r\n" +
2022-06-17 14:54:14 +02:00
"Content-Transfer-Encoding: base64\r\n" +
"\r\n" + base64.StdEncoding.EncodeToString([]byte(body))
_, err = w.Write([]byte(msg))
if err != nil {
2023-06-29 22:58:24 +02:00
log.WithFields(log.Fields{"addr": addr, "from": from, "subject": subject, "call": "writer.Write", "error": err}).Errorf("")
2022-06-17 14:54:14 +02:00
return err
}
2022-06-19 06:18:34 +02:00
2022-06-17 14:54:14 +02:00
err = w.Close()
if err != nil {
2023-06-29 22:58:24 +02:00
log.WithFields(log.Fields{"addr": addr, "from": from, "subject": subject, "call": "writer.Close", "error": err}).Errorf("")
2022-06-17 14:54:14 +02:00
return err
}
2022-06-19 06:18:34 +02:00
2023-06-29 22:58:24 +02:00
if err = c.Quit(); err != nil {
log.WithFields(log.Fields{"addr": addr, "from": from, "subject": subject, "call": "client.Quit", "error": err}).Errorf("")
return err
2022-06-19 06:18:34 +02:00
}
2023-06-29 22:58:24 +02:00
return nil
2022-06-17 14:54:14 +02:00
}