smtp.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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. s.User = username
  40. var user models.User
  41. encodePwd := password.Encode(pwd)
  42. infos := strings.Split(username, "@")
  43. if len(infos) > 1 {
  44. username = infos[0]
  45. }
  46. err := db.Instance.Get(&user, db.WithContext(s.Ctx, "select * from user where account =? and password =?"),
  47. username, encodePwd)
  48. if err != nil && err != sql.ErrNoRows {
  49. log.Errorf("%+v", err)
  50. }
  51. if user.ID > 0 {
  52. s.Ctx.UserAccount = user.Account
  53. s.Ctx.UserID = user.ID
  54. s.Ctx.UserName = user.Name
  55. return nil
  56. }
  57. log.WithContext(s.Ctx).Debugf("登陆错误%s %s", username, pwd)
  58. return errors.New("password error")
  59. }
  60. func (s *Session) Mail(from string, opts *smtp.MailOptions) error {
  61. s.From = from
  62. return nil
  63. }
  64. func (s *Session) Rcpt(to string) error {
  65. s.To = append(s.To, to)
  66. return nil
  67. }
  68. func (s *Session) Reset() {}
  69. func (s *Session) Logout() error {
  70. return nil
  71. }
  72. var instance *smtp.Server
  73. func Start() {
  74. be := &Backend{}
  75. instance = smtp.NewServer(be)
  76. instance.Addr = ":25"
  77. instance.Domain = config.Instance.Domain
  78. instance.ReadTimeout = 10 * time.Second
  79. instance.AuthDisabled = false
  80. instance.WriteTimeout = 10 * time.Second
  81. instance.MaxMessageBytes = 1024 * 1024
  82. instance.MaxRecipients = 50
  83. // force TLS for auth
  84. instance.AllowInsecureAuth = false
  85. // Load the certificate and key
  86. cer, err := tls.LoadX509KeyPair(config.Instance.SSLPublicKeyPath, config.Instance.SSLPrivateKeyPath)
  87. if err != nil {
  88. log.Fatal(err)
  89. return
  90. }
  91. // Configure the TLS support
  92. instance.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cer}}
  93. log.Println("Starting server at", instance.Addr)
  94. if err := instance.ListenAndServe(); err != nil {
  95. log.Fatal(err)
  96. }
  97. }
  98. func Stop() {
  99. if instance != nil {
  100. instance.Close()
  101. }
  102. }