diff --git a/models/issue.go b/models/issue.go index 63074cd40..bde5758b0 100644 --- a/models/issue.go +++ b/models/issue.go @@ -472,6 +472,18 @@ func (issue *Issue) sendLabelUpdatedWebhook(doer *User) { } } +// ReplyReference returns tokenized address to use for email reply headers +func (issue *Issue) ReplyReference() string { + var path string + if issue.IsPull { + path = "pulls" + } else { + path = "issues" + } + + return fmt.Sprintf("%s/%s/%d@%s", issue.Repo.FullName(), path, issue.Index, setting.Domain) +} + func (issue *Issue) addLabel(e *xorm.Session, label *Label, doer *User) error { return newIssueLabel(e, issue, label, doer) } diff --git a/models/mail.go b/models/mail.go index 2bb07607a..cd4e4bc80 100644 --- a/models/mail.go +++ b/models/mail.go @@ -156,7 +156,13 @@ func composeTplData(subject, body, link string) map[string]interface{} { } func composeIssueCommentMessage(issue *Issue, doer *User, content string, comment *Comment, tplName base.TplName, tos []string, info string) *mailer.Message { - subject := issue.mailSubject() + var subject string + if comment != nil { + subject = "Re: " + issue.mailSubject() + } else { + subject = issue.mailSubject() + } + err := issue.LoadRepo() if err != nil { log.Error("LoadRepo: %v", err) @@ -179,6 +185,15 @@ func composeIssueCommentMessage(issue *Issue, doer *User, content string, commen msg := mailer.NewMessageFrom(tos, doer.DisplayName(), setting.MailService.FromEmail, subject, mailBody.String()) msg.Info = fmt.Sprintf("Subject: %s, %s", subject, info) + + // Set Message-ID on first message so replies know what to reference + if comment == nil { + msg.SetHeader("Message-ID", "<"+issue.ReplyReference()+">") + } else { + msg.SetHeader("In-Reply-To", "<"+issue.ReplyReference()+">") + msg.SetHeader("References", "<"+issue.ReplyReference()+">") + } + return msg } diff --git a/models/mail_test.go b/models/mail_test.go new file mode 100644 index 000000000..51c52427f --- /dev/null +++ b/models/mail_test.go @@ -0,0 +1,87 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +import ( + "html/template" + "testing" + + "code.gitea.io/gitea/modules/setting" + + "github.com/stretchr/testify/assert" +) + +const tmpl = ` + + +
+ +{{.Body}}
+
+ ---
+
+ View it on Gitea.
+