-
Notifications
You must be signed in to change notification settings - Fork 2
/
mail.go
143 lines (114 loc) · 2.75 KB
/
mail.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package model
import (
"errors"
"fmt"
"html/template"
"io"
"strings"
"github.com/ViBiOh/httputils/v4/pkg/logger"
)
// MailRequest describes an email to be sent
type MailRequest struct {
Payload any
Tpl string
FromEmail string
Sender string
Subject string
Recipients []string
}
// NewMailRequest create a new email
func NewMailRequest() MailRequest {
return MailRequest{}
}
// Template set template
func (mr MailRequest) Template(template string) MailRequest {
mr.Tpl = template
return mr
}
// From set from
func (mr MailRequest) From(fromEmail string) MailRequest {
mr.FromEmail = fromEmail
return mr
}
// As set sender
func (mr MailRequest) As(sender string) MailRequest {
mr.Sender = sender
return mr
}
// WithSubject set subject
func (mr MailRequest) WithSubject(subject string) MailRequest {
mr.Subject = subject
return mr
}
// To add recipients to list
func (mr MailRequest) To(recipients ...string) MailRequest {
if len(mr.Recipients) == 0 {
mr.Recipients = recipients
} else {
mr.Recipients = append(mr.Recipients, recipients...)
}
return mr
}
// Data set payload
func (mr MailRequest) Data(payload any) MailRequest {
mr.Payload = payload
return mr
}
// Check checks if current instance is valid
func (mr MailRequest) Check() error {
if len(mr.FromEmail) == 0 {
return errors.New("from email is required")
}
if len(mr.Recipients) == 0 {
return errors.New("recipients are required")
}
for index, recipient := range mr.Recipients {
if len(recipient) == 0 {
return fmt.Errorf("recipient at index %d is empty", index)
}
}
if len(mr.Tpl) == 0 {
return errors.New("template name is required")
}
return nil
}
func getSubject(subject string, payload any) string {
if !strings.Contains(subject, "{{") {
return subject
}
tpl, err := template.New("subject").Parse(subject)
if err != nil {
logger.Warn("cannot parse template subject `%s`: %s", subject, err)
return subject
}
subjectOutput := strings.Builder{}
if err := tpl.Execute(&subjectOutput, payload); err != nil {
logger.Warn("cannot execute template subject `%s`: %s", subject, err)
return subject
}
return subjectOutput.String()
}
// ConvertToMail convert mail request to Mail with given content
func (mr MailRequest) ConvertToMail(content io.Reader) Mail {
return Mail{
From: mr.FromEmail,
Sender: mr.Sender,
Subject: getSubject(mr.Subject, mr.Payload),
Content: content,
To: mr.Recipients,
}
}
// Mail describe envelope of an email
type Mail struct {
From string
Sender string
Subject string
Content io.Reader
To []string
}
// LoggedCloser closes a ressources with handling error
func LoggedCloser(closer io.Closer) {
if err := closer.Close(); err != nil {
logger.Error("error while closing: %s", err)
}
}