backend.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package backends
  2. import (
  3. "fmt"
  4. "github.com/flashmob/go-guerrilla/envelope"
  5. "github.com/flashmob/go-guerrilla/log"
  6. "strconv"
  7. "strings"
  8. )
  9. var mainlog log.Logger
  10. // Backends process received mail. Depending on the implementation, they can store mail in the database,
  11. // write to a file, check for spam, re-transmit to another server, etc.
  12. // Must return an SMTP message (i.e. "250 OK") and a boolean indicating
  13. // whether the message was processed successfully.
  14. type Backend interface {
  15. // Public methods
  16. Process(*envelope.Envelope) BackendResult
  17. Initialize(BackendConfig) error
  18. Shutdown() error
  19. }
  20. type Worker interface {
  21. // start save mail worker(s)
  22. saveMailWorker(chan *savePayload)
  23. // get the number of workers that will be stared
  24. getNumberOfWorkers() int
  25. // test database settings, permissions, correct paths, etc, before starting workers
  26. testSettings() error
  27. // parse the configuration files
  28. loadConfig(BackendConfig) error
  29. AddConfigLoader(f ConfigLoaderFunc)
  30. AddConfigTester(f ConfigTesterFunc)
  31. AddInitializer(f DecoratorinitializeFunc)
  32. Shutdown() error
  33. Process(*envelope.Envelope) BackendResult
  34. Initialize(BackendConfig) error
  35. SetProcessors(p ...Decorator)
  36. }
  37. type DecoratorCallbacks struct {
  38. loader ConfigLoaderFunc
  39. tester ConfigTesterFunc
  40. initialize DecoratorinitializeFunc
  41. }
  42. type BackendConfig map[string]interface{}
  43. var backends = map[string]Worker{}
  44. type baseConfig interface{}
  45. type saveStatus struct {
  46. err error
  47. hash string
  48. }
  49. type savePayload struct {
  50. mail *envelope.Envelope
  51. //from *envelope.EmailAddress
  52. //recipient *envelope.EmailAddress
  53. savedNotify chan *saveStatus
  54. }
  55. // BackendResult represents a response to an SMTP client after receiving DATA.
  56. // The String method should return an SMTP message ready to send back to the
  57. // client, for example `250 OK: Message received`.
  58. type BackendResult interface {
  59. fmt.Stringer
  60. // Code should return the SMTP code associated with this response, ie. `250`
  61. Code() int
  62. }
  63. // Internal implementation of BackendResult for use by backend implementations.
  64. type backendResult string
  65. func (br backendResult) String() string {
  66. return string(br)
  67. }
  68. // Parses the SMTP code from the first 3 characters of the SMTP message.
  69. // Returns 554 if code cannot be parsed.
  70. func (br backendResult) Code() int {
  71. trimmed := strings.TrimSpace(string(br))
  72. if len(trimmed) < 3 {
  73. return 554
  74. }
  75. code, err := strconv.Atoi(trimmed[:3])
  76. if err != nil {
  77. return 554
  78. }
  79. return code
  80. }
  81. func NewBackendResult(message string) BackendResult {
  82. return backendResult(message)
  83. }