smtp.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package smtp_server
  2. import (
  3. "crypto/tls"
  4. "database/sql"
  5. "github.com/emersion/go-smtp"
  6. log "github.com/sirupsen/logrus"
  7. "net"
  8. "pmail/config"
  9. "pmail/db"
  10. "pmail/models"
  11. "pmail/utils/context"
  12. "pmail/utils/errors"
  13. "pmail/utils/id"
  14. "pmail/utils/password"
  15. "strings"
  16. "time"
  17. )
  18. // The Backend implements SMTP server methods.
  19. type Backend struct{}
  20. func (bkd *Backend) NewSession(conn *smtp.Conn) (smtp.Session, error) {
  21. remoteAddress := conn.Conn().RemoteAddr()
  22. ctx := &context.Context{}
  23. ctx.SetValue(context.LogID, id.GenLogID())
  24. log.WithContext(ctx).Debugf("新SMTP连接")
  25. return &Session{
  26. RemoteAddress: remoteAddress,
  27. Ctx: ctx,
  28. }, nil
  29. }
  30. // A Session is returned after EHLO.
  31. type Session struct {
  32. RemoteAddress net.Addr
  33. User string
  34. From string
  35. To []string
  36. Ctx *context.Context
  37. }
  38. func (s *Session) AuthPlain(username, pwd string) error {
  39. log.WithContext(s.Ctx).Debugf("Auth %s %s", username, pwd)
  40. s.User = username
  41. var user models.User
  42. encodePwd := password.Encode(pwd)
  43. infos := strings.Split(username, "@")
  44. if len(infos) > 1 {
  45. username = infos[0]
  46. }
  47. err := db.Instance.Get(&user, db.WithContext(s.Ctx, "select * from user where account =? and password =?"),
  48. username, encodePwd)
  49. if err != nil && err != sql.ErrNoRows {
  50. log.Errorf("%+v", err)
  51. }
  52. if user.ID > 0 {
  53. s.Ctx.UserAccount = user.Account
  54. s.Ctx.UserID = user.ID
  55. s.Ctx.UserName = user.Name
  56. log.WithContext(s.Ctx).Debugf("Auth Success %+v", user)
  57. return nil
  58. }
  59. log.WithContext(s.Ctx).Debugf("登陆错误%s %s", username, pwd)
  60. return errors.New("password error")
  61. }
  62. func (s *Session) Mail(from string, opts *smtp.MailOptions) error {
  63. log.WithContext(s.Ctx).Debugf("Mail Success %+v %+v", from, opts)
  64. s.From = from
  65. return nil
  66. }
  67. func (s *Session) Rcpt(to string) error {
  68. log.WithContext(s.Ctx).Debugf("Rcpt Success %+v", to)
  69. s.To = append(s.To, to)
  70. return nil
  71. }
  72. func (s *Session) Reset() {}
  73. func (s *Session) Logout() error {
  74. return nil
  75. }
  76. var instance *smtp.Server
  77. var instanceTls *smtp.Server
  78. func StartWithTLS() {
  79. be := &Backend{}
  80. instance = smtp.NewServer(be)
  81. instance.Addr = ":465"
  82. instance.Domain = config.Instance.Domain
  83. instance.ReadTimeout = 10 * time.Second
  84. instance.AuthDisabled = false
  85. instance.WriteTimeout = 10 * time.Second
  86. instance.MaxMessageBytes = 1024 * 1024
  87. instance.MaxRecipients = 50
  88. // force TLS for auth
  89. instance.AllowInsecureAuth = false
  90. // Load the certificate and key
  91. cer, err := tls.LoadX509KeyPair(config.Instance.SSLPublicKeyPath, config.Instance.SSLPrivateKeyPath)
  92. if err != nil {
  93. log.Fatal(err)
  94. return
  95. }
  96. // Configure the TLS support
  97. instance.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cer}}
  98. log.Println("Starting Smtp With SSL Server Port:", instance.Addr)
  99. if err := instance.ListenAndServeTLS(); err != nil {
  100. log.Fatal(err)
  101. }
  102. }
  103. func Start() {
  104. be := &Backend{}
  105. instance = smtp.NewServer(be)
  106. instance.Addr = ":25"
  107. instance.Domain = config.Instance.Domain
  108. instance.ReadTimeout = 10 * time.Second
  109. instance.AuthDisabled = false
  110. instance.WriteTimeout = 10 * time.Second
  111. instance.MaxMessageBytes = 1024 * 1024
  112. instance.MaxRecipients = 50
  113. // force TLS for auth
  114. instance.AllowInsecureAuth = false
  115. // Load the certificate and key
  116. cer, err := tls.LoadX509KeyPair(config.Instance.SSLPublicKeyPath, config.Instance.SSLPrivateKeyPath)
  117. if err != nil {
  118. log.Fatal(err)
  119. return
  120. }
  121. // Configure the TLS support
  122. instance.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cer}}
  123. log.Println("Starting Smtp Server Port:", instance.Addr)
  124. if err := instance.ListenAndServe(); err != nil {
  125. log.Fatal(err)
  126. }
  127. }
  128. func Stop() {
  129. if instance != nil {
  130. instance.Close()
  131. }
  132. if instanceTls != nil {
  133. instanceTls.Close()
  134. }
  135. }