mailgun-tracking 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/mailgun/tracking/templates/mailgun_tracking.rb.erb +1 -1
  3. data/lib/mailgun-tracking.rb +3 -0
  4. data/lib/mailgun/tracking.rb +65 -33
  5. data/lib/mailgun/tracking/auth.rb +52 -0
  6. data/lib/mailgun/tracking/configuration.rb +5 -9
  7. data/lib/mailgun/tracking/fanout.rb +18 -0
  8. data/lib/mailgun/tracking/middleware.rb +10 -47
  9. data/lib/mailgun/tracking/railtie.rb +2 -2
  10. data/lib/mailgun/tracking/version.rb +8 -7
  11. data/spec/dummy/logs/test.log +77 -0
  12. data/spec/dummy/rails/logs/test.log +19 -11
  13. data/spec/mailgun/tracking/auth_spec.rb +31 -0
  14. data/spec/mailgun/tracking/middleware_spec.rb +43 -51
  15. data/spec/mailgun/tracking_spec.rb +11 -4
  16. data/spec/support/shared_examples/integration/acts_as_rack.rb +6 -4
  17. metadata +18 -53
  18. data/lib/mailgun/tracking/exceptions.rb +0 -11
  19. data/lib/mailgun/tracking/listener.rb +0 -55
  20. data/lib/mailgun/tracking/notifier.rb +0 -61
  21. data/lib/mailgun/tracking/payload.rb +0 -96
  22. data/lib/mailgun/tracking/request.rb +0 -47
  23. data/lib/mailgun/tracking/signature.rb +0 -48
  24. data/lib/mailgun/tracking/subscriber.rb +0 -26
  25. data/lib/mailgun/tracking/subscriber/all_messages.rb +0 -37
  26. data/lib/mailgun/tracking/subscriber/evented.rb +0 -40
  27. data/lib/mailgun/tracking/util.rb +0 -67
  28. data/spec/mailgun/tracking/listener_spec.rb +0 -48
  29. data/spec/mailgun/tracking/notifier_spec.rb +0 -66
  30. data/spec/mailgun/tracking/payload_spec.rb +0 -73
  31. data/spec/mailgun/tracking/request_spec.rb +0 -63
  32. data/spec/mailgun/tracking/signature_spec.rb +0 -65
  33. data/spec/mailgun/tracking/subscriber/all_messages_spec.rb +0 -13
  34. data/spec/mailgun/tracking/subscriber/evented_spec.rb +0 -14
  35. data/spec/mailgun/tracking/subscriber_spec.rb +0 -15
  36. data/spec/mailgun/tracking/util_spec.rb +0 -155
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cffbc8bee4968f3230841a2a75da150ef6d17bb2e4d860d05897aef61e55f2e1
4
- data.tar.gz: be71a2d5a143a49d4ada8d050ffd402e09917e31cacc83da954654adfeae358d
3
+ metadata.gz: 6b812299fdcd198f08dd868a8b7c19f862637d68cad9be5af788867b98f53522
4
+ data.tar.gz: 705758e31e1ce4e8527edba0c2d172627298aacf0d156363f5ccb6ed02466556
5
5
  SHA512:
6
- metadata.gz: 4451ebb90204a5a887ad09afaac2187b0e86591e880a1bf944a7c671056c93999a8d6ec89920c38928a230e0b86a161eb472f0d57e320085865f12f33dcde843
7
- data.tar.gz: efda62e3aa07d4fbe150dbfb48d2f2cbaa6204b49de9f0bb7278e473723ed85515dc56cfe84b503bf9c94b18a70cdfec5e94642ed5b927942381852babceb37e
6
+ metadata.gz: 84e5e69c832f3c3f19f775c47d35d675d2a150e5564e41899bc8a7e79858e25c70fabd27e4c20e49543c65a4c423e0cd2406ca70fafefd898b6bcbb5c29bf08e
7
+ data.tar.gz: a341aec22ff80fa7c0edb22706aa4f72631155e4fe8606cd0493043aed9c72f5830655c82373d5976064e159f91b96ac5cd6de1c5399b0f3ef6813b391481b2e
@@ -6,7 +6,7 @@ Mailgun::Tracking.configure do |config|
6
6
  config.api_key = ENV['MAILGUN_API_KEY']
