From 5504e98714d9bf0f3ea77a39b32cd0f96bd36698 Mon Sep 17 00:00:00 2001 From: Xeronith Date: Wed, 7 Jun 2023 11:02:03 +0330 Subject: [PATCH] refactor(providers): :technologist: improve messaging and email --- components/core/system_component.go | 3 +- .../outbound/common/messaging/provider.go | 11 +++-- providers/outbound/email/postmark/handler.go | 47 +++++++++++++++++++ providers/outbound/email/postmark/provider.go | 30 ++++++++++++ .../outbound/email/postmark/provider_test.go | 17 +++++++ providers/outbound/email/provider.go | 17 +------ .../outbound/email/{ => sendgrid}/handler.go | 4 +- providers/outbound/email/sendgrid/provider.go | 30 ++++++++++++ .../email/{ => sendgrid}/provider_test.go | 6 +-- providers/outbound/sms/handler.go | 2 +- providers/outbound/sms/provider.go | 6 +-- 11 files changed, 143 insertions(+), 30 deletions(-) create mode 100644 providers/outbound/email/postmark/handler.go create mode 100644 providers/outbound/email/postmark/provider.go create mode 100644 providers/outbound/email/postmark/provider_test.go rename providers/outbound/email/{ => sendgrid}/handler.go (87%) create mode 100644 providers/outbound/email/sendgrid/provider.go rename providers/outbound/email/{ => sendgrid}/provider_test.go (64%) diff --git a/components/core/system_component.go b/components/core/system_component.go index c291eeb..d04db1d 100644 --- a/components/core/system_component.go +++ b/components/core/system_component.go @@ -117,8 +117,7 @@ func (component *systemComponent) GenerateRSAKeyPair() (string, string, error) { func (component *systemComponent) Email(destination string, format string, args ...interface{}) { component.Async(func() { - message := fmt.Sprintf(format, args...) - component.emailProvider.Send(destination, message) + component.emailProvider.Send(destination, format, args...) }) } diff --git a/providers/outbound/common/messaging/provider.go b/providers/outbound/common/messaging/provider.go index 05bd700..5cb23e7 100644 --- a/providers/outbound/common/messaging/provider.go +++ b/providers/outbound/common/messaging/provider.go @@ -4,9 +4,14 @@ import ( "fmt" . "github.com/xeronith/diamante/contracts/logging" - . "github.com/xeronith/diamante/contracts/messaging" ) +type IMessagingHandler func(receiver string, template string, model map[string]interface{}) error + +type IMessagingProvider interface { + Send(receiver string, template string, model map[string]interface{}) error +} + type provider struct { name string logger ILogger @@ -21,8 +26,8 @@ func NewProvider(name string, logger ILogger, handler IMessagingHandler) IMessag } } -func (provider *provider) Send(receiver, message string) error { - if err := provider.handler(receiver, message); err != nil { +func (provider *provider) Send(receiver, message string, model map[string]interface{}) error { + if err := provider.handler(receiver, message, model); err != nil { provider.logger.Error(fmt.Sprintf("%s: %s", provider.name, err.Error())) return err } else { diff --git a/providers/outbound/email/postmark/handler.go b/providers/outbound/email/postmark/handler.go new file mode 100644 index 0000000..d6b3f77 --- /dev/null +++ b/providers/outbound/email/postmark/handler.go @@ -0,0 +1,47 @@ +package postmark + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "os" +) + +var client = &http.Client{} + +func handler(receiver, templateAlias string, model map[string]interface{}) error { + emailBody := map[string]interface{}{ + "From": "GreatApe ", + "To": receiver, + "TemplateAlias": templateAlias, + "TemplateModel": model, + } + + requestBody, _ := json.Marshal(emailBody) + buffer := bytes.NewBuffer(requestBody) + + r, err := http.NewRequest("POST", "https://api.postmarkapp.com/email/withTemplate", buffer) + if err != nil { + return err + } + + token := os.Getenv("POSTMARK_TOKEN") + + r.Header.Add("Content-Type", "application/json") + r.Header.Add("Accept", "application/json") + r.Header.Add("X-Postmark-Server-Token", token) + + resp, err := client.Do(r) + if err != nil { + return err + } + + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("error sending email to %s", receiver) + } + + return nil +} diff --git a/providers/outbound/email/postmark/provider.go b/providers/outbound/email/postmark/provider.go new file mode 100644 index 0000000..d1df34e --- /dev/null +++ b/providers/outbound/email/postmark/provider.go @@ -0,0 +1,30 @@ +package postmark + +import ( + "github.com/reiver/greatape/providers/outbound/common/messaging" + "github.com/xeronith/diamante/contracts/email" + "github.com/xeronith/diamante/contracts/logging" +) + +const ProviderName = "POSTMARK_EMAIL_PROVIDER" + +type provider struct { + messaging messaging.IMessagingProvider +} + +func NewProvider(logger logging.ILogger) email.IEmailProvider { + return &provider{ + messaging: messaging.NewProvider(ProviderName, logger, handler), + } +} + +func (provider *provider) Send(receiver, template string, args ...interface{}) error { + model := map[string]interface{}{} + if len(args) > 0 { + if data, ok := args[0].(map[string]interface{}); ok { + model = data + } + } + + return provider.messaging.Send(receiver, template, model) +} diff --git a/providers/outbound/email/postmark/provider_test.go b/providers/outbound/email/postmark/provider_test.go new file mode 100644 index 0000000..a979dff --- /dev/null +++ b/providers/outbound/email/postmark/provider_test.go @@ -0,0 +1,17 @@ +package postmark_test + +import ( + "testing" + + "github.com/reiver/greatape/providers/outbound/email/postmark" + "github.com/xeronith/diamante/logging" +) + +func Test_Send(t *testing.T) { + logger := logging.NewLogger(false) + provider := postmark.NewProvider(logger) + + if err := provider.Send("somebody@somewhere.com", "template-alias", map[string]interface{}{}); err != nil { + t.Fatal(err) + } +} diff --git a/providers/outbound/email/provider.go b/providers/outbound/email/provider.go index e5c3bbf..fc92677 100644 --- a/providers/outbound/email/provider.go +++ b/providers/outbound/email/provider.go @@ -1,25 +1,12 @@ package email import ( - "github.com/reiver/greatape/providers/outbound/common/messaging" "github.com/xeronith/diamante/contracts/logging" + "github.com/reiver/greatape/providers/outbound/email/postmark" "github.com/xeronith/diamante/contracts/email" - . "github.com/xeronith/diamante/contracts/messaging" ) -const EmailProvider = "EMAIL_PROVIDER" - -type provider struct { - messaging IMessagingProvider -} - func NewProvider(logger logging.ILogger) email.IEmailProvider { - return &provider{ - messaging: messaging.NewProvider(EmailProvider, logger, handler), - } -} - -func (provider *provider) Send(receiver, message string) error { - return provider.messaging.Send(receiver, message) + return postmark.NewProvider(logger) } diff --git a/providers/outbound/email/handler.go b/providers/outbound/email/sendgrid/handler.go similarity index 87% rename from providers/outbound/email/handler.go rename to providers/outbound/email/sendgrid/handler.go index 8a2d015..99d33d6 100644 --- a/providers/outbound/email/handler.go +++ b/providers/outbound/email/sendgrid/handler.go @@ -1,4 +1,4 @@ -package email +package sendgrid import ( "fmt" @@ -9,7 +9,7 @@ import ( "github.com/sendgrid/sendgrid-go/helpers/mail" ) -func handler(receiver, content string) error { +func handler(receiver, content string, _ map[string]interface{}) error { from := mail.NewEmail("Admin", "admin@site") subject := "Subject" to := mail.NewEmail(receiver, receiver) diff --git a/providers/outbound/email/sendgrid/provider.go b/providers/outbound/email/sendgrid/provider.go new file mode 100644 index 0000000..7c4a1f5 --- /dev/null +++ b/providers/outbound/email/sendgrid/provider.go @@ -0,0 +1,30 @@ +package sendgrid + +import ( + "github.com/reiver/greatape/providers/outbound/common/messaging" + "github.com/xeronith/diamante/contracts/email" + "github.com/xeronith/diamante/contracts/logging" +) + +const ProviderName = "SENDGRID_EMAIL_PROVIDER" + +type provider struct { + messaging messaging.IMessagingProvider +} + +func NewProvider(logger logging.ILogger) email.IEmailProvider { + return &provider{ + messaging: messaging.NewProvider(ProviderName, logger, handler), + } +} + +func (provider *provider) Send(receiver, template string, args ...interface{}) error { + model := map[string]interface{}{} + if len(args) > 0 { + if data, ok := args[0].(map[string]interface{}); ok { + model = data + } + } + + return provider.messaging.Send(receiver, template, model) +} diff --git a/providers/outbound/email/provider_test.go b/providers/outbound/email/sendgrid/provider_test.go similarity index 64% rename from providers/outbound/email/provider_test.go rename to providers/outbound/email/sendgrid/provider_test.go index 767f4ca..9485fe1 100644 --- a/providers/outbound/email/provider_test.go +++ b/providers/outbound/email/sendgrid/provider_test.go @@ -1,15 +1,15 @@ -package email_test +package sendgrid_test import ( "testing" - "github.com/reiver/greatape/providers/outbound/email" + "github.com/reiver/greatape/providers/outbound/email/sendgrid" "github.com/xeronith/diamante/logging" ) func Test_Send(t *testing.T) { logger := logging.NewLogger(false) - provider := email.NewProvider(logger) + provider := sendgrid.NewProvider(logger) if err := provider.Send("somebody@somewhere.com", "Message content"); err != nil { t.Fatal(err) diff --git a/providers/outbound/sms/handler.go b/providers/outbound/sms/handler.go index d3845cc..221419a 100644 --- a/providers/outbound/sms/handler.go +++ b/providers/outbound/sms/handler.go @@ -2,6 +2,6 @@ package sms import "fmt" -func handler(receiver, message string) error { +func handler(receiver, message string, _ map[string]interface{}) error { return fmt.Errorf("not_implemented %s %s", receiver, message) } diff --git a/providers/outbound/sms/provider.go b/providers/outbound/sms/provider.go index 5a040a2..951d3e9 100644 --- a/providers/outbound/sms/provider.go +++ b/providers/outbound/sms/provider.go @@ -3,15 +3,13 @@ package sms import ( "github.com/reiver/greatape/providers/outbound/common/messaging" "github.com/xeronith/diamante/contracts/logging" - - . "github.com/xeronith/diamante/contracts/messaging" "github.com/xeronith/diamante/contracts/sms" ) const SMSProvider = "SMS_PROVIDER" type provider struct { - messaging IMessagingProvider + messaging messaging.IMessagingProvider } func NewProvider(logger logging.ILogger) sms.ISMSProvider { @@ -21,5 +19,5 @@ func NewProvider(logger logging.ILogger) sms.ISMSProvider { } func (provider *provider) Send(receiver, message string) error { - return provider.messaging.Send(receiver, message) + return provider.messaging.Send(receiver, message, nil) }