From e7d65cbc6e50d70753f7228c46cbff0cffde7eba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=B5=B5=E6=99=BA=E8=B6=85?= <1012112796@qq.com>
Date: Sun, 23 Aug 2020 23:03:18 +0800
Subject: [PATCH] Add email notify for new release (#12463)

* Add email notify for new release

Signed-off-by: a1012112796 <1012112796@qq.com>
---
 models/release.go                 |  1 +
 modules/notification/mail/mail.go | 13 ++++++
 services/mailer/mail_release.go   | 69 +++++++++++++++++++++++++++++++
 templates/mail/release.tmpl       | 56 +++++++++++++++++++++++++
 4 files changed, 139 insertions(+)
 create mode 100644 services/mailer/mail_release.go
 create mode 100644 templates/mail/release.tmpl

diff --git a/models/release.go b/models/release.go
index 0c76d17f4..f55341b86 100644
--- a/models/release.go
+++ b/models/release.go
@@ -35,6 +35,7 @@ type Release struct {
 	NumCommits       int64
 	NumCommitsBehind int64              `xorm:"-"`
 	Note             string             `xorm:"TEXT"`
+	RenderedNote     string             `xorm:"-"`
 	IsDraft          bool               `xorm:"NOT NULL DEFAULT false"`
 	IsPrerelease     bool               `xorm:"NOT NULL DEFAULT false"`
 	IsTag            bool               `xorm:"NOT NULL DEFAULT false"`
diff --git a/modules/notification/mail/mail.go b/modules/notification/mail/mail.go
index 795c8af2c..9b2c27280 100644
--- a/modules/notification/mail/mail.go
+++ b/modules/notification/mail/mail.go
@@ -145,3 +145,16 @@ func (m *mailNotifier) NotifyPullRequestPushCommits(doer *models.User, pr *model
 
 	m.NotifyCreateIssueComment(doer, comment.Issue.Repo, comment.Issue, comment)
 }
+
+func (m *mailNotifier) NotifyNewRelease(rel *models.Release) {
+	if err := rel.LoadAttributes(); err != nil {
+		log.Error("NotifyNewRelease: %v", err)
+		return
+	}
+
+	if rel.IsDraft || rel.IsPrerelease {
+		return
+	}
+
+	mailer.MailNewRelease(rel)
+}
diff --git a/services/mailer/mail_release.go b/services/mailer/mail_release.go
new file mode 100644
index 000000000..55182f55c
--- /dev/null
+++ b/services/mailer/mail_release.go
@@ -0,0 +1,69 @@
+// Copyright 2020 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 mailer
+
+import (
+	"bytes"
+	"fmt"
+
+	"code.gitea.io/gitea/models"
+	"code.gitea.io/gitea/modules/base"
+	"code.gitea.io/gitea/modules/log"
+	"code.gitea.io/gitea/modules/markup/markdown"
+	"code.gitea.io/gitea/modules/setting"
+)
+
+const (
+	tplNewReleaseMail base.TplName = "release"
+)
+
+// MailNewRelease send new release notify to all all repo watchers.
+func MailNewRelease(rel *models.Release) {
+	watcherIDList, err := models.GetRepoWatchersIDs(rel.RepoID)
+	if err != nil {
+		log.Error("GetRepoWatchersIDs(%d): %v", rel.RepoID, err)
+		return
+	}
+
+	recipients, err := models.GetMaileableUsersByIDs(watcherIDList)
+	if err != nil {
+		log.Error("models.GetMaileableUsersByIDs: %v", err)
+		return
+	}
+
+	tos := make([]string, 0, len(recipients))
+	for _, to := range recipients {
+		if to.ID != rel.PublisherID {
+			tos = append(tos, to.Email)
+		}
+	}
+
+	rel.RenderedNote = markdown.RenderString(rel.Note, rel.Repo.Link(), rel.Repo.ComposeMetas())
+	subject := fmt.Sprintf("%s in %s released", rel.TagName, rel.Repo.FullName())
+
+	mailMeta := map[string]interface{}{
+		"Release": rel,
+		"Subject": subject,
+	}
+
+	var mailBody bytes.Buffer
+
+	if err = bodyTemplates.ExecuteTemplate(&mailBody, string(tplNewReleaseMail), mailMeta); err != nil {
+		log.Error("ExecuteTemplate [%s]: %v", string(tplNewReleaseMail)+"/body", err)
+		return
+	}
+
+	msgs := make([]*Message, 0, len(recipients))
+	publisherName := rel.Publisher.DisplayName()
+	relURL := "<" + rel.HTMLURL() + ">"
+	for _, to := range tos {
+		msg := NewMessageFrom([]string{to}, publisherName, setting.MailService.FromEmail, subject, mailBody.String())
+		msg.Info = subject
+		msg.SetHeader("Message-ID", relURL)
+		msgs = append(msgs, msg)
+	}
+
+	SendAsyncs(msgs)
+}
diff --git a/templates/mail/release.tmpl b/templates/mail/release.tmpl
new file mode 100644
index 000000000..bb0eb17a5
--- /dev/null
+++ b/templates/mail/release.tmpl
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	<title>{{.Subject}}</title>
+
+	<style>
+		blockquote { padding-left: 1em; margin: 1em 0; border-left: 1px solid grey; color: #777}
+		.footer { font-size:small; color:#666;}
+	</style>
+
+</head>
+
+<body>
+	<p><b>@{{.Release.Publisher.Name}}</b> released <a href="{{.Release.HTMLURL}}">{{.Release.TagName}}</a> 
+	  in <a href="{{AppUrl}}{{.Release.Repo.OwnerName}}/{{.Release.Repo.Name}}">{{.Release.Repo.FullName}} </p>
+	<h4>Title: {{.Release.Title}}</h4>
+	<p>
+		Note: <br>
+		{{- if eq .Release.RenderedNote ""}}
+		{{else}}
+			{{.Release.RenderedNote | Str2html}}
+		{{end -}}
+	</p>
+	<br><br>
+	<p>
+		--- 
+		<br>
+		Downloads:
+		<ul>
+			<li>
+				<a href="{{AppUrl}}{{.Release.Repo.OwnerName}}/{{.Release.Repo.Name}}/archive/{{.Release.TagName | EscapePound}}.zip" rel="nofollow"><strong> Source Code (ZIP)</strong></a>
+			</li>
+			<li>
+				<a href="{{AppUrl}}{{.Release.Repo.OwnerName}}/{{.Release.Repo.Name}}/archive/{{.Release.TagName | EscapePound}}.tar.gz"><strong> Source Code (TAR.GZ)</strong></a>
+			</li>
+			{{if .Release.Attachments}}
+				{{range .Release.Attachments}}
+					<li>
+						<a target="_blank" rel="noopener noreferrer" href="{{.DownloadURL}}">
+							<strong>{{.Name}} ({{.Size | FileSize}})</strong>
+						</a>
+					</li>
+				{{end}}
+			{{end}}
+		</ul>
+	</p>
+	<div class="footer">
+	<p>
+		---
+		<br>
+		<a href="{{.Release.HTMLURL}}">View it on {{AppName}}</a>.
+	</p>
+	</div>
+</body>
+</html>