7
7
  <% end -%>
8
8
 
9
- # Mailgun Webhook API endpoint. Default is '/mailgun'.
9
+ # Mailgun callback URL. Default is '/mailgun-tracking'.
10
10
  <% if endpoint -%>
11
11
  config.endpoint = <%= endpoint %>
12
12
  <% else -%>
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mailgun/tracking'
@@ -1,66 +1,98 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'tracking/configuration'
4
- require_relative 'tracking/exceptions'
5
- require_relative 'tracking/listener'
6
- require_relative 'tracking/middleware'
7
- require_relative 'tracking/notifier'
8
- require_relative 'tracking/payload'
9
- require_relative 'tracking/signature'
10
- require_relative 'tracking/subscriber'
11
- require_relative 'tracking/util'
12
- require_relative 'tracking/version'
13
- require_relative 'tracking/railtie' if defined?(Rails)
14
- require_relative 'tracking/request'
3
+ require 'mailgun/tracking/configuration'
4
+ require 'mailgun/tracking/middleware'
5
+ require 'mailgun/tracking/version'
6
+ require 'mailgun/tracking/railtie' if defined?(::Rails)
7
+ require 'mailgun/tracking/fanout'
15
8
 
16
- # Module for interacting with the Mailgun.
17
9
  module Mailgun
18
- # Namespace for classes and modules that handle Mailgun Webhooks.
10
+ # The namespace for classes and modules that handle Mailgun webhooks.
19
11
  module Tracking
20
12
  module_function
21
13
 
22
- # Default way to setup Mailgun Tracking.
14
+ # The default way to set up Mailgun Tracking.
15
+ #
16
+ # @yield [self] block yields itself.
23
17
  #
24
18
  # @example
25
19
  # Mailgun::Tracking.configure do |config|
26
20
  # config.api_key = ENV['MAILGUN_API_KEY']
21
+ #
27
22
  # config.endpoint = '/mailgun-tracking'
28
23
  #
29
- # config.notifier.subscribe :delivered do |payload|
24
+ # config.on 'delivered' do |payload|
30
25
  # # Do something with the incoming data.
31
26
  # end
32
27
  #
33
- # config.notifier.subscribe :bounced, Bounced.new
28
+ # # The object should respond to #call
29
+ # config.on 'bounced', Bounced.new
34
30
  #
35
- # config.notifier.all do |payload|
36
- # # Handle all event types.
31
+ # config.all do |payload|
32
+ # # Do something with the incoming data.
37
33
  # end
38
34
  # end
39
- #
40
- # @return [void]
41
35
  def configure
42
36
  yield(self)
43
37
  end
44
38
 
45
- # A Notifier instance.
39
+ # Subscribe to an event.
46
40
  #
47
- # @return [Mailgun::Tracking::Notifier]
48
- def notifier
49
- @notifier ||= Notifier.new
41
+ # @param event [Symbol, String] the event identifier.
42
+ # @param callable [#call] the event handler.
43
+ #
44
+ # @example
45
+ # Mailgun::Tracking.configure do |config|
46
+ # config.on 'delivered' do |payload|
47
+ # # Do something with the incoming data.
48
+ # end
49
+ #
50
+ # # The object should respond to #call
51
+ # config.on 'bounced', Bounced.new
52
+ # end
53
+ def on(event, callable = nil, &block)
54
+ ::Mailgun::Tracking::Fanout.on(
55
+ event.to_s.dup.freeze,
56
+ callable || block
57
+ )
50
58
  end
51
59
 
