@@ -164,13 +164,7 @@ func SendCollaboratorMail(u, doer *models.User, repo *models.Repository) {
164
164
SendAsync (msg )
165
165
}
166
166
167
- func composeIssueCommentMessage (issue * models.Issue , doer * models.User , actionType models.ActionType , fromMention bool ,
168
- content string , comment * models.Comment , tos []string , info string ) * Message {
169
-
170
- if err := issue .LoadPullRequest (); err != nil {
171
- log .Error ("LoadPullRequest: %v" , err )
172
- return nil
173
- }
167
+ func composeIssueCommentMessages (ctx * mailCommentContext , tos []string , fromMention bool , info string ) []* Message {
174
168
175
169
var (
176
170
subject string
@@ -182,29 +176,29 @@ func composeIssueCommentMessage(issue *models.Issue, doer *models.User, actionTy
182
176
)
183
177
184
178
commentType := models .CommentTypeComment
185
- if comment != nil {
179
+ if ctx . Comment != nil {
186
180
prefix = "Re: "
187
- commentType = comment .Type
188
- link = issue . HTMLURL () + "#" + comment .HashTag ()
181
+ commentType = ctx . Comment .Type
182
+ link = ctx . Issue . HTMLURL () + "#" + ctx . Comment .HashTag ()
189
183
} else {
190
- link = issue .HTMLURL ()
184
+ link = ctx . Issue .HTMLURL ()
191
185
}
192
186
193
187
reviewType := models .ReviewTypeComment
194
- if comment != nil && comment .Review != nil {
195
- reviewType = comment .Review .Type
188
+ if ctx . Comment != nil && ctx . Comment .Review != nil {
189
+ reviewType = ctx . Comment .Review .Type
196
190
}
197
191
198
- fallback = prefix + fallbackMailSubject (issue )
192
+ fallback = prefix + fallbackMailSubject (ctx . Issue )
199
193
200
194
// This is the body of the new issue or comment, not the mail body
201
- body := string (markup .RenderByType (markdown .MarkupName , []byte (content ), issue . Repo .HTMLURL (), issue .Repo .ComposeMetas ()))
195
+ body := string (markup .RenderByType (markdown .MarkupName , []byte (ctx . Content ), ctx . Issue . Repo .HTMLURL (), ctx . Issue .Repo .ComposeMetas ()))
202
196
203
- actType , actName , tplName := actionToTemplate (issue , actionType , commentType , reviewType )
197
+ actType , actName , tplName := actionToTemplate (ctx . Issue , ctx . ActionType , commentType , reviewType )
204
198
205
- if comment != nil && comment .Review != nil {
199
+ if ctx . Comment != nil && ctx . Comment .Review != nil {
206
200
reviewComments = make ([]* models.Comment , 0 , 10 )
207
- for _ , lines := range comment .Review .CodeComments {
201
+ for _ , lines := range ctx . Comment .Review .CodeComments {
208
202
for _ , comments := range lines {
209
203
reviewComments = append (reviewComments , comments ... )
210
204
}
@@ -215,12 +209,12 @@ func composeIssueCommentMessage(issue *models.Issue, doer *models.User, actionTy
215
209
"FallbackSubject" : fallback ,
216
210
"Body" : body ,
217
211
"Link" : link ,
218
- "Issue" : issue ,
219
- "Comment" : comment ,
220
- "IsPull" : issue .IsPull ,
221
- "User" : issue .Repo .MustOwner (),
222
- "Repo" : issue .Repo .FullName (),
223
- "Doer" : doer ,
212
+ "Issue" : ctx . Issue ,
213
+ "Comment" : ctx . Comment ,
214
+ "IsPull" : ctx . Issue .IsPull ,
215
+ "User" : ctx . Issue .Repo .MustOwner (),
216
+ "Repo" : ctx . Issue .Repo .FullName (),
217
+ "Doer" : ctx . Doer ,
224
218
"IsMention" : fromMention ,
225
219
"SubjectPrefix" : prefix ,
226
220
"ActionType" : actType ,
@@ -246,18 +240,23 @@ func composeIssueCommentMessage(issue *models.Issue, doer *models.User, actionTy
246
240
log .Error ("ExecuteTemplate [%s]: %v" , string (tplName )+ "/body" , err )
247
241
}
248
242
249
- msg := NewMessageFrom (tos , doer .DisplayName (), setting .MailService .FromEmail , subject , mailBody .String ())
250
- msg .Info = fmt .Sprintf ("Subject: %s, %s" , subject , info )
251
-
252
- // Set Message-ID on first message so replies know what to reference
253
- if comment == nil {
254
- msg .SetHeader ("Message-ID" , "<" + issue .ReplyReference ()+ ">" )
255
- } else {
256
- msg .SetHeader ("In-Reply-To" , "<" + issue .ReplyReference ()+ ">" )
257
- msg .SetHeader ("References" , "<" + issue .ReplyReference ()+ ">" )
243
+ // Make sure to compose independent messages to avoid leaking user emails
244
+ msgs := make ([]* Message , 0 , len (tos ))
245
+ for _ , to := range tos {
246
+ msg := NewMessageFrom ([]string {to }, ctx .Doer .DisplayName (), setting .MailService .FromEmail , subject , mailBody .String ())
247
+ msg .Info = fmt .Sprintf ("Subject: %s, %s" , subject , info )
248
+
249
+ // Set Message-ID on first message so replies know what to reference
250
+ if ctx .Comment == nil {
251
+ msg .SetHeader ("Message-ID" , "<" + ctx .Issue .ReplyReference ()+ ">" )
252
+ } else {
253
+ msg .SetHeader ("In-Reply-To" , "<" + ctx .Issue .ReplyReference ()+ ">" )
254
+ msg .SetHeader ("References" , "<" + ctx .Issue .ReplyReference ()+ ">" )
255
+ }
256
+ msgs = append (msgs , msg )
258
257
}
259
258
260
- return msg
259
+ return msgs
261
260
}
262
261
263
262
func sanitizeSubject (subject string ) string {
@@ -269,21 +268,15 @@ func sanitizeSubject(subject string) string {
269
268
return mime .QEncoding .Encode ("utf-8" , string (runes ))
270
269
}
271
270
272
- // SendIssueCommentMail composes and sends issue comment emails to target receivers.
273
- func SendIssueCommentMail (issue * models.Issue , doer * models.User , actionType models.ActionType , content string , comment * models.Comment , tos []string ) {
274
- if len (tos ) == 0 {
275
- return
276
- }
277
-
278
- SendAsync (composeIssueCommentMessage (issue , doer , actionType , false , content , comment , tos , "issue comment" ))
279
- }
280
-
281
- // SendIssueMentionMail composes and sends issue mention emails to target receivers.
282
- func SendIssueMentionMail (issue * models.Issue , doer * models.User , actionType models.ActionType , content string , comment * models.Comment , tos []string ) {
283
- if len (tos ) == 0 {
284
- return
285
- }
286
- SendAsync (composeIssueCommentMessage (issue , doer , actionType , true , content , comment , tos , "issue mention" ))
271
+ // SendIssueAssignedMail composes and sends issue assigned email
272
+ func SendIssueAssignedMail (issue * models.Issue , doer * models.User , content string , comment * models.Comment , tos []string ) {
273
+ SendAsyncs (composeIssueCommentMessages (& mailCommentContext {
274
+ Issue : issue ,
275
+ Doer : doer ,
276
+ ActionType : models .ActionType (0 ),
277
+ Content : content ,
278
+ Comment : comment ,
279
+ }, tos , false , "issue assigned" ))
287
280
}
288
281
289
282
// actionToTemplate returns the type and name of the action facing the user
@@ -341,8 +334,3 @@ func actionToTemplate(issue *models.Issue, actionType models.ActionType,
341
334
}
342
335
return
343
336
}
344
-
345
- // SendIssueAssignedMail composes and sends issue assigned email
346
- func SendIssueAssignedMail (issue * models.Issue , doer * models.User , content string , comment * models.Comment , tos []string ) {
347
- SendAsync (composeIssueCommentMessage (issue , doer , models .ActionType (0 ), false , content , comment , tos , "issue assigned" ))
348
- }
0 commit comments