forked from influxdata/kapacitor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
service.go
113 lines (101 loc) · 2.15 KB
/
service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package smtp
import (
"crypto/tls"
"errors"
"log"
"sync"
"time"
"gopkg.in/gomail.v2"
)
var ErrNoRecipients = errors.New("not sending email, no recipients defined")
type Service struct {
c Config
mail chan *gomail.Message
logger *log.Logger
wg sync.WaitGroup
}
func NewService(c Config, l *log.Logger) *Service {
return &Service{
c: c,
mail: make(chan *gomail.Message),
logger: l,
}
}
func (s *Service) Open() error {
s.logger.Println("I! Starting SMTP service")
if s.c.From == "" {
return errors.New("cannot open smtp service: missing from address in configuration")
}
s.wg.Add(1)
go s.runMailer()
return nil
}
func (s *Service) Close() error {
s.logger.Println("I! Closing SMTP service")
close(s.mail)
s.wg.Wait()
return nil
}
func (s *Service) Global() bool {
return s.c.Global
}
func (s *Service) StateChangesOnly() bool {
return s.c.StateChangesOnly
}
func (s *Service) runMailer() {
defer s.wg.Done()
var d *gomail.Dialer
if s.c.Username == "" {
d = &gomail.Dialer{Host: s.c.Host, Port: s.c.Port}
} else {
d = gomail.NewPlainDialer(s.c.Host, s.c.Port, s.c.Username, s.c.Password)
}
if s.c.NoVerify {
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
}
var conn gomail.SendCloser
var err error
open := false
for {
select {
case m, ok := <-s.mail:
if !ok {
return
}
if !open {
if conn, err = d.Dial(); err != nil {
s.logger.Println("E! error connecting to SMTP server", err)
continue
}
open = true
}
if err := gomail.Send(conn, m); err != nil {
s.logger.Println("E!", err)
}
// Close the connection to the SMTP server if no email was sent in
// the last IdleTimeout duration.
case <-time.After(time.Duration(s.c.IdleTimeout)):
if open {
if err := conn.Close(); err != nil {
panic(err)
}
open = false
}
}
}
}
func (s *Service) SendMail(to []string, subject, body string) error {
if len(to) == 0 {
to = s.c.To
}
if len(to) == 0 {
return ErrNoRecipients
}
m := gomail.NewMessage()
m.SetHeader("From", s.c.From)
m.SetHeader("To", to...)
m.SetHeader("Subject", subject)
m.SetBody("text/html", body)
s.mail <- m
return nil
}