2016-07-15 19:36:39 +03:00
// Copyright 2016 The Gogs 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 (
2016-12-06 20:58:31 +03:00
"bytes"
2016-07-15 19:36:39 +03:00
"fmt"
"html/template"
"path"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/mailer"
2017-09-16 20:17:57 +03:00
"code.gitea.io/gitea/modules/markup"
2017-09-21 08:20:14 +03:00
"code.gitea.io/gitea/modules/markup/markdown"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/setting"
2016-12-06 20:58:31 +03:00
"gopkg.in/gomail.v2"
2016-07-15 19:36:39 +03:00
)
const (
2016-11-25 11:11:12 +03:00
mailAuthActivate base . TplName = "auth/activate"
mailAuthActivateEmail base . TplName = "auth/activate_email"
mailAuthResetPassword base . TplName = "auth/reset_passwd"
mailAuthRegisterNotify base . TplName = "auth/register_notify"
2016-07-15 19:36:39 +03:00
2016-11-25 11:11:12 +03:00
mailIssueComment base . TplName = "issue/comment"
mailIssueMention base . TplName = "issue/mention"
2016-07-15 19:36:39 +03:00
2016-11-25 11:11:12 +03:00
mailNotifyCollaborator base . TplName = "notify/collaborator"
2016-07-15 19:36:39 +03:00
)
2016-12-06 20:58:31 +03:00
var templates * template . Template
2016-07-15 19:36:39 +03:00
2019-05-14 16:52:18 +03:00
// InitMailRender initializes the mail renderer
2016-12-06 20:58:31 +03:00
func InitMailRender ( tmpls * template . Template ) {
templates = tmpls
2016-07-15 19:36:39 +03:00
}
2016-11-25 11:11:12 +03:00
// SendTestMail sends a test mail
2016-07-15 19:36:39 +03:00
func SendTestMail ( email string ) error {
2016-12-25 16:55:22 +03:00
return gomail . Send ( mailer . Sender , mailer . NewMessage ( [ ] string { email } , "Gitea Test Email!" , "Gitea Test Email!" ) . Message )
2016-07-15 19:36:39 +03:00
}
2016-11-25 11:11:12 +03:00
// SendUserMail sends a mail to the user
2019-05-14 01:53:54 +03:00
func SendUserMail ( language string , u * User , tpl base . TplName , code , subject , info string ) {
2016-07-15 19:36:39 +03:00
data := map [ string ] interface { } {
2019-04-04 10:52:48 +03:00
"DisplayName" : u . DisplayName ( ) ,
2019-05-14 01:53:54 +03:00
"ActiveCodeLives" : base . MinutesToFriendly ( setting . Service . ActiveCodeLives , language ) ,
"ResetPwdCodeLives" : base . MinutesToFriendly ( setting . Service . ResetPwdCodeLives , language ) ,
2016-07-15 19:36:39 +03:00
"Code" : code ,
}
2016-12-06 20:58:31 +03:00
var content bytes . Buffer
if err := templates . ExecuteTemplate ( & content , string ( tpl ) , data ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Template: %v" , err )
2016-07-15 19:36:39 +03:00
return
}
2016-12-06 20:58:31 +03:00
msg := mailer . NewMessage ( [ ] string { u . Email } , subject , content . String ( ) )
2016-07-23 20:08:22 +03:00
msg . Info = fmt . Sprintf ( "UID: %d, %s" , u . ID , info )
2016-07-15 19:36:39 +03:00
mailer . SendAsync ( msg )
}
2019-05-14 01:53:54 +03:00
// Locale represents an interface to translation
type Locale interface {
Language ( ) string
Tr ( string , ... interface { } ) string
}
2017-05-14 05:38:30 +03:00
// SendActivateAccountMail sends an activation mail to the user (new user registration)
2019-05-14 01:53:54 +03:00
func SendActivateAccountMail ( locale Locale , u * User ) {
SendUserMail ( locale . Language ( ) , u , mailAuthActivate , u . GenerateActivateCode ( ) , locale . Tr ( "mail.activate_account" ) , "activate account" )
2016-07-15 19:36:39 +03:00
}
2016-11-25 11:11:12 +03:00
// SendResetPasswordMail sends a password reset mail to the user
2019-05-14 01:53:54 +03:00
func SendResetPasswordMail ( locale Locale , u * User ) {
SendUserMail ( locale . Language ( ) , u , mailAuthResetPassword , u . GenerateActivateCode ( ) , locale . Tr ( "mail.reset_password" ) , "recover account" )
2016-07-15 19:36:39 +03:00
}
2017-05-14 05:38:30 +03:00
// SendActivateEmailMail sends confirmation email to confirm new email address
2019-05-14 01:53:54 +03:00
func SendActivateEmailMail ( locale Locale , u * User , email * EmailAddress ) {
2016-07-15 19:36:39 +03:00
data := map [ string ] interface { } {
2019-04-04 10:52:48 +03:00
"DisplayName" : u . DisplayName ( ) ,
2019-05-14 01:53:54 +03:00
"ActiveCodeLives" : base . MinutesToFriendly ( setting . Service . ActiveCodeLives , locale . Language ( ) ) ,
2016-07-15 19:36:39 +03:00
"Code" : u . GenerateEmailActivateCode ( email . Email ) ,
"Email" : email . Email ,
}
2016-12-06 20:58:31 +03:00
var content bytes . Buffer
if err := templates . ExecuteTemplate ( & content , string ( mailAuthActivateEmail ) , data ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Template: %v" , err )
2016-07-15 19:36:39 +03:00
return
}
2019-05-14 01:53:54 +03:00
msg := mailer . NewMessage ( [ ] string { email . Email } , locale . Tr ( "mail.activate_email" ) , content . String ( ) )
2016-07-23 20:08:22 +03:00
msg . Info = fmt . Sprintf ( "UID: %d, activate email" , u . ID )
2016-07-15 19:36:39 +03:00
mailer . SendAsync ( msg )
}
// SendRegisterNotifyMail triggers a notify e-mail by admin created a account.
2019-05-14 01:53:54 +03:00
func SendRegisterNotifyMail ( locale Locale , u * User ) {
2016-07-15 19:36:39 +03:00
data := map [ string ] interface { } {
2019-04-04 10:52:48 +03:00
"DisplayName" : u . DisplayName ( ) ,
"Username" : u . Name ,
2016-07-15 19:36:39 +03:00
}
2016-12-06 20:58:31 +03:00
var content bytes . Buffer
if err := templates . ExecuteTemplate ( & content , string ( mailAuthRegisterNotify ) , data ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Template: %v" , err )
2016-07-15 19:36:39 +03:00
return
}
2019-05-14 01:53:54 +03:00
msg := mailer . NewMessage ( [ ] string { u . Email } , locale . Tr ( "mail.register_notify" ) , content . String ( ) )
2016-07-23 20:08:22 +03:00
msg . Info = fmt . Sprintf ( "UID: %d, registration notify" , u . ID )
2016-07-15 19:36:39 +03:00
mailer . SendAsync ( msg )
}
// SendCollaboratorMail sends mail notification to new collaborator.
func SendCollaboratorMail ( u , doer * User , repo * Repository ) {
repoName := path . Join ( repo . Owner . Name , repo . Name )
subject := fmt . Sprintf ( "%s added you to %s" , doer . DisplayName ( ) , repoName )
data := map [ string ] interface { } {
"Subject" : subject ,
"RepoName" : repoName ,
2016-08-16 20:19:09 +03:00
"Link" : repo . HTMLURL ( ) ,
2016-07-15 19:36:39 +03:00
}
2016-12-06 20:58:31 +03:00
var content bytes . Buffer
if err := templates . ExecuteTemplate ( & content , string ( mailNotifyCollaborator ) , data ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Template: %v" , err )
2016-07-15 19:36:39 +03:00
return
}
2016-12-06 20:58:31 +03:00
msg := mailer . NewMessage ( [ ] string { u . Email } , subject , content . String ( ) )
2016-07-23 20:08:22 +03:00
msg . Info = fmt . Sprintf ( "UID: %d, add collaborator" , u . ID )
2016-07-15 19:36:39 +03:00
mailer . SendAsync ( msg )
}
func composeTplData ( subject , body , link string ) map [ string ] interface { } {
data := make ( map [ string ] interface { } , 10 )
data [ "Subject" ] = subject
data [ "Body" ] = body
data [ "Link" ] = link
return data
}
2017-11-03 12:23:17 +03:00
func composeIssueCommentMessage ( issue * Issue , doer * User , content string , comment * Comment , tplName base . TplName , tos [ ] string , info string ) * mailer . Message {
2019-07-17 22:02:42 +03:00
var subject string
if comment != nil {
subject = "Re: " + issue . mailSubject ( )
} else {
subject = issue . mailSubject ( )
}
2019-06-12 22:41:28 +03:00
err := issue . LoadRepo ( )
if err != nil {
log . Error ( "LoadRepo: %v" , err )
}
2017-11-03 12:23:17 +03:00
body := string ( markup . RenderByType ( markdown . MarkupName , [ ] byte ( content ) , issue . Repo . HTMLURL ( ) , issue . Repo . ComposeMetas ( ) ) )
2017-05-25 05:38:56 +03:00
2019-06-12 22:41:28 +03:00
var data = make ( map [ string ] interface { } , 10 )
2017-05-25 05:38:56 +03:00
if comment != nil {
data = composeTplData ( subject , body , issue . HTMLURL ( ) + "#" + comment . HashTag ( ) )
} else {
data = composeTplData ( subject , body , issue . HTMLURL ( ) )
}
2016-07-15 19:36:39 +03:00
data [ "Doer" ] = doer
2016-12-06 20:58:31 +03:00
2017-11-03 12:23:17 +03:00
var mailBody bytes . Buffer
2016-12-06 20:58:31 +03:00
2017-11-03 12:23:17 +03:00
if err := templates . ExecuteTemplate ( & mailBody , string ( tplName ) , data ) ; err != nil {
2019-04-02 10:48:31 +03:00
log . Error ( "Template: %v" , err )
2016-07-15 19:36:39 +03:00
}
2016-12-06 20:58:31 +03:00
2017-11-03 12:23:17 +03:00
msg := mailer . NewMessageFrom ( tos , doer . DisplayName ( ) , setting . MailService . FromEmail , subject , mailBody . String ( ) )
2016-07-15 19:36:39 +03:00
msg . Info = fmt . Sprintf ( "Subject: %s, %s" , subject , info )
2019-07-17 22:02:42 +03:00
// 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 ( ) + ">" )
}
2016-07-15 19:36:39 +03:00
return msg
}
// SendIssueCommentMail composes and sends issue comment emails to target receivers.
2017-11-03 12:23:17 +03:00
func SendIssueCommentMail ( issue * Issue , doer * User , content string , comment * Comment , tos [ ] string ) {
2016-07-15 19:36:39 +03:00
if len ( tos ) == 0 {
return
}
2017-11-03 12:23:17 +03:00
mailer . SendAsync ( composeIssueCommentMessage ( issue , doer , content , comment , mailIssueComment , tos , "issue comment" ) )
2016-07-15 19:36:39 +03:00
}
// SendIssueMentionMail composes and sends issue mention emails to target receivers.
2017-11-03 12:23:17 +03:00
func SendIssueMentionMail ( issue * Issue , doer * User , content string , comment * Comment , tos [ ] string ) {
2016-07-15 19:36:39 +03:00
if len ( tos ) == 0 {
return
}
2017-11-03 12:23:17 +03:00
mailer . SendAsync ( composeIssueCommentMessage ( issue , doer , content , comment , mailIssueMention , tos , "issue mention" ) )
2016-07-15 19:36:39 +03:00
}