backend.go 2.7 KB

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