52
- # Delegate other missing methods to configuration.
60
+ # Subscribe to all events.
61
+ #
62
+ # @param callable [#call] the event handler.
63
+ #
64
+ # @example
65
+ # Mailgun::Tracking.configure do |config|
66
+ # config.all do |payload|
67
+ # # Do something with the incoming data.
68
+ # end
69
+ #
70
+ # # The object should respond to #call
71
+ # config.all, All.new
72
+ # end
73
+ def all(callable = nil, &block)
74
+ ::Mailgun::Tracking::Fanout.all(
75
+ callable || block
76
+ )
77
+ end
78
+
79
+ # Delegate any missing method call to the configuration.
53
80
  def method_missing(method_name, *arguments, &block)
54
- if Configuration.instance.respond_to?(method_name)
55
- Configuration.instance.public_send(method_name, *arguments, &block)
56
- else
57
- super
58
- end
81
+ return super unless configuration.respond_to?(method_name)
82
+
83
+ configuration.public_send(method_name, *arguments, &block)
59
84
  end
60
85
 
61
- # Replaces the Object.respond_to?() method.
86
+ # Replace the Object.respond_to?() method.
62
87
  def respond_to_missing?(method_name, include_private = false)
63
- Configuration.instance.respond_to?(method_name) || super
88
+ configuration.respond_to?(method_name) || super
64
89
  end
90
+
91
+ # @return [Mailgun::Tracking::Configuration]
92
+ def configuration
93
+ ::Mailgun::Tracking::Configuration.instance
94
+ end
95
+
96
+ private_class_method :configuration
65
97
  end
66
98
  end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+
5
+ module Mailgun
6
+ module Tracking
7
+ # Used to ensure the authenticity of event requests.
8
+ class Auth
9
+ SIGNATURE = 'signature'
10
+
11
+ # @param payload [Hash] webhook payload.
12
+ #
13
+ # @return [Boolean]
14
+ def self.call(payload, _env = nil)
15
+ new(payload).valid?
16
+ end
17
+
18
+ # Initialize a Mailgun::Tracking::Auth object.
19
+ #
20
+ # @param payload [Hash] webhook payload.
21
+ #
22
+ # @return [Mailgun::Tracking::Auth]
23
+ def initialize(payload)
24
+ @payload = payload
25
+ end
26
+
27
+ # Compare the resulting hexdigest to the signature.
28
+ #
29
+ # @return [Boolean]
30
+ def valid?
31
+ @payload.dig(SIGNATURE, SIGNATURE) == \
32
+ ::OpenSSL::HMAC.hexdigest(
33
+ ::OpenSSL::Digest::SHA256.new,
34
+ ::Mailgun::Tracking.api_key,
35
+ data
36
+ )
37
+ end
38
+
39
+ private
40
+
41
+ # Concatenate timestamp and token values.
42
+ #
43
+ # @return [String]
44
+ def data
45
+ [
46
+ @payload.dig(SIGNATURE, 'timestamp'),
47
+ @payload.dig(SIGNATURE, 'token')
48
+ ].join
49
+ end
50
+ end
51
+ end
52
+ end
@@ -4,23 +4,19 @@ require 'singleton'
4
4
 
5
5
  module Mailgun
6
6
  module Tracking
7
- # Stores configuration information.
7
+ # Configuration for Mailgun Tracking.
8
8
  class Configuration
9
- include Singleton
9
+ include ::Singleton
10
10
 
11
11
  DEFAULT_ENDPOINT = '/mailgun'
12
12
 
13
- # Mailgun API public key.
14
- #
15
- # @return [String]
13
+ # @return [String] Mailgun API public key.
16
14
  attr_accessor :api_key
17
15
 
18
- # Mailgun Webhook API endpoint.
19
- #
20
- # @return [String]
16
+ # @return [String] Mailgun callback URL.
21
17
  attr_accessor :endpoint
22
18
 
