read_content.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package smtp_server
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "github.com/mileusna/spf"
  6. log "github.com/sirupsen/logrus"
  7. "io"
  8. "net"
  9. "net/netip"
  10. "pmail/config"
  11. "pmail/db"
  12. "pmail/dto/parsemail"
  13. "pmail/hooks"
  14. "pmail/services/rule"
  15. "pmail/utils/async"
  16. "strings"
  17. "time"
  18. )
  19. func (s *Session) Data(r io.Reader) error {
  20. emailData, err := io.ReadAll(r)
  21. if err != nil {
  22. log.Error("邮件内容无法读取", err)
  23. return err
  24. }
  25. as1 := async.New(nil)
  26. for _, hook := range hooks.HookList {
  27. if hook == nil {
  28. continue
  29. }
  30. as1.WaitProcess(func(hk any) {
  31. hk.(hooks.EmailHook).ReceiveParseBefore(emailData)
  32. }, hook)
  33. }
  34. as1.Wait()
  35. log.Infof("邮件原始内容: %s", emailData)
  36. var dkimStatus, SPFStatus bool
  37. // DKIM校验
  38. dkimStatus = parsemail.Check(bytes.NewReader(emailData))
  39. email := parsemail.NewEmailFromReader(bytes.NewReader(emailData))
  40. if err != nil {
  41. log.Fatalf("邮件内容解析失败! Error : %v \n", err)
  42. }
  43. SPFStatus = spfCheck(s.RemoteAddress.String(), email.Sender, email.Sender.EmailAddress)
  44. var dkimV, spfV int8
  45. if dkimStatus {
  46. dkimV = 1
  47. }
  48. if SPFStatus {
  49. spfV = 1
  50. }
  51. // 垃圾过滤
  52. if config.Instance.SpamFilterLevel == 1 && !SPFStatus && !dkimStatus {
  53. log.Infoln("垃圾邮件,拒信")
  54. return nil
  55. }
  56. if config.Instance.SpamFilterLevel == 2 && !SPFStatus {
  57. log.Infoln("垃圾邮件,拒信")
  58. return nil
  59. }
  60. as2 := async.New(nil)
  61. for _, hook := range hooks.HookList {
  62. if hook == nil {
  63. continue
  64. }
  65. as2.WaitProcess(func(hk any) {
  66. hk.(hooks.EmailHook).ReceiveParseAfter(email)
  67. }, hook)
  68. }
  69. as2.Wait()
  70. // 执行邮件规则
  71. rs := rule.GetAllRules(nil)
  72. for _, r := range rs {
  73. if rule.MatchRule(nil, r, email) {
  74. rule.DoRule(nil, r, email)
  75. }
  76. }
  77. if email == nil {
  78. return nil
  79. }
  80. sql := "INSERT INTO email (send_date, subject, reply_to, from_name, from_address, `to`, bcc, cc, text, html, sender, attachments,spf_check, dkim_check, create_time,is_read,status,group_id) VALUES (?,?,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
  81. _, err = db.Instance.Exec(sql,
  82. email.Date,
  83. email.Subject,
  84. json2string(email.ReplyTo),
  85. email.From.Name,
  86. email.From.EmailAddress,
  87. json2string(email.To),
  88. json2string(email.Bcc),
  89. json2string(email.Cc),
  90. email.Text,
  91. email.HTML,
  92. json2string(email.Sender),
  93. json2string(email.Attachments),
  94. spfV,
  95. dkimV,
  96. time.Now(),
  97. email.IsRead,
  98. email.Status,
  99. email.GroupId,
  100. )
  101. if err != nil {
  102. log.Println("mysql insert error:", err.Error())
  103. }
  104. return nil
  105. }
  106. func json2string(d any) string {
  107. by, _ := json.Marshal(d)
  108. return string(by)
  109. }
  110. func spfCheck(remoteAddress string, sender *parsemail.User, senderString string) bool {
  111. //spf校验
  112. ipAddress, _ := netip.ParseAddrPort(remoteAddress)
  113. ip := net.ParseIP(ipAddress.Addr().String())
  114. if ip.IsPrivate() {
  115. return true
  116. }
  117. tmp := strings.Split(sender.EmailAddress, "@")
  118. if len(tmp) < 2 {
  119. return false
  120. }
  121. res := spf.CheckHost(ip, tmp[1], senderString, "")
  122. if res == spf.None || res == spf.Pass {
  123. // spf校验通过
  124. return true
  125. }
  126. return false
  127. }