gitea源码

message.go 3.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Copyright 2024 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package sender
  4. import (
  5. "fmt"
  6. "hash/fnv"
  7. "net/mail"
  8. "strings"
  9. "time"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/setting"
  12. "code.gitea.io/gitea/modules/util"
  13. "github.com/jaytaylor/html2text"
  14. gomail "github.com/wneessen/go-mail"
  15. )
  16. // Message mail body and log info
  17. type Message struct {
  18. Info string // Message information for log purpose.
  19. FromAddress string
  20. FromDisplayName string
  21. To string // Use only one recipient to prevent leaking of addresses
  22. ReplyTo string
  23. Subject string
  24. Date time.Time
  25. Body string
  26. Headers map[string][]string
  27. }
  28. // ToMessage converts a Message to gomail.Message
  29. func (m *Message) ToMessage() *gomail.Msg {
  30. msg := gomail.NewMsg()
  31. addr := mail.Address{Name: m.FromDisplayName, Address: m.FromAddress}
  32. _ = msg.SetAddrHeader("From", addr.String())
  33. _ = msg.SetAddrHeader("To", m.To)
  34. if m.ReplyTo != "" {
  35. msg.SetGenHeader("Reply-To", m.ReplyTo)
  36. }
  37. for header := range m.Headers {
  38. msg.SetGenHeader(gomail.Header(header), m.Headers[header]...)
  39. }
  40. if setting.MailService.SubjectPrefix != "" {
  41. msg.SetGenHeader("Subject", setting.MailService.SubjectPrefix+" "+m.Subject)
  42. } else {
  43. msg.SetGenHeader("Subject", m.Subject)
  44. }
  45. msg.SetDateWithValue(m.Date)
  46. msg.SetGenHeader("X-Auto-Response-Suppress", "All")
  47. plainBody, err := html2text.FromString(m.Body)
  48. if err != nil || setting.MailService.SendAsPlainText {
  49. if strings.Contains(util.TruncateRunes(m.Body, 100), "<html>") {
  50. log.Warn("Mail contains HTML but configured to send as plain text.")
  51. }
  52. msg.SetBodyString("text/plain", plainBody)
  53. } else {
  54. msg.SetBodyString("text/plain", plainBody)
  55. msg.AddAlternativeString("text/html", m.Body)
  56. }
  57. if len(msg.GetGenHeader("Message-ID")) == 0 {
  58. msg.SetGenHeader("Message-ID", m.generateAutoMessageID())
  59. }
  60. for k, v := range setting.MailService.OverrideHeader {
  61. if len(msg.GetGenHeader(gomail.Header(k))) != 0 {
  62. log.Debug("Mailer override header '%s' as per config", k)
  63. }
  64. msg.SetGenHeader(gomail.Header(k), v...)
  65. }
  66. return msg
  67. }
  68. // SetHeader adds additional headers to a message
  69. func (m *Message) SetHeader(field string, value ...string) {
  70. m.Headers[field] = value
  71. }
  72. func (m *Message) generateAutoMessageID() string {
  73. dateMs := m.Date.UnixNano() / 1e6
  74. h := fnv.New64()
  75. if len(m.To) > 0 {
  76. _, _ = h.Write([]byte(m.To))
  77. }
  78. _, _ = h.Write([]byte(m.Subject))
  79. _, _ = h.Write([]byte(m.Body))
  80. return fmt.Sprintf("<autogen-%d-%016x@%s>", dateMs, h.Sum64(), setting.Domain)
  81. }
  82. // NewMessageFrom creates new mail message object with custom From header.
  83. func NewMessageFrom(to, fromDisplayName, fromAddress, subject, body string) *Message {
  84. log.Trace("NewMessageFrom (body):\n%s", body)
  85. return &Message{
  86. FromAddress: fromAddress,
  87. FromDisplayName: fromDisplayName,
  88. To: to,
  89. Subject: subject,
  90. Date: time.Now(),
  91. Body: body,
  92. Headers: map[string][]string{},
  93. }
  94. }
  95. // NewMessage creates new mail message object with default From header.
  96. func NewMessage(to, subject, body string) *Message {
  97. return NewMessageFrom(to, setting.MailService.FromName, setting.MailService.FromEmail, subject, body)
  98. }