smtp.go 4.4 KB

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