diff --git a/go.mod b/go.mod index 0ef4cc2..f4b40e7 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/fatih/color v1.17.0 github.com/go-playground/validator/v10 v10.22.1 github.com/goccy/go-json v0.10.3 + github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible github.com/nats-io/nats.go v1.37.0 github.com/robfig/cron/v3 v3.0.1 github.com/rs/zerolog v1.33.0 diff --git a/go.sum b/go.sum index e4b5549..e299591 100644 --- a/go.sum +++ b/go.sum @@ -175,6 +175,8 @@ github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= diff --git a/pkg/internal/grpc/pusher.go b/pkg/internal/grpc/pusher.go index 70d721a..8449161 100644 --- a/pkg/internal/grpc/pusher.go +++ b/pkg/internal/grpc/pusher.go @@ -26,11 +26,15 @@ func (v *Server) PushNotificationBatch(ctx context.Context, request *proto.PushN } func (v *Server) DeliverEmail(ctx context.Context, request *proto.DeliverEmailRequest) (*proto.DeliveryResponse, error) { - //TODO implement me - panic("implement me") + go provider.SendMail(request.GetTo(), pushkit.NewEmailDataFromProto(request.GetEmail())) + return &proto.DeliveryResponse{IsSuccess: true}, nil } func (v *Server) DeliverEmailBatch(ctx context.Context, request *proto.DeliverEmailBatchRequest) (*proto.DeliveryResponse, error) { - //TODO implement me - panic("implement me") + go func() { + for _, to := range request.GetTo() { + _ = provider.SendMail(to, pushkit.NewEmailDataFromProto(request.GetEmail())) + } + }() + return &proto.DeliveryResponse{IsSuccess: true}, nil } diff --git a/pkg/internal/provider/apns.go b/pkg/internal/provider/apns.go index be31fdf..53c31dc 100644 --- a/pkg/internal/provider/apns.go +++ b/pkg/internal/provider/apns.go @@ -39,7 +39,7 @@ func (v *AppleNotifyProvider) Push(in pushkit.Notification, tk string) error { Topic: viper.GetString(v.topic), Payload: rawData, } - _, err := v.conn.Push(payload) + _, err = v.conn.Push(payload) return err } diff --git a/pkg/internal/provider/mailer.go b/pkg/internal/provider/mailer.go new file mode 100644 index 0000000..a06ac06 --- /dev/null +++ b/pkg/internal/provider/mailer.go @@ -0,0 +1,36 @@ +package provider + +import ( + "crypto/tls" + "fmt" + "git.solsynth.dev/hypernet/pusher/pkg/pushkit" + "github.com/jordan-wright/email" + "github.com/spf13/viper" + "net/smtp" + "net/textproto" +) + +func SendMail(target string, in pushkit.EmailData) error { + mail := &email.Email{ + To: []string{target}, + From: viper.GetString("mailer.name"), + Subject: in.Subject, + Headers: textproto.MIMEHeader{}, + } + if in.Text != nil { + mail.Text = []byte(*in.Text) + } + if in.HTML != nil { + mail.HTML = []byte(*in.HTML) + } + return mail.SendWithTLS( + fmt.Sprintf("%s:%d", viper.GetString("mailer.smtp_host"), viper.GetInt("mailer.smtp_port")), + smtp.PlainAuth( + "", + viper.GetString("mailer.username"), + viper.GetString("mailer.password"), + viper.GetString("mailer.smtp_host"), + ), + &tls.Config{ServerName: viper.GetString("mailer.smtp_host")}, + ) +} diff --git a/pkg/internal/scheduler/dispatch.go b/pkg/internal/scheduler/dispatch.go index 62957da..e11b813 100644 --- a/pkg/internal/scheduler/dispatch.go +++ b/pkg/internal/scheduler/dispatch.go @@ -47,5 +47,37 @@ func SubscribeToQueue() error { return fmt.Errorf("failed to subscribe notification batch topic: %v", err) } + _, err = mq.Nt.Subscribe(pushkit.PushEmailMqTopic, func(msg *nats.Msg) { + var req pushkit.EmailDeliverRequest + if json.Unmarshal(msg.Data, &req) != nil { + return + } else if validate.Struct(&req) != nil { + return + } + + go provider.SendMail(req.To, req.Email) + }) + if err != nil { + return fmt.Errorf("failed to subscribe email topic: %v", err) + } + + _, err = mq.Nt.Subscribe(pushkit.PushEmailBatchMqTopic, func(msg *nats.Msg) { + var req pushkit.EmailDeliverBatchRequest + if json.Unmarshal(msg.Data, &req) != nil { + return + } else if validate.Struct(&req) != nil { + return + } + + go func() { + for _, to := range req.To { + _ = provider.SendMail(to, req.Email) + } + }() + }) + if err != nil { + return fmt.Errorf("failed to subscribe email batch topic: %v", err) + } + return nil } diff --git a/pkg/pushkit/email.go b/pkg/pushkit/email.go new file mode 100644 index 0000000..ca53578 --- /dev/null +++ b/pkg/pushkit/email.go @@ -0,0 +1,30 @@ +package pushkit + +import ( + "git.solsynth.dev/hypernet/pusher/pkg/proto" + "github.com/samber/lo" +) + +type EmailDeliverRequest struct { + To string `json:"to" validate:"required"` + Email EmailData `json:"email" validate:"required"` +} + +type EmailDeliverBatchRequest struct { + To []string `json:"to" validate:"required"` + Email EmailData `json:"email" validate:"required"` +} + +type EmailData struct { + Subject string `json:"subject" validate:"required"` + Text *string `json:"text"` + HTML *string `json:"html"` +} + +func NewEmailDataFromProto(in *proto.EmailInfo) EmailData { + return EmailData{ + Subject: in.GetSubject(), + Text: lo.ToPtr(in.GetTextBody()), + HTML: lo.ToPtr(in.GetHtmlBody()), + } +} diff --git a/settings.toml b/settings.toml index efe16a4..05e6eb3 100644 --- a/settings.toml +++ b/settings.toml @@ -6,4 +6,11 @@ nexus_addr = "127.0.0.1:7001" [debug] database = false -print_routes = false \ No newline at end of file +print_routes = false + +[mailer] +name = "Alphabot " +smtp_host = "smtp.exmail.qq.com" +smtp_port = 465 +username = "alphabot@smartsheep.studio" +password = "gz937Zxxzfcd9SeH"