You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
5.9 KiB

  1. // Copyright 2016 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "fmt"
  7. "html/template"
  8. "path"
  9. "gopkg.in/gomail.v2"
  10. "gopkg.in/macaron.v1"
  11. "code.gitea.io/gitea/modules/base"
  12. "code.gitea.io/gitea/modules/log"
  13. "code.gitea.io/gitea/modules/mailer"
  14. "code.gitea.io/gitea/modules/markdown"
  15. "code.gitea.io/gitea/modules/setting"
  16. )
  17. const (
  18. mailAuthActivate base.TplName = "auth/activate"
  19. mailAuthActivateEmail base.TplName = "auth/activate_email"
  20. mailAuthResetPassword base.TplName = "auth/reset_passwd"
  21. mailAuthRegisterNotify base.TplName = "auth/register_notify"
  22. mailIssueComment base.TplName = "issue/comment"
  23. mailIssueMention base.TplName = "issue/mention"
  24. mailNotifyCollaborator base.TplName = "notify/collaborator"
  25. )
  26. type mailRenderInterface interface {
  27. HTMLString(string, interface{}, ...macaron.HTMLOptions) (string, error)
  28. }
  29. var mailRender mailRenderInterface
  30. // InitMailRender initializes the macaron mail renderer
  31. func InitMailRender(dir, appendDir string, funcMap []template.FuncMap) {
  32. opt := &macaron.RenderOptions{
  33. Directory: dir,
  34. AppendDirectories: []string{appendDir},
  35. Funcs: funcMap,
  36. Extensions: []string{".tmpl", ".html"},
  37. }
  38. ts := macaron.NewTemplateSet()
  39. ts.Set(macaron.DEFAULT_TPL_SET_NAME, opt)
  40. mailRender = &macaron.TplRender{
  41. TemplateSet: ts,
  42. Opt: opt,
  43. }
  44. }
  45. // SendTestMail sends a test mail
  46. func SendTestMail(email string) error {
  47. return gomail.Send(&mailer.Sender{}, mailer.NewMessage([]string{email}, "Gogs Test Email!", "Gogs Test Email!").Message)
  48. }
  49. // SendUserMail sends a mail to the user
  50. func SendUserMail(c *macaron.Context, u *User, tpl base.TplName, code, subject, info string) {
  51. data := map[string]interface{}{
  52. "Username": u.DisplayName(),
  53. "ActiveCodeLives": setting.Service.ActiveCodeLives / 60,
  54. "ResetPwdCodeLives": setting.Service.ResetPwdCodeLives / 60,
  55. "Code": code,
  56. }
  57. body, err := mailRender.HTMLString(string(tpl), data)
  58. if err != nil {
  59. log.Error(3, "HTMLString: %v", err)
  60. return
  61. }
  62. msg := mailer.NewMessage([]string{u.Email}, subject, body)
  63. msg.Info = fmt.Sprintf("UID: %d, %s", u.ID, info)
  64. mailer.SendAsync(msg)
  65. }
  66. // SendActivateAccountMail sends an activation mail to the user
  67. func SendActivateAccountMail(c *macaron.Context, u *User) {
  68. SendUserMail(c, u, mailAuthActivate, u.GenerateActivateCode(), c.Tr("mail.activate_account"), "activate account")
  69. }
  70. // SendResetPasswordMail sends a password reset mail to the user
  71. func SendResetPasswordMail(c *macaron.Context, u *User) {
  72. SendUserMail(c, u, mailAuthResetPassword, u.GenerateActivateCode(), c.Tr("mail.reset_password"), "reset password")
  73. }
  74. // SendActivateEmailMail sends confirmation email.
  75. func SendActivateEmailMail(c *macaron.Context, u *User, email *EmailAddress) {
  76. data := map[string]interface{}{
  77. "Username": u.DisplayName(),
  78. "ActiveCodeLives": setting.Service.ActiveCodeLives / 60,
  79. "Code": u.GenerateEmailActivateCode(email.Email),
  80. "Email": email.Email,
  81. }
  82. body, err := mailRender.HTMLString(string(mailAuthActivateEmail), data)
  83. if err != nil {
  84. log.Error(3, "HTMLString: %v", err)
  85. return
  86. }
  87. msg := mailer.NewMessage([]string{email.Email}, c.Tr("mail.activate_email"), body)
  88. msg.Info = fmt.Sprintf("UID: %d, activate email", u.ID)
  89. mailer.SendAsync(msg)
  90. }
  91. // SendRegisterNotifyMail triggers a notify e-mail by admin created a account.
  92. func SendRegisterNotifyMail(c *macaron.Context, u *User) {
  93. data := map[string]interface{}{
  94. "Username": u.DisplayName(),
  95. }
  96. body, err := mailRender.HTMLString(string(mailAuthRegisterNotify), data)
  97. if err != nil {
  98. log.Error(3, "HTMLString: %v", err)
  99. return
  100. }
  101. msg := mailer.NewMessage([]string{u.Email}, c.Tr("mail.register_notify"), body)
  102. msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID)
  103. mailer.SendAsync(msg)
  104. }
  105. // SendCollaboratorMail sends mail notification to new collaborator.
  106. func SendCollaboratorMail(u, doer *User, repo *Repository) {
  107. repoName := path.Join(repo.Owner.Name, repo.Name)
  108. subject := fmt.Sprintf("%s added you to %s", doer.DisplayName(), repoName)
  109. data := map[string]interface{}{
  110. "Subject": subject,
  111. "RepoName": repoName,
  112. "Link": repo.HTMLURL(),
  113. }
  114. body, err := mailRender.HTMLString(string(mailNotifyCollaborator), data)
  115. if err != nil {
  116. log.Error(3, "HTMLString: %v", err)
  117. return
  118. }
  119. msg := mailer.NewMessage([]string{u.Email}, subject, body)
  120. msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.ID)
  121. mailer.SendAsync(msg)
  122. }
  123. func composeTplData(subject, body, link string) map[string]interface{} {
  124. data := make(map[string]interface{}, 10)
  125. data["Subject"] = subject
  126. data["Body"] = body
  127. data["Link"] = link
  128. return data
  129. }
  130. func composeIssueMessage(issue *Issue, doer *User, tplName base.TplName, tos []string, info string) *mailer.Message {
  131. subject := issue.mailSubject()
  132. body := string(markdown.RenderSpecialLink([]byte(issue.Content), issue.Repo.HTMLURL(), issue.Repo.ComposeMetas()))
  133. data := composeTplData(subject, body, issue.HTMLURL())
  134. data["Doer"] = doer
  135. content, err := mailRender.HTMLString(string(tplName), data)
  136. if err != nil {
  137. log.Error(3, "HTMLString (%s): %v", tplName, err)
  138. }
  139. msg := mailer.NewMessageFrom(tos, fmt.Sprintf(`"%s" <%s>`, doer.DisplayName(), setting.MailService.FromEmail), subject, content)
  140. msg.Info = fmt.Sprintf("Subject: %s, %s", subject, info)
  141. return msg
  142. }
  143. // SendIssueCommentMail composes and sends issue comment emails to target receivers.
  144. func SendIssueCommentMail(issue *Issue, doer *User, tos []string) {
  145. if len(tos) == 0 {
  146. return
  147. }
  148. mailer.SendAsync(composeIssueMessage(issue, doer, mailIssueComment, tos, "issue comment"))
  149. }
  150. // SendIssueMentionMail composes and sends issue mention emails to target receivers.
  151. func SendIssueMentionMail(issue *Issue, doer *User, tos []string) {
  152. if len(tos) == 0 {
  153. return
  154. }
  155. mailer.SendAsync(composeIssueMessage(issue, doer, mailIssueMention, tos, "issue mention"))
  156. }