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.

126 lines
2.7 KiB

10 years ago
  1. // Copyright 2014 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 mailer
  5. import (
  6. "fmt"
  7. "net/smtp"
  8. "strings"
  9. "github.com/gogits/gogs/modules/base"
  10. "github.com/gogits/gogs/modules/log"
  11. )
  12. type Message struct {
  13. To []string
  14. From string
  15. Subject string
  16. Body string
  17. User string
  18. Type string
  19. Massive bool
  20. Info string
  21. }
  22. // create mail content
  23. func (m Message) Content() string {
  24. // set mail type
  25. contentType := "text/plain; charset=UTF-8"
  26. if m.Type == "html" {
  27. contentType = "text/html; charset=UTF-8"
  28. }
  29. // create mail content
  30. content := "From: " + m.From + "<" + m.User +
  31. ">\r\nSubject: " + m.Subject + "\r\nContent-Type: " + contentType + "\r\n\r\n" + m.Body
  32. return content
  33. }
  34. var mailQueue chan *Message
  35. func NewMailerContext() {
  36. mailQueue = make(chan *Message, base.Cfg.MustInt("mailer", "SEND_BUFFER_LEN", 10))
  37. go processMailQueue()
  38. }
  39. func processMailQueue() {
  40. for {
  41. select {
  42. case msg := <-mailQueue:
  43. num, err := Send(msg)
  44. tos := strings.Join(msg.To, "; ")
  45. info := ""
  46. if err != nil {
  47. if len(msg.Info) > 0 {
  48. info = ", info: " + msg.Info
  49. }
  50. log.Error(fmt.Sprintf("Async sent email %d succeed, not send emails: %s%s err: %s", num, tos, info, err))
  51. } else {
  52. log.Trace(fmt.Sprintf("Async sent email %d succeed, sent emails: %s%s", num, tos, info))
  53. }
  54. }
  55. }
  56. }
  57. // Direct Send mail message
  58. func Send(msg *Message) (int, error) {
  59. log.Trace("Sending mails to: %s", strings.Join(msg.To, "; "))
  60. host := strings.Split(base.MailService.Host, ":")
  61. // get message body
  62. content := msg.Content()
  63. auth := smtp.PlainAuth("", base.MailService.User, base.MailService.Passwd, host[0])
  64. if len(msg.To) == 0 {
  65. return 0, fmt.Errorf("empty receive emails")
  66. }
  67. if len(msg.Body) == 0 {
  68. return 0, fmt.Errorf("empty email body")
  69. }
  70. if msg.Massive {
  71. // send mail to multiple emails one by one
  72. num := 0
  73. for _, to := range msg.To {
  74. body := []byte("To: " + to + "\r\n" + content)
  75. err := smtp.SendMail(base.MailService.Host, auth, msg.From, []string{to}, body)
  76. if err != nil {
  77. return num, err
  78. }
  79. num++
  80. }
  81. return num, nil
  82. } else {
  83. body := []byte("To: " + strings.Join(msg.To, ";") + "\r\n" + content)
  84. // send to multiple emails in one message
  85. err := smtp.SendMail(base.MailService.Host, auth, msg.From, msg.To, body)
  86. if err != nil {
  87. return 0, err
  88. } else {
  89. return 1, nil
  90. }
  91. }
  92. }
  93. // Async Send mail message
  94. func SendAsync(msg *Message) {
  95. go func() {
  96. mailQueue <- msg
  97. }()
  98. }
  99. // Create html mail message
  100. func NewHtmlMessage(To []string, From, Subject, Body string) Message {
  101. return Message{
  102. To: To,
  103. From: From,
  104. Subject: Subject,
  105. Body: Body,
  106. Type: "html",
  107. }
  108. }