/
mailgun_notification_delivery_service.go
129 lines (101 loc) · 3.35 KB
/
mailgun_notification_delivery_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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package notification
import (
"context"
"fmt"
"time"
toolchainv1alpha1 "github.com/codeready-toolchain/api/api/v1alpha1"
"github.com/mailgun/mailgun-go/v4"
)
const (
ContextReplyTo = "ReplyTo"
)
type MailgunDeliveryError struct {
id string
response string
errorMessage string
}
func (e MailgunDeliveryError) Error() string {
return fmt.Sprintf("error while delivering notification (ID: %s, Response: %s) - %s", e.id, e.response, e.errorMessage)
}
func NewMailgunDeliveryError(id, response, errorMessage string) error {
return MailgunDeliveryError{
id: id,
response: response,
errorMessage: errorMessage,
}
}
type MailgunNotificationDeliveryService struct {
base BaseNotificationDeliveryService
Mailgun mailgun.Mailgun
SenderEmail string
ReplyToEmail string
}
type MailgunConfig interface {
GetMailgunDomain() string
GetMailgunAPIKey() string
GetMailgunSenderEmail() string
GetMailgunReplyToEmail() string
}
type MailgunOption interface {
// ApplyToMailgun applies this configuration to the given mailgun instance.
ApplyToMailgun(mailgun.Mailgun)
}
// NewMailgunNotificationDeliveryService creates a delivery service that uses the Mailgun API to deliver email notifications
func NewMailgunNotificationDeliveryService(config DeliveryServiceFactoryConfig, templateLoader TemplateLoader,
opts ...MailgunOption) DeliveryService {
mg := mailgun.NewMailgun(config.GetMailgunDomain(), config.GetMailgunAPIKey())
for _, opt := range opts {
opt.ApplyToMailgun(mg)
}
return &MailgunNotificationDeliveryService{
base: BaseNotificationDeliveryService{TemplateLoader: templateLoader},
Mailgun: mg,
SenderEmail: config.GetMailgunSenderEmail(),
ReplyToEmail: config.GetMailgunReplyToEmail(),
}
}
func (s *MailgunNotificationDeliveryService) Send(notification *toolchainv1alpha1.Notification, templateSetName string) error {
var subject, body string
if notification.Spec.Template != "" {
template, err := s.base.TemplateLoader.GetNotificationTemplate(notification.Spec.Template, templateSetName)
if err != nil {
return err
}
// Copy the context to a local variable, we will add some more values to it here
context := notification.Spec.Context
if s.ReplyToEmail != "" {
context[ContextReplyTo] = s.ReplyToEmail
} else {
context[ContextReplyTo] = s.SenderEmail
}
subject, err = s.base.GenerateContent(context, template.Subject)
if err != nil {
return err
}
body, err = s.base.GenerateContent(context, template.Content)
if err != nil {
return err
}
} else {
// If there is no template specified then simply use the subject and content provided by the notification
subject = notification.Spec.Subject
body = notification.Spec.Content
}
if subject == "" || body == "" {
return fmt.Errorf("no subject or body specified for notification")
}
// The message object allows you to add attachments and Bcc recipients
message := s.Mailgun.NewMessage(s.SenderEmail, subject, "", notification.Spec.Recipient)
if s.ReplyToEmail != "" {
message.SetReplyTo(s.ReplyToEmail)
}
message.SetHtml(body)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
// Send the message with a 10 second timeout
response, id, err := s.Mailgun.Send(ctx, message)
if err != nil {
return NewMailgunDeliveryError(id, response, err.Error())
}
return nil
}