2016-07-15 19:36:39 +03:00
// Copyright 2016 The Gogs Authors. All rights reserved.
2018-08-24 07:41:26 +03:00
// Copyright 2018 The Gitea Authors. All rights reserved.
2016-07-15 19:36:39 +03:00
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"fmt"
"github.com/Unknwon/com"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/log"
2017-09-16 20:17:57 +03:00
"code.gitea.io/gitea/modules/markup"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/setting"
2016-07-15 19:36:39 +03:00
)
2016-11-25 11:11:12 +03:00
func ( issue * Issue ) mailSubject ( ) string {
2019-05-28 12:41:48 +03:00
return fmt . Sprintf ( "[%s] %s (#%d)" , issue . Repo . FullName ( ) , issue . Title , issue . Index )
2016-07-15 19:36:39 +03:00
}
// mailIssueCommentToParticipants can be used for both new issue creation and comment.
2017-03-16 04:34:24 +03:00
// This function sends two list of emails:
// 1. Repository watchers and users who are participated in comments.
// 2. Users who are not in 1. but get mentioned in current issue/comment.
2017-11-03 12:23:17 +03:00
func mailIssueCommentToParticipants ( e Engine , issue * Issue , doer * User , content string , comment * Comment , mentions [ ] string ) error {
2016-07-15 19:36:39 +03:00
if ! setting . Service . EnableNotifyMail {
return nil
}
2017-08-30 07:31:33 +03:00
watchers , err := getWatchers ( e , issue . RepoID )
2016-07-15 19:36:39 +03:00
if err != nil {
2017-08-30 07:31:33 +03:00
return fmt . Errorf ( "getWatchers [repo_id: %d]: %v" , issue . RepoID , err )
2017-03-16 04:34:24 +03:00
}
2017-08-30 07:31:33 +03:00
participants , err := getParticipantsByIssueID ( e , issue . ID )
2017-03-16 04:34:24 +03:00
if err != nil {
2017-08-30 07:31:33 +03:00
return fmt . Errorf ( "getParticipantsByIssueID [issue_id: %d]: %v" , issue . ID , err )
2017-03-16 04:34:24 +03:00
}
2017-09-16 03:18:25 +03:00
// In case the issue poster is not watching the repository and is active,
2017-03-16 04:34:24 +03:00
// even if we have duplicated in watchers, can be safely filtered out.
2019-01-30 00:26:17 +03:00
err = issue . loadPoster ( e )
2017-09-16 03:18:25 +03:00
if err != nil {
return fmt . Errorf ( "GetUserByID [%d]: %v" , issue . PosterID , err )
}
2019-01-30 00:26:17 +03:00
if issue . PosterID != doer . ID && issue . Poster . IsActive && ! issue . Poster . ProhibitLogin {
2017-03-16 04:34:24 +03:00
participants = append ( participants , issue . Poster )
2016-07-15 19:36:39 +03:00
}
2018-05-09 19:29:04 +03:00
// Assignees must receive any communications
2019-01-05 00:51:27 +03:00
assignees , err := getAssigneesByIssue ( e , issue )
2018-05-09 19:29:04 +03:00
if err != nil {
return err
}
for _ , assignee := range assignees {
if assignee . ID != doer . ID {
participants = append ( participants , assignee )
}
2017-06-23 16:43:37 +03:00
}
2016-07-15 19:36:39 +03:00
tos := make ( [ ] string , 0 , len ( watchers ) ) // List of email addresses.
names := make ( [ ] string , 0 , len ( watchers ) )
for i := range watchers {
2016-07-23 20:08:22 +03:00
if watchers [ i ] . UserID == doer . ID {
2016-07-15 19:36:39 +03:00
continue
}
2017-08-30 07:31:33 +03:00
to , err := getUserByID ( e , watchers [ i ] . UserID )
2016-07-15 19:36:39 +03:00
if err != nil {
return fmt . Errorf ( "GetUserByID [%d]: %v" , watchers [ i ] . UserID , err )
}
if to . IsOrganization ( ) {
continue
}
tos = append ( tos , to . Email )
names = append ( names , to . Name )
}
2017-03-16 04:34:24 +03:00
for i := range participants {
if participants [ i ] . ID == doer . ID {
continue
} else if com . IsSliceContainsStr ( names , participants [ i ] . Name ) {
continue
}
tos = append ( tos , participants [ i ] . Email )
names = append ( names , participants [ i ] . Name )
}
2017-05-25 05:38:56 +03:00
2019-01-30 01:43:40 +03:00
if err := issue . loadRepo ( e ) ; err != nil {
return err
}
2018-08-24 07:41:26 +03:00
for _ , to := range tos {
SendIssueCommentMail ( issue , doer , content , comment , [ ] string { to } )
}
2016-07-15 19:36:39 +03:00
// Mail mentioned people and exclude watchers.
names = append ( names , doer . Name )
tos = make ( [ ] string , 0 , len ( mentions ) ) // list of user names.
for i := range mentions {
if com . IsSliceContainsStr ( names , mentions [ i ] ) {
continue
}
tos = append ( tos , mentions [ i ] )
}
2018-08-24 07:41:26 +03:00
emails := getUserEmailsByNames ( e , tos )
for _ , to := range emails {
SendIssueMentionMail ( issue , doer , content , comment , [ ] string { to } )
}
2016-07-15 19:36:39 +03:00
return nil
}
// MailParticipants sends new issue thread created emails to repository watchers
// and mentioned people.
2019-06-11 22:27:38 +03:00
func ( issue * Issue ) MailParticipants ( doer * User , opType ActionType ) ( err error ) {
return issue . mailParticipants ( x , doer , opType )
2017-08-30 07:31:33 +03:00
}
2019-06-11 22:27:38 +03:00
func ( issue * Issue ) mailParticipants ( e Engine , doer * User , opType ActionType ) ( err error ) {
2017-09-16 20:17:57 +03:00
mentions := markup . FindAllMentions ( issue . Content )
2019-06-11 22:27:38 +03:00
2017-08-30 07:31:33 +03:00
if err = UpdateIssueMentions ( e , issue . ID , mentions ) ; err != nil {
2016-07-15 19:36:39 +03:00
return fmt . Errorf ( "UpdateIssueMentions [%d]: %v" , issue . ID , err )
}
2019-06-11 22:27:38 +03:00
if len ( issue . Content ) > 0 {
if err = mailIssueCommentToParticipants ( e , issue , doer , issue . Content , nil , mentions ) ; err != nil {
log . Error ( "mailIssueCommentToParticipants: %v" , err )
}
}
2019-04-12 00:59:01 +03:00
switch opType {
2019-06-11 22:27:38 +03:00
case ActionCreateIssue , ActionCreatePullRequest :
if len ( issue . Content ) == 0 {
ct := fmt . Sprintf ( "Created #%d." , issue . Index )
if err = mailIssueCommentToParticipants ( e , issue , doer , ct , nil , mentions ) ; err != nil {
log . Error ( "mailIssueCommentToParticipants: %v" , err )
}
}
2019-04-12 00:59:01 +03:00
case ActionCloseIssue , ActionClosePullRequest :
2019-06-11 22:27:38 +03:00
ct := fmt . Sprintf ( "Closed #%d." , issue . Index )
if err = mailIssueCommentToParticipants ( e , issue , doer , ct , nil , mentions ) ; err != nil {
log . Error ( "mailIssueCommentToParticipants: %v" , err )
}
2019-04-12 00:59:01 +03:00
case ActionReopenIssue , ActionReopenPullRequest :
2019-06-11 22:27:38 +03:00
ct := fmt . Sprintf ( "Reopened #%d." , issue . Index )
if err = mailIssueCommentToParticipants ( e , issue , doer , ct , nil , mentions ) ; err != nil {
log . Error ( "mailIssueCommentToParticipants: %v" , err )
}
2016-07-15 19:36:39 +03:00
}
return nil
}