23
- # Initializes a new Configuration object.
19
+ # Initialize a Mailgun::Tracking::Configuration object.
24
20
  def initialize
25
21
  @endpoint = DEFAULT_ENDPOINT
26
22
  end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'catch_box/fanout'
4
+ require 'mailgun/tracking/auth'
5
+
6
+ module Mailgun
7
+ module Tracking
8
+ # It broadcast the payload to all callable based on event type. Also, there is an authenticity
9
+ # of the webhook before each broadcast.
10
+ class Fanout
11
+ extend ::CatchBox::Fanout
12
+
13
+ event 'event-data.event'
14
+
15
+ auth ::Mailgun::Tracking::Auth
16
+ end
17
+ end
18
+ end
@@ -1,55 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'catch_box/middleware'
4
+
3
5
  module Mailgun
4
6
  module Tracking
5
- # Rack-based middleware to handle event notifications.
6
- class Middleware
7
- # Initializes a new Middleware object.
8
- #
9
- # @param app the next Rack middleware in the stack.
7
+ # Rack middleware to handle an HTTP POST to the callback URL when events occur with a message.
8
+ class Middleware < ::CatchBox::Middleware
9
+ # Initialize a Mailgun::Tracking::Middleware object.
10
10
  def initialize(app)
11
- @app = app
12
- end
13
-
14
- # Thread-safe {call!}.
15
- #
16
- # @param env [Hash] Environment hash.
17
- #
18
- # @return [Array(Numeric,Hash,Array)] The Rack-style response.
19
- def call(env)
20
- dup.call!(env)
21
- end
22
-
23
- # Responds to Rack requests.
24
- #
25
- # @param env [Hash] Environment hash.
26
- #
27
- # @return [Array(Numeric,Hash,Array)] The Rack-style response.
28
- def call!(env)
29
- @request = Request.new(env)
30
-
31
- return @app.call(env) unless @request.mailgun_tracking?
32
-
33
- handle_event
34
- end
35
-
36
- private
37
-
38
- # @return [Array(Numeric,Hash,Array)] The Rack-style response.
39
- def null_response
40
- [200, {}, []]
41
- end
42
-
43
- # @return [Array(Numeric,Hash,Array)] The Rack-style response.
44
- def bad_request
45
- [400, {}, []]
46
- end
47
-
48
- def handle_event
49
- Mailgun::Tracking.notifier.broadcast(@request.payload.event_data.event, @request.payload)
50
- null_response
51
- rescue InvalidSignature
52
- bad_request
11
+ super(
12
+ app,
13
+ fanout: ::Mailgun::Tracking::Fanout,
14
+ endpoint: ::Mailgun::Tracking.endpoint
15
+ )
53
16
  end
54
17
  end
55
18
  end
@@ -3,9 +3,9 @@
3
3
  module Mailgun
4
4
  module Tracking
5
5
  # Mailgun Tracking Railtie.
6
- class Railtie < Rails::Railtie
6
+ class Railtie < ::Rails::Railtie
7
7
  initializer 'mailgun-tracking.insert_middleware' do |app|
8
- app.config.middleware.use(Mailgun::Tracking::Middleware)
8
+ app.config.middleware.use(::Mailgun::Tracking::Middleware)
9
9
  end
10
10
  end
11
11
  end
@@ -2,17 +2,18 @@
2
2
 
3
3
  module Mailgun
4
4
  module Tracking
5
- # This module holds the Mailgun Tracking version information.
5
+ # The module which hold version data.
6
6
  module Version
7
7
  module_function
8
8
 
9
9
  KEYS = %i[major minor patch].freeze
10
+ DOT = '.'
10
11
 
11
12
  # Major version.
12
13
  #
13
14
  # @return [Integer]
14
15
  def major
15
- 2
16
+ 3
16
17
  end
17
18
 
18
19
  # Minor version.
@@ -29,25 +30,25 @@ module Mailgun
29
30
  0
