Added email notification option to receive all own messages (#20179)

Sometimes users want to receive email notifications of messages they create or reply to,
Added an option to personal preferences to allow users to choose

Closes #20149
This commit is contained in:
Tyrone Yeh 2022-07-28 16:30:12 +08:00 committed by GitHub
parent 86e5268c39
commit 3bd8f50af8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 18 additions and 7 deletions

View file

@ -64,12 +64,14 @@ var AvailableHashAlgorithms = []string{
} }
const ( const (
// EmailNotificationsEnabled indicates that the user would like to receive all email notifications // EmailNotificationsEnabled indicates that the user would like to receive all email notifications except your own
EmailNotificationsEnabled = "enabled" EmailNotificationsEnabled = "enabled"
// EmailNotificationsOnMention indicates that the user would like to be notified via email when mentioned. // EmailNotificationsOnMention indicates that the user would like to be notified via email when mentioned.
EmailNotificationsOnMention = "onmention" EmailNotificationsOnMention = "onmention"
// EmailNotificationsDisabled indicates that the user would not like to be notified via email. // EmailNotificationsDisabled indicates that the user would not like to be notified via email.
EmailNotificationsDisabled = "disabled" EmailNotificationsDisabled = "disabled"
// EmailNotificationsEnabled indicates that the user would like to receive all email notifications and your own
EmailNotificationsAndYourOwn = "andyourown"
) )
// User represents the object of individual and member of organization. // User represents the object of individual and member of organization.
@ -1045,7 +1047,7 @@ func GetMaileableUsersByIDs(ids []int64, isMention bool) ([]*User, error) {
Where("`type` = ?", UserTypeIndividual). Where("`type` = ?", UserTypeIndividual).
And("`prohibit_login` = ?", false). And("`prohibit_login` = ?", false).
And("`is_active` = ?", true). And("`is_active` = ?", true).
And("`email_notifications_preference` IN ( ?, ?)", EmailNotificationsEnabled, EmailNotificationsOnMention). In("`email_notifications_preference`", EmailNotificationsEnabled, EmailNotificationsOnMention, EmailNotificationsAndYourOwn).
Find(&ous) Find(&ous)
} }
@ -1053,7 +1055,7 @@ func GetMaileableUsersByIDs(ids []int64, isMention bool) ([]*User, error) {
Where("`type` = ?", UserTypeIndividual). Where("`type` = ?", UserTypeIndividual).
And("`prohibit_login` = ?", false). And("`prohibit_login` = ?", false).
And("`is_active` = ?", true). And("`is_active` = ?", true).
And("`email_notifications_preference` = ?", EmailNotificationsEnabled). In("`email_notifications_preference`", EmailNotificationsEnabled, EmailNotificationsAndYourOwn).
Find(&ous) Find(&ous)
} }

View file

@ -153,6 +153,9 @@ func TestEmailNotificationPreferences(t *testing.T) {
assert.NoError(t, user_model.SetEmailNotifications(user, user_model.EmailNotificationsDisabled)) assert.NoError(t, user_model.SetEmailNotifications(user, user_model.EmailNotificationsDisabled))
assert.Equal(t, user_model.EmailNotificationsDisabled, user.EmailNotifications()) assert.Equal(t, user_model.EmailNotificationsDisabled, user.EmailNotifications())
assert.NoError(t, user_model.SetEmailNotifications(user, user_model.EmailNotificationsAndYourOwn))
assert.Equal(t, user_model.EmailNotificationsAndYourOwn, user.EmailNotifications())
} }
} }

View file

