forked from digisan/go-mail
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gomail.go
115 lines (100 loc) · 2.71 KB
/
gomail.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
114
115
package gomail
import (
"fmt"
"sync"
"time"
cfg "github.com/digisan/go-config"
lk "github.com/digisan/logkit"
"github.com/mailgun/mailgun-go/v4"
"github.com/sendgrid/sendgrid-go"
)
var (
cfgSG = []string{"sendgrid-config.toml", "sendgrid-config.json"}
cfgMG = []string{"mailgun-config.toml", "mailgun-config.json"}
)
var (
cfgOK = true
sendBy = ""
mg *mailgun.MailgunImpl // mailgun
sg *sendgrid.Client // sendgrid
sender = "" // sender name, both
senderEmail = "" // sender email, sendgrid
domain = "" // sender domain, mailgun
key = "" // api key (encrypted), both
mRecipient = sync.Map{} // both
timeout = 12 * time.Second // both
)
// SendGrid is the first priority
func init() {
if err := cfg.Init("sendgrid", false, cfgSG...); err == nil {
if sendBy = initSG(); len(sendBy) > 0 {
lk.Log("using %v", sendBy)
return
}
}
if err := cfg.Init("mailgun", false, cfgMG...); err == nil {
if sendBy = initMG(); len(sendBy) > 0 {
lk.Log("using %v", sendBy)
return
}
}
lk.WarnDetail(false)
lk.Warn("email agent config [%v, %v] loaded error, sending email cannot work", cfgMG, cfgSG)
cfgOK = false
}
func RegisterRecipient(name, email string) error {
if cfgOK {
if validEmail(email) {
mRecipient.Store(name, email)
return nil
}
return fmt.Errorf("[%v] is invalid email format", email)
}
return fmt.Errorf("cannot find any of email agent config [%v, %v], cannot register recipient", cfgMG, cfgSG)
}
type result interface {
Recipient() string
Err() error
}
func SendMail(subject, body string, recipients ...string) (OK bool, sent []string, failed []string, errs []error) {
if cfgOK {
var (
chRst chan result
nOK = 0
done = make(chan bool)
)
switch sendBy {
case "sendgrid":
chRst = sendSG(subject, body, recipients...)
case "mailgun":
chRst = sendMG(subject, body, recipients...)
default:
panic("only [mailgun, sendgrid] are supported")
}
go func() {
for rst := range chRst {
if rst.Err() == nil {
sent = append(sent, rst.Recipient())
nOK++
} else {
failed = append(failed, rst.Recipient())
errs = append(errs, rst.Err())
}
if nOK == len(recipients) {
close(chRst)
}
}
done <- true
}()
select {
case <-done:
return nOK == len(recipients), sent, failed, errs
case <-time.After(timeout):
errs = append(errs, fmt.Errorf("timeout @%vs", timeout/time.Second))
return false, nil, nil, errs
}
} else {
errs = append(errs, fmt.Errorf("cannot find any of email agent config [%v, %v], cannot send email", cfgMG, cfgSG))
return false, nil, nil, errs
}
}