30
31
  end
31
32
 
32
- # Returns a hash representation of version.
33
+ # Return a hash representation of version.
33
34
  #
34
35
  # @return [Hash]
35
36
  def to_h
36
- Hash[KEYS.zip(to_a)]
37
+ ::Hash[KEYS.zip(to_a)]
37
38
  end
38
39
 
39
- # Returns a string representation of version.
40
+ # Return an array representation of version.
40
41
  #
41
42
  # @return [Array]
42
43
  def to_a
43
44
  [major, minor, patch]
44
45
  end
45
46
 
46
- # Returns an array representation of version.
47
+ # Return a string representation of version.
47
48
  #
48
49
  # @return [String]
49
50
  def to_s
50
- to_a.join('.')
51
+ to_a.join(DOT)
51
52
  end
52
53
  end
53
54
  end
@@ -0,0 +1,77 @@
1
+ # Logfile created on 2019-12-20 14:25:19 +0200 by logger.rb/66358
2
+ I, [2019-12-20T14:25:20.156536 #32357] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:25:20 +0200
3
+ F, [2019-12-20T14:25:20.159019 #32357] FATAL -- :
4
+ RSpec::Mocks::ExpiredTestDoubleError (#<InstanceDouble(Delivered) (anonymous)> was originally created in one example but has leaked into another example and can no longer be used. rspec-mocks' doubles are designed to only last for one example, and you need to create a new one in each example you wish to use it for.):
5
+ lib/mailgun/tracking/subscriber/evented.rb:26:in `call'
6
+ lib/mailgun/tracking/listener.rb:39:in `block in broadcast'
7
+ lib/mailgun/tracking/listener.rb:39:in `each'
8
+ lib/mailgun/tracking/listener.rb:39:in `broadcast'
9
+ lib/mailgun/tracking/notifier.rb:52:in `broadcast'
10
+ lib/mailgun/tracking/middleware.rb:49:in `handle_event'
11
+ lib/mailgun/tracking/middleware.rb:33:in `call!'
12
+ lib/mailgun/tracking/middleware.rb:20:in `call'
13
+
14
+
15
+ I, [2019-12-20T14:25:20.196642 #32357] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:25:20 +0200
16
+ I, [2019-12-20T14:25:20.244510 #32357] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:25:20 +0200
17
+ F, [2019-12-20T14:25:20.245802 #32357] FATAL -- :
18
+ RSpec::Mocks::ExpiredTestDoubleError (#<InstanceDouble(Delivered) (anonymous)> was originally created in one example but has leaked into another example and can no longer be used. rspec-mocks' doubles are designed to only last for one example, and you need to create a new one in each example you wish to use it for.):
19
+ lib/mailgun/tracking/subscriber/evented.rb:26:in `call'
20
+ lib/mailgun/tracking/listener.rb:39:in `block in broadcast'
21
+ lib/mailgun/tracking/listener.rb:39:in `each'
22
+ lib/mailgun/tracking/listener.rb:39:in `broadcast'
23
+ lib/mailgun/tracking/notifier.rb:52:in `broadcast'
24
+ lib/mailgun/tracking/middleware.rb:49:in `handle_event'
25
+ lib/mailgun/tracking/middleware.rb:33:in `call!'
26
+ lib/mailgun/tracking/middleware.rb:20:in `call'
27
+
28
+
29
+ I, [2019-12-20T14:25:20.248316 #32357] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:25:20 +0200
30
+ I, [2019-12-20T14:25:20.260350 #32357] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:25:20 +0200
31
+ F, [2019-12-20T14:25:20.261696 #32357] FATAL -- :
32
+ RSpec::Mocks::ExpiredTestDoubleError (#<InstanceDouble(Delivered) (anonymous)> was originally created in one example but has leaked into another example and can no longer be used. rspec-mocks' doubles are designed to only last for one example, and you need to create a new one in each example you wish to use it for.):
33
+ lib/mailgun/tracking/subscriber/evented.rb:26:in `call'
34
+ lib/mailgun/tracking/listener.rb:39:in `block in broadcast'
35
+ lib/mailgun/tracking/listener.rb:39:in `each'
36
+ lib/mailgun/tracking/listener.rb:39:in `broadcast'
37
+ lib/mailgun/tracking/notifier.rb:52:in `broadcast'
38
+ lib/mailgun/tracking/middleware.rb:49:in `handle_event'
39
+ lib/mailgun/tracking/middleware.rb:33:in `call!'
40
+ lib/mailgun/tracking/middleware.rb:20:in `call'
41
+
42
+
43
+ I, [2019-12-20T14:25:20.264988 #32357] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:25:20 +0200
44
+ I, [2019-12-20T14:25:58.135206 #32391] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:25:58 +0200
45
+ I, [2019-12-20T14:25:58.150294 #32391] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:25:58 +0200
46
+ I, [2019-12-20T14:26:03.646734 #32397] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:26:03 +0200
47
+ I, [2019-12-20T14:26:03.650724 #32397] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:26:03 +0200
48
+ I, [2019-12-20T14:26:08.150452 #32407] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:26:08 +0200
49
+ I, [2019-12-20T14:26:08.154891 #32407] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:26:08 +0200
50
+ I, [2019-12-20T14:26:11.908915 #32414] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:26:11 +0200
51
+ I, [2019-12-20T14:26:11.914969 #32414] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:26:11 +0200
52
+ I, [2019-12-20T14:26:16.436839 #32421] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:26:16 +0200
53
+ I, [2019-12-20T14:26:16.443137 #32421] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:26:16 +0200
54
+ I, [2019-12-20T14:30:17.817726 #32588] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:17 +0200
55
+ I, [2019-12-20T14:30:17.821355 #32588] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:17 +0200
56
+ I, [2019-12-20T14:30:22.836667 #32594] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:22 +0200
57
+ I, [2019-12-20T14:30:22.844164 #32594] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:22 +0200
58
+ I, [2019-12-20T14:30:32.888089 #32611] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:32 +0200
59
+ I, [2019-12-20T14:30:32.890907 #32611] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:32 +0200
60
+ I, [2019-12-20T14:30:36.327917 #32616] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:36 +0200
61
+ I, [2019-12-20T14:30:36.332494 #32616] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:36 +0200
62
+ I, [2019-12-20T14:30:39.691402 #32622] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:39 +0200
63
+ I, [2019-12-20T14:30:39.705041 #32622] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:39 +0200
64
+ I, [2019-12-20T14:30:43.148966 #32628] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:43 +0200
65
+ I, [2019-12-20T14:30:43.154670 #32628] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:43 +0200
66
+ I, [2019-12-20T14:30:47.047963 #32633] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:47 +0200
67
+ I, [2019-12-20T14:30:47.051108 #32633] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:47 +0200
68
+ I, [2019-12-20T14:30:50.559295 #32639] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:50 +0200
69
+ I, [2019-12-20T14:30:50.566124 #32639] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:30:50 +0200
70
+ I, [2019-12-20T14:31:22.457376 #32659] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:31:22 +0200
71
+ I, [2019-12-20T14:31:22.464730 #32659] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:31:22 +0200
72
+ I, [2019-12-20T14:31:44.337243 #32670] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:31:44 +0200
73
+ I, [2019-12-20T14:31:44.345211 #32670] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:31:44 +0200
74
+ I, [2019-12-20T14:33:25.161614 #32696] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:33:25 +0200
75
+ I, [2019-12-20T14:33:25.171927 #32696] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:33:25 +0200
76
+ I, [2019-12-20T14:33:33.415794 #32700] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:33:33 +0200
77
+ I, [2019-12-20T14:33:33.422618 #32700] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-12-20 14:33:33 +0200