Files
sendico/api/notification/internal/server/notificationimp/mail/internal/sendgrid.go
Stephan D d367dddbbd
Some checks failed
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/fx/1 Pipeline failed
ci/woodpecker/push/nats Pipeline was successful
ci/woodpecker/push/fx/2 Pipeline failed
fx build fix
2025-11-08 00:40:01 +01:00

105 lines
3.0 KiB
Go

package mailimp
import (
"net/http"
"os"
mb "github.com/tech/sendico/notification/internal/server/notificationimp/mail/internal/builder"
mmail "github.com/tech/sendico/notification/internal/server/notificationimp/mail/messagebuilder"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/messaging"
"github.com/tech/sendico/pkg/mlogger"
"github.com/sendgrid/sendgrid-go"
"github.com/sendgrid/sendgrid-go/helpers/mail"
"go.uber.org/zap"
)
type KeysConfig struct {
Email string `yaml:"email"`
Name string `yaml:"name"`
URL string `yaml:"url"`
ID string `yaml:"id"`
}
type Sender struct {
Address string `yaml:"address"`
Name string `yaml:"name"`
}
type SGEmailConfig struct {
Sender Sender `yaml:"sender"`
}
type SendGridConfig struct {
APIKeyEnv string `yaml:"api_key_env"`
Email SGEmailConfig `yaml:"email"`
Keys KeysConfig `yaml:"keys"`
}
type SendGridNotifier struct {
logger mlogger.Logger
client *sendgrid.Client
config *SendGridConfig
producer messaging.Producer
}
func (sg *SendGridNotifier) Send(mb mmail.MailBuilder) error {
m := mail.NewV3Mail()
e := mail.NewEmail(sg.config.Email.Sender.Name, sg.config.Email.Sender.Address)
m.SetFrom(e)
task, err := mb.Build()
if err != nil {
sg.logger.Warn("Failed to build message", zap.Error(err))
return err
}
m.SetTemplateID(task.TemplateID())
p := mail.NewPersonalization()
for _, recipient := range task.Recipients() {
p.AddTos(mail.NewEmail(recipient, recipient))
}
for k, v := range task.Parameters() {
p.SetDynamicTemplateData(k, v)
}
m.AddPersonalizations(p)
response, err := sg.client.Send(m)
if err != nil {
sg.logger.Warn("Failed to send email", zap.Error(err), zap.Any("task", &task))
return err
}
if (response.StatusCode != http.StatusOK) && (response.StatusCode != http.StatusAccepted) {
sg.logger.Warn("Unexpected SendGrid sresponse", zap.Int("status_code", response.StatusCode),
zap.String("sresponse", response.Body), zap.Any("task", &task))
return merrors.Internal("email_notification_not_sent")
}
sg.logger.Info("Email sent successfully", zap.Strings("recipients", task.Recipients()), zap.String("template_id", task.TemplateID()))
// if err = sg.producer.SendMessage(model.NewNotification(model.NTEmail, model.NAComplete), &task); err != nil {
// sg.logger.Warn("Failed to send email statistics", zap.Error(err), zap.Strings("recipients", task.Recipients), zap.String("template_id", task.TemplateID))
// }
return nil
}
func (sg *SendGridNotifier) MailBuilder() mmail.MailBuilder {
return mb.NewMessageBuilder()
}
func NewSendGridNotifier(logger mlogger.Logger, producer messaging.Producer, config *SendGridConfig) (*SendGridNotifier, error) {
apiKey := os.Getenv(config.APIKeyEnv)
if apiKey == "" {
logger.Warn("No SendGrid API key")
return nil, merrors.NoData("No SendGrid API key")
}
return &SendGridNotifier{
logger: logger.Named("sendgrid"),
client: sendgrid.NewSendClient(apiKey),
config: config,
producer: producer,
}, nil
}