diff --git a/backend/app/notify/email.go b/backend/app/notify/email.go index e306eddb..e08321f1 100644 --- a/backend/app/notify/email.go +++ b/backend/app/notify/email.go @@ -177,45 +177,33 @@ func (e *Email) Send(ctx context.Context, req Request) error { result := new(multierror.Error) - // send user notifications for _, email := range req.Emails { - email := email - log.Printf("[DEBUG] send user notification via %s, comment id %s", e, req.Comment.ID) - msg, err := e.buildMessageFromRequest(req, email, false) - if err != nil { - return err - } - - err = repeater.NewDefault(5, time.Millisecond*250).Do( - ctx, - func() error { - return e.sendMessage(emailMessage{from: e.From, to: email, message: msg}) - }) - + err := e.buildAndSendMessage(ctx, req, email, false) result = multierror.Append(errors.Wrapf(err, "problem sending user email notification to %q", email)) } - // send admin notifications for _, email := range req.AdminEmails { - email := email - log.Printf("[DEBUG] send admin notification via %s, comment id %s", e, req.Comment.ID) - msg, err := e.buildMessageFromRequest(req, email, true) - if err != nil { - return err - } - - err = repeater.NewDefault(5, time.Millisecond*250).Do( - ctx, - func() error { - return e.sendMessage(emailMessage{from: e.From, to: email, message: msg}) - }) - + err := e.buildAndSendMessage(ctx, req, email, true) result = multierror.Append(errors.Wrapf(err, "problem sending admin email notification to %q", email)) } return result.ErrorOrNil() } +func (e *Email) buildAndSendMessage(ctx context.Context, req Request, email string, forAdmin bool) error { + log.Printf("[DEBUG] send notification via %s, comment id %s", e, req.Comment.ID) + msg, err := e.buildMessageFromRequest(req, email, forAdmin) + if err != nil { + return err + } + + return repeater.NewDefault(5, time.Millisecond*250).Do( + ctx, + func() error { + return e.sendMessage(emailMessage{from: e.From, to: email, message: msg}) + }) +} + // SendVerification email verification VerificationRequest.Email if it's set. // Thread safe func (e *Email) SendVerification(ctx context.Context, req VerificationRequest) error { diff --git a/backend/app/notify/email_test.go b/backend/app/notify/email_test.go index e6c76019..6d4fee2c 100644 --- a/backend/app/notify/email_test.go +++ b/backend/app/notify/email_test.go @@ -114,7 +114,10 @@ func TestEmailSendErrors(t *testing.T) { e.msgTmpl, err = template.New("test").Parse("{{.Test}}") assert.NoError(t, err) assert.EqualError(t, e.Send(context.Background(), Request{Comment: store.Comment{ID: "999"}, parent: store.Comment{User: store.User{ID: "test"}}, Emails: []string{"bad@example.org"}}), - "error executing template to build comment reply message: template: test:1:2: executing \"test\" at <.Test>: can't evaluate field Test in type notify.msgTmplData") + "1 error occurred:\n\t* problem sending user email notification to \"bad@example.org\": " + + "error executing template to build comment reply message: " + + "template: test:1:2: executing \"test\" at <.Test>: " + + "can't evaluate field Test in type notify.msgTmplData\n\n") ctx, cancel := context.WithCancel(context.Background()) cancel() @@ -123,7 +126,8 @@ func TestEmailSendErrors(t *testing.T) { e.smtp = &fakeTestSMTP{} assert.EqualError(t, e.Send(context.Background(), Request{Comment: store.Comment{ID: "999"}, parent: store.Comment{User: store.User{ID: "error"}}, Emails: []string{"bad@example.org"}}), - "error creating token for unsubscribe link: token generation error") + "1 error occurred:\n\t* problem sending user email notification to \"bad@example.org\":" + + " error creating token for unsubscribe link: token generation error\n\n") } func TestEmailSend_ExitConditions(t *testing.T) { diff --git a/backend/app/notify/notify.go b/backend/app/notify/notify.go index 1488763e..ae63db8a 100644 --- a/backend/app/notify/notify.go +++ b/backend/app/notify/notify.go @@ -37,7 +37,7 @@ type Store interface { GetUserEmail(siteID string, userID string) (string, error) } -// Request notification either about comment +// Request notification for a Comment type Request struct { Comment store.Comment parent store.Comment