@ -126,7 +126,7 @@ func (m *mailNotifier) NotifyPullRequestCodeComment(pr *issues_model.PullRequest
func (m *mailNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) { func (m *mailNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *issues_model.Issue, assignee *user_model.User, removed bool, comment *issues_model.Comment) {
// mail only sent to added assignees and not self-assignee // mail only sent to added assignees and not self-assignee
if !removed && doer.ID != assignee.ID && (assignee.EmailNotifications() == user_model.EmailNotificationsEnabled || assignee.EmailNotifications() == user_model.EmailNotificationsOnMention) { if !removed && doer.ID != assignee.ID && assignee.EmailNotifications() != user_model.EmailNotificationsDisabled {
ct := fmt.Sprintf("Assigned #%d.", issue.Index) ct := fmt.Sprintf("Assigned #%d.", issue.Index)
if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{assignee}); err != nil { if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{assignee}); err != nil {
log.Error("Error in SendIssueAssignedMail for issue[%d] to assignee[%d]: %v", issue.ID, assignee.ID, err) log.Error("Error in SendIssueAssignedMail for issue[%d] to assignee[%d]: %v", issue.ID, assignee.ID, err)
@ -135,7 +135,7 @@ func (m *mailNotifier) NotifyIssueChangeAssignee(doer *user_model.User, issue *i
} }
func (m *mailNotifier) NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { func (m *mailNotifier) NotifyPullReviewRequest(doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) {
if isRequest && doer.ID != reviewer.ID && (reviewer.EmailNotifications() == user_model.EmailNotificationsEnabled || reviewer.EmailNotifications() == user_model.EmailNotificationsOnMention) { if isRequest && doer.ID != reviewer.ID && reviewer.EmailNotifications() != user_model.EmailNotificationsDisabled {
ct := fmt.Sprintf("Requested to review %s.", issue.HTMLURL()) ct := fmt.Sprintf("Requested to review %s.", issue.HTMLURL())
if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{reviewer}); err != nil { if err := mailer.SendIssueAssignedMail(issue, doer, ct, comment, []*user_model.User{reviewer}); err != nil {
log.Error("Error in SendIssueAssignedMail for issue[%d] to reviewer[%d]: %v", issue.ID, reviewer.ID, err) log.Error("Error in SendIssueAssignedMail for issue[%d] to reviewer[%d]: %v", issue.ID, reviewer.ID, err)

View file

@ -1787,6 +1787,7 @@ settings.mirror_sync_in_progress = Mirror synchronization is in progress. Check
settings.email_notifications.enable = Enable Email Notifications settings.email_notifications.enable = Enable Email Notifications
settings.email_notifications.onmention = Only Email on Mention settings.email_notifications.onmention = Only Email on Mention
settings.email_notifications.disable = Disable Email Notifications settings.email_notifications.disable = Disable Email Notifications
settings.email_notifications.andyourown = And Your Own Email Notifications
settings.email_notifications.submit = Set Email Preference settings.email_notifications.submit = Set Email Preference
settings.site = Website settings.site = Website
settings.update_settings = Update Settings settings.update_settings = Update Settings

View file

@ -156,7 +156,8 @@ func EmailPost(ctx *context.Context) {
preference := ctx.FormString("preference") preference := ctx.FormString("preference")
if !(preference == user_model.EmailNotificationsEnabled || if !(preference == user_model.EmailNotificationsEnabled ||
preference == user_model.EmailNotificationsOnMention || preference == user_model.EmailNotificationsOnMention ||
preference == user_model.EmailNotificationsDisabled) { preference == user_model.EmailNotificationsDisabled ||
preference == user_model.EmailNotificationsAndYourOwn) {
log.Error("Email notifications preference change returned unrecognized option %s: %s", preference, ctx.Doer.Name) log.Error("Email notifications preference change returned unrecognized option %s: %s", preference, ctx.Doer.Name)
ctx.ServerError("SetEmailPreference", errors.New("option unrecognized")) ctx.ServerError("SetEmailPreference", errors.New("option unrecognized"))
return return

View file

@ -91,7 +91,9 @@ func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*user_mo
visited := make(map[int64]bool, len(unfiltered)+len(mentions)+1) visited := make(map[int64]bool, len(unfiltered)+len(mentions)+1)
// Avoid mailing the doer // Avoid mailing the doer
visited[ctx.Doer.ID] = true if ctx.Doer.EmailNotificationsPreference != user_model.EmailNotificationsAndYourOwn {
visited[ctx.Doer.ID] = true
}
// =========== Mentions =========== // =========== Mentions ===========
if err = mailIssueCommentBatch(ctx, mentions, visited, true); err != nil { if err = mailIssueCommentBatch(ctx, mentions, visited, true); err != nil {
@ -133,6 +135,7 @@ func mailIssueCommentBatch(ctx *mailCommentContext, users []*user_model.User, vi
// At this point we exclude: // At this point we exclude:
// user that don't have all mails enabled or users only get mail on mention and this is one ... // user that don't have all mails enabled or users only get mail on mention and this is one ...
if !(user.EmailNotificationsPreference == user_model.EmailNotificationsEnabled || if !(user.EmailNotificationsPreference == user_model.EmailNotificationsEnabled ||
user.EmailNotificationsPreference == user_model.EmailNotificationsAndYourOwn ||
fromMention && user.EmailNotificationsPreference == user_model.EmailNotificationsOnMention) { fromMention && user.EmailNotificationsPreference == user_model.EmailNotificationsOnMention) {
continue continue
} }

View file

@ -62,6 +62,7 @@
<div class="text">{{$.locale.Tr "settings.email_notifications"}}</div> <div class="text">{{$.locale.Tr "settings.email_notifications"}}</div>
<div class="menu"> <div class="menu">
<div data-value="enabled" class="{{if eq .EmailNotificationsPreference "enabled"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.enable"}}</div> <div data-value="enabled" class="{{if eq .EmailNotificationsPreference "enabled"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.enable"}}</div>
<div data-value="andyourown" class="{{if eq .EmailNotificationsPreference "andyourown"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.andyourown"}}</div>
<div data-value="onmention" class="{{if eq .EmailNotificationsPreference "onmention"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.onmention"}}</div> <div data-value="onmention" class="{{if eq .EmailNotificationsPreference "onmention"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.onmention"}}</div>
<div data-value="disabled" class="{{if eq .EmailNotificationsPreference "disabled"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.disable"}}</div> <div data-value="disabled" class="{{if eq .EmailNotificationsPreference "disabled"}}active selected {{end}}item">{{$.locale.Tr "settings.email_notifications.disable"}}</div>
</div> </div>