forked from encoredev/examples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sendgrid.go
110 lines (95 loc) · 3.15 KB
/
sendgrid.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
package sendgrid
import (
"context"
"net/http"
"encore.dev"
"encore.dev/beta/errs"
"encore.dev/pubsub"
"encore.dev/rlog"
"github.com/sendgrid/sendgrid-go"
"github.com/sendgrid/sendgrid-go/helpers/mail"
)
// This uses Encore's built-in secrets manager, learn more: https://encore.dev/docs/primitives/secrets
var secrets struct {
SendGridAPIKey string
}
type Address struct {
Name string `json:"name"`
Email string `json:"email"`
}
type SendParams struct {
From Address `json:"from"` // sender email address
To Address `json:"to"` // recipient email address
Subject string `json:"subject"`
Text string `json:"text"`
Html string `json:"html"`
}
type SendResponse struct {
MessageID string `json:"message_id"` // Message ID in PubSub
}
// Send publishes an email to PubSub for further asynchronous sending using the SendGrid API.
// https://docs.sendgrid.com/api-reference/mail-send/mail-send
//
//encore:api private method=POST path=/sendgrid
func Send(ctx context.Context, params *SendParams) (*SendResponse, error) {
// Preparing the data to create an email event ready to be sent
event := &EmailPreparedEvent{
From: *mail.NewEmail(params.From.Name, params.From.Email),
To: *mail.NewEmail(params.To.Name, params.To.Email),
Subject: params.Subject,
PlainTextContent: params.Text,
HTMLContent: params.Html,
}
// Publishing an event
messageID, err := Emails.Publish(ctx, event)
if err != nil {
return nil, err
}
return &SendResponse{MessageID: messageID}, nil
}
type EmailPreparedEvent struct {
From mail.Email
Subject string
To mail.Email
PlainTextContent string
HTMLContent string
}
// This creates a Pub/Sub topic, learn more: https://encore.dev/docs/primitives/pubsub
var Emails = pubsub.NewTopic[*EmailPreparedEvent]("emails", pubsub.TopicConfig{
DeliveryGuarantee: pubsub.AtLeastOnce,
})
// The maximum number of messages which will be processed and retry policy can be configured below.
// https://pkg.go.dev/encore.dev/pubsub#SubscriptionConfig
var _ = pubsub.NewSubscription(
Emails, "send-email",
pubsub.SubscriptionConfig[*EmailPreparedEvent]{
Handler: sendEmail,
},
)
// When sending email, Pub/Sub is used to control concurrency, learn more: https://encore.dev/docs/primitives/pubsub
func sendEmail(ctx context.Context, event *EmailPreparedEvent) error {
// Creating an email
email := mail.NewSingleEmail(&event.From, event.Subject, &event.To, event.PlainTextContent, event.HTMLContent)
// Skipping sending an email in a non-production environment
if encore.Meta().Environment.Type != encore.EnvProduction {
rlog.Info(
"skipping sending email in non-production environment",
"env", encore.Meta().Environment.Type)
return nil
}
// Creating a client using an API key
client := sendgrid.NewSendClient(secrets.SendGridAPIKey)
// Sending and error handling
response, err := client.SendWithContext(ctx, email)
if err != nil {
rlog.Error("failed sending email", "err", err)
return err
}
if response.StatusCode != http.StatusOK {
return &errs.Error{
Code: errs.Internal,
Message: "failed to send email",
}
}
return nil
}