From 057829ee04e53910b348383804f47d3df8a27a13 Mon Sep 17 00:00:00 2001 From: "taekyu.kang" Date: Thu, 11 Apr 2024 16:58:26 +0900 Subject: [PATCH] feature. support sending email to multiple targets --- internal/mail/content.go | 11 ++--- internal/mail/ses.go | 2 +- internal/mail/smtp.go | 15 +++--- internal/usecase/app-group.go | 2 +- internal/usecase/system-notification.go | 61 +++++++++++++++++-------- pkg/domain/system-notification.go | 13 +++--- 6 files changed, 64 insertions(+), 40 deletions(-) diff --git a/internal/mail/content.go b/internal/mail/content.go index 9a7abbb3..417d00cf 100644 --- a/internal/mail/content.go +++ b/internal/mail/content.go @@ -27,7 +27,7 @@ func MakeVerityIdentityMessage(ctx context.Context, to, code string) (*MessageIn m := &MessageInfo{ From: from, - To: to, + To: []string{to}, Subject: subject, Body: tpl.String(), } @@ -54,7 +54,7 @@ func MakeTemporaryPasswordMessage(ctx context.Context, to, organizationId, accou m := &MessageInfo{ From: from, - To: to, + To: []string{to}, Subject: subject, Body: tpl.String(), } @@ -90,7 +90,7 @@ func MakeGeneratingOrganizationMessage( m := &MessageInfo{ From: from, - To: to, + To: []string{to}, Subject: subject, Body: tpl.String(), } @@ -98,10 +98,7 @@ func MakeGeneratingOrganizationMessage( return m, nil } -func MakeSystemNotificationMessage( - ctx context.Context, - organizationId string, title string, - to string) (*MessageInfo, error) { +func MakeSystemNotificationMessage(ctx context.Context, organizationId string, title string, to []string) (*MessageInfo, error) { subject := "[TKS] 시스템 알림이 발생하였습니다." tmpl, err := template.ParseFS(templateFS, "contents/system_notification.html") diff --git a/internal/mail/ses.go b/internal/mail/ses.go index eb7a4f0a..787e1324 100644 --- a/internal/mail/ses.go +++ b/internal/mail/ses.go @@ -23,7 +23,7 @@ type AwsMailer struct { func (a *AwsMailer) SendMail(ctx context.Context) error { input := &awsSes.SendEmailInput{ Destination: &types.Destination{ - ToAddresses: []string{a.message.To}, + ToAddresses: a.message.To, }, Message: &types.Message{ Subject: &types.Content{ diff --git a/internal/mail/smtp.go b/internal/mail/smtp.go index 62dc4578..ef673310 100644 --- a/internal/mail/smtp.go +++ b/internal/mail/smtp.go @@ -33,7 +33,7 @@ type Mailer interface { type MessageInfo struct { From string - To string + To []string Subject string Body string } @@ -50,14 +50,17 @@ type SmtpMailer struct { func (s *SmtpMailer) SendMail(ctx context.Context) error { s.client.SetHeader("From", s.message.From) - s.client.SetHeader("To", s.message.To) s.client.SetHeader("Subject", s.message.Subject) s.client.SetBody("text/html", s.message.Body) - d := NewDialer(s.Host, s.Port, s.Username, s.Password) - if err := d.DialAndSend(s.client); err != nil { - log.Errorf(ctx, "failed to send email, %v", err) - return err + + for _, to := range s.message.To { + s.client.SetHeader("To", to) + + if err := d.DialAndSend(s.client); err != nil { + log.Errorf(ctx, "failed to send email, %v", err) + continue + } } return nil diff --git a/internal/usecase/app-group.go b/internal/usecase/app-group.go index 39d7c8ac..37896b64 100644 --- a/internal/usecase/app-group.go +++ b/internal/usecase/app-group.go @@ -127,7 +127,7 @@ func (u *AppGroupUsecase) Create(ctx context.Context, dto model.AppGroup) (id do "app_group_id=" + dto.ID.String(), "keycloak_url=" + strings.TrimSuffix(viper.GetString("keycloak-address"), "/auth"), "console_url=" + viper.GetString("console-address"), - "alert_tks=" + viper.GetString("external-address") + "/system-api/1.0/alerts", + "alert_tks=" + viper.GetString("external-address") + "/system-api/1.0/system-notifications", "alert_slack=" + viper.GetString("alert-slack"), "cloud_account_id=" + tksCloudAccountId, "object_store=" + tksObjectStore, diff --git a/internal/usecase/system-notification.go b/internal/usecase/system-notification.go index 09a1b688..2543ab9e 100644 --- a/internal/usecase/system-notification.go +++ b/internal/usecase/system-notification.go @@ -8,6 +8,7 @@ import ( "time" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/mail" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -31,18 +32,20 @@ type ISystemNotificationUsecase interface { } type SystemNotificationUsecase struct { - repo repository.ISystemNotificationRepository - clusterRepo repository.IClusterRepository - organizationRepo repository.IOrganizationRepository - appGroupRepo repository.IAppGroupRepository + repo repository.ISystemNotificationRepository + clusterRepo repository.IClusterRepository + organizationRepo repository.IOrganizationRepository + appGroupRepo repository.IAppGroupRepository + systemNotificationRuleRepo repository.ISystemNotificationRuleRepository } func NewSystemNotificationUsecase(r repository.Repository) ISystemNotificationUsecase { return &SystemNotificationUsecase{ - repo: r.SystemNotification, - clusterRepo: r.Cluster, - appGroupRepo: r.AppGroup, - organizationRepo: r.Organization, + repo: r.SystemNotification, + clusterRepo: r.Cluster, + appGroupRepo: r.AppGroup, + organizationRepo: r.Organization, + systemNotificationRuleRepo: r.SystemNotificationRule, } } @@ -117,20 +120,40 @@ func (u *SystemNotificationUsecase) Create(ctx context.Context, input domain.Cre _, err = u.repo.Create(ctx, dto) if err != nil { + log.Error(ctx, "Failed to create systemNotification ", err) continue } - /* - for _, user := range dto.System - message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, "test", dto.Users, user.AccountId, randomPassword) - if err != nil { - return nil, httpErrors.NewInternalServerError(err, "", "") - } - mailer := mail.New(message) - if err := mailer.SendMail(ctx); err != nil { - return nil, httpErrors.NewInternalServerError(err, "", "") - } - */ + if systemNotification.Annotations.SystemNotificationRuleId == "" { + log.Error(ctx, "Invalid systemNotificationRuleId ") + continue + } + + systemNotificationRuleId, err := uuid.Parse(systemNotification.Annotations.SystemNotificationRuleId) + if err != nil { + log.Error(ctx, "Failed to parse uuid ", err) + continue + } + rule, err := u.systemNotificationRuleRepo.Get(ctx, systemNotificationRuleId) + if err != nil { + log.Error(ctx, "Failed to get systemNotificationRule ", err) + continue + } + + to := []string{} + for _, user := range rule.TargetUsers { + to = append(to, user.Email) + } + message, err := mail.MakeSystemNotificationMessage(ctx, organizationId, systemNotification.Annotations.Message, to) + if err != nil { + log.Error(ctx, fmt.Sprintf("Failed to make email content. err : %s", err.Error())) + continue + } + mailer := mail.New(message) + if err := mailer.SendMail(ctx); err != nil { + log.Error(ctx, fmt.Sprintf("Failed to send email to %s. err : %s", to, err.Error())) + continue + } } return nil diff --git a/pkg/domain/system-notification.go b/pkg/domain/system-notification.go index 697f7968..f95868ef 100644 --- a/pkg/domain/system-notification.go +++ b/pkg/domain/system-notification.go @@ -53,12 +53,13 @@ type SystemNotificationRequest struct { TacoCluster string `json:"taco_cluster"` } `json:"labels"` Annotations struct { - Message string `json:"message"` - Summary string `json:"summary"` - Description string `json:"description"` - Checkpoint string `json:"Checkpoint"` - Discriminative string `json:"discriminative"` - AlertType string `json:"alertType"` + Message string `json:"message"` + Summary string `json:"summary"` + Description string `json:"description"` + Checkpoint string `json:"Checkpoint"` + Discriminative string `json:"discriminative"` + AlertType string `json:"alertType"` + SystemNotificationRuleId string `json:"systemNotificationRuleId"` } `json:"annotations"` }