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.

mailer.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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. if len(msg.To) == 0 {
  64. return 0, fmt.Errorf("empty receive emails")
  65. } else if len(msg.Body) == 0 {
  66. return 0, fmt.Errorf("empty email body")
  67. }
  68. auth := smtp.PlainAuth("", base.MailService.User, base.MailService.Passwd, host[0])
  69. if msg.Massive {
  70. // send mail to multiple emails one by one
  71. num := 0
  72. for _, to := range msg.To {
  73. body := []byte("To: " + to + "\r\n" + content)
  74. err := smtp.SendMail(base.MailService.Host, auth, msg.From, []string{to}, body)
  75. if err != nil {
  76. return num, err
  77. }
  78. num++
  79. }
  80. return num, nil
  81. } else {
  82. body := []byte("To: " + strings.Join(msg.To, ";") + "\r\n" + content)
  83. // send to multiple emails in one message
  84. err := smtp.SendMail(base.MailService.Host, auth, msg.From, msg.To, body)
  85. if err != nil {
  86. return 0, err
  87. } else {
  88. return 1, nil
  89. }
  90. }
  91. }
  92. // Async Send mail message
  93. func SendAsync(msg *Message) {
  94. go func() {
  95. mailQueue <- msg
  96. }()
  97. }
  98. // Create html mail message
  99. func NewHtmlMessage(To []string, From, Subject, Body string) Message {
  100. return Message{
  101. To: To,
  102. From: From,
  103. Subject: Subject,
  104. Body: Body,
  105. Type: "html",
  106. }
  107. }