2018-01-29 16:52:59 +01:00
|
|
|
package services
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"log"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/go-mail/mail"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrMailUninitializedConfig = errors.New("Mail: uninitialized config")
|
|
|
|
)
|
|
|
|
|
|
|
|
type EmailConfig struct {
|
|
|
|
From string
|
2018-02-01 03:30:00 +01:00
|
|
|
SMTPEnabled bool
|
2018-01-29 16:52:59 +01:00
|
|
|
SMTPServer string
|
|
|
|
SMTPPort int
|
|
|
|
SMTPUsername string
|
|
|
|
SMTPPassword string
|
2018-01-29 20:55:25 +01:00
|
|
|
SMTPTimeout time.Duration
|
2018-01-29 16:52:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type Email struct {
|
|
|
|
config *EmailConfig
|
|
|
|
|
|
|
|
mailChan chan *mail.Message
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewEmail(conf *EmailConfig) *Email {
|
|
|
|
if conf == nil {
|
|
|
|
log.Println(ErrMailUninitializedConfig)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &Email{
|
|
|
|
config: conf,
|
2018-01-29 20:55:25 +01:00
|
|
|
mailChan: make(chan *mail.Message, 4),
|
2018-01-29 16:52:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send sends an email to the receiver
|
|
|
|
func (email *Email) Send(to, subject, text, html string) error {
|
|
|
|
if email.config == nil {
|
|
|
|
log.Print("Error: trying to send mail with uninitialized config.")
|
|
|
|
return ErrMailUninitializedConfig
|
|
|
|
}
|
|
|
|
|
2018-02-01 03:30:00 +01:00
|
|
|
if !email.config.SMTPEnabled {
|
|
|
|
log.Printf("SMTP is disabled in config, printing out email text instead:\nTo: %s\n%s", to, text)
|
|
|
|
}
|
|
|
|
|
2018-01-29 16:52:59 +01:00
|
|
|
m := mail.NewMessage()
|
|
|
|
m.SetHeader("From", email.config.From)
|
|
|
|
m.SetHeader("To", to)
|
|
|
|
m.SetHeader("Subject", subject)
|
|
|
|
m.SetBody("text/plain", text)
|
2018-02-01 03:30:00 +01:00
|
|
|
|
|
|
|
if len(html) > 0 {
|
|
|
|
m.AddAlternative("text/html", html)
|
|
|
|
}
|
2018-01-29 16:52:59 +01:00
|
|
|
|
|
|
|
// put email in chan
|
|
|
|
email.mailChan <- m
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Daemon is a function that takes Mail and sends it without blocking.
|
|
|
|
// WIP
|
|
|
|
func (email *Email) Daemon() {
|
|
|
|
if email.config == nil {
|
|
|
|
log.Print("Error: trying to set up mail deamon with uninitialized config.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-02-01 03:30:00 +01:00
|
|
|
if !email.config.SMTPEnabled {
|
|
|
|
log.Print("SMTP is disabled in config, emails will be printed instead.")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-01-29 20:55:25 +01:00
|
|
|
log.Print("Running mail sending routine")
|
|
|
|
|
2018-01-29 16:52:59 +01:00
|
|
|
d := mail.NewDialer(
|
|
|
|
email.config.SMTPServer,
|
|
|
|
email.config.SMTPPort,
|
|
|
|
email.config.SMTPUsername,
|
|
|
|
email.config.SMTPPassword)
|
|
|
|
|
|
|
|
var s mail.SendCloser
|
|
|
|
var err error
|
|
|
|
open := false
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case m, ok := <-email.mailChan:
|
|
|
|
if !ok {
|
|
|
|
// channel is closed
|
2018-01-29 20:55:25 +01:00
|
|
|
log.Print("Channel closed")
|
2018-01-29 16:52:59 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
if !open {
|
|
|
|
if s, err = d.Dial(); err != nil {
|
|
|
|
log.Print(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
open = true
|
|
|
|
}
|
2018-01-29 20:55:25 +01:00
|
|
|
log.Printf("Trying to send mail")
|
2018-01-29 16:52:59 +01:00
|
|
|
if err := mail.Send(s, m); err != nil {
|
2018-01-29 20:55:25 +01:00
|
|
|
log.Printf("Mail: %s", err)
|
2018-01-29 16:52:59 +01:00
|
|
|
}
|
2018-01-29 20:55:25 +01:00
|
|
|
// Close the connection if no email was sent in the last X seconds.
|
|
|
|
case <-time.After(email.config.SMTPTimeout):
|
2018-01-29 16:52:59 +01:00
|
|
|
if open {
|
|
|
|
if err := s.Close(); err != nil {
|
2018-01-29 20:55:25 +01:00
|
|
|
log.Printf("Mail: Failed to close connection: %s", err)
|
2018-01-29 16:52:59 +01:00
|
|
|
}
|
|
|
|
open = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|