mailgun-tracking 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21d2fa7599f08ae635591938264cdfdd0dadf64e2baed939ef236e5dead989a2
4
- data.tar.gz: a6d7f4a3f6d1c87c08d14467608a02141dd40906d1b5172049662e8ae3ece203
3
+ metadata.gz: e61daca288034107cca6ca891a80fa601016a555fb1fb2d07ab9b9755d52a12e
4
+ data.tar.gz: 6bc9cac63844b3190418dbf6b2fa14964bfbe372bf6eb23ef55ea6d6aaf8b739
5
5
  SHA512:
6
- metadata.gz: 8238ebe57aabc593f7810d20a44fe2c3b8c3440aefcf07fb5a564d093304d1d37874e04dc22346d2dda996c4a9cac3596d4cf0f71af0aa4fd8f0bf5d256465cb
7
- data.tar.gz: b90c4aacd8d8f8cc6ad70482eae5e2e23d2fe288fc77b7d259f30ed279214efd4e7d0c691a85d4de34344cb22812913bd9b3bc51d62897880d520e5252acce08
6
+ metadata.gz: 6de25bb55ff82c27c8420111acd1c72d4ee390ead819abc2631b1196e6d37ed62637023ed5048287f0ab399b23d1b942b626d8de1c4c9c58e7d3b2cc69b94ad0
7
+ data.tar.gz: dcd30f8087f1fd233b33a20d843ef1517ce1678d51b79bd8570574dabca01ab8963f944501f3e3e3cff1a6f268b1f37329112e7c3392cef3e516bff2fbc7cd09
@@ -4,7 +4,7 @@ module Mailgun
4
4
  module Tracking
5
5
  # Creates the Mailgun Tracking initializer file for Rails apps.
6
6
  #
7
- # @example Invokation from terminal
7
+ # @example Invocation from terminal
8
8
  # rails generate mailgun:tracking:install API_KEY ENDPOINT
9
9
  class InstallGenerator < Rails::Generators::Base
10
10
  source_root File.expand_path('templates', __dir__)
@@ -6,6 +6,7 @@ require 'mailgun/tracking/listener'
6
6
  require 'mailgun/tracking/middleware'
7
7
  require 'mailgun/tracking/notifier'
8
8
  require 'mailgun/tracking/payload'
9
+ require 'mailgun/tracking/payload/legacy'
9
10
  require 'mailgun/tracking/signature'
10
11
  require 'mailgun/tracking/subscriber'
11
12
  require 'mailgun/tracking/util'
@@ -27,6 +27,7 @@ module Mailgun
27
27
  # @return [Array(Numeric,Hash,Array)] The Rack-style response.
28
28
  def call!(env)
29
29
  @request = Request.new(env)
30
+
30
31
  return @app.call(env) unless @request.mailgun_tracking?
31
32
 
32
33
  handle_event
@@ -45,7 +46,7 @@ module Mailgun
45
46
  end
46
47
 
47
48
  def handle_event
48
- Mailgun::Tracking.notifier.broadcast(@request.params.fetch('event'), @request.payload)
49
+ Mailgun::Tracking.notifier.broadcast(@request.payload.event, @request.payload)
49
50
  null_response
50
51
  rescue InvalidSignature
51
52
  bad_request
@@ -49,7 +49,7 @@ module Mailgun
49
49
  # @return [NilClass]
50
50
  def broadcast(event, payload)
51
51
  Signature.verify!(payload)
52
- listener.broadcast(event, payload)
52
+ listener.broadcast(event, payload.body)
53
53
  end
54
54
 
55
55
  private
@@ -1,50 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
3
+ require_relative 'payload/legacy'
4
4
 
5
5
  module Mailgun
6
6
  module Tracking
7
7
  # Payload object.
8
8
  class Payload
9
- # Initializes a new Payload object.
10
- #
11
- # @param options [Hash]
12
- #
13
- # @return [Mailgun::Tracking::Payload]
14
9
  def initialize(options = {})
15
- @options = Util.normalize(options)
16
- @original = options
17
- define_instance_methods(Set.new(@options.keys), @options)
10
+ @options = options
18
11
  end
19
12
 
20
- # Returns a value of the original payload with the given key.
21
- #
22
- # @param key [String]
23
- #
24
- # @return a value of the original payload.
25
- def [](key)
26
- @original[key]
13
+ def body
14
+ @options
27
15
  end
28
16
 
29
- private
17
+ def event
18
+ @event ||= __event_data.fetch('event')
19
+ end
30
20
 
31
- # @return [Class]
32
- def __metaclass__
33
- class << self
34
- self
35
- end
21
+ def token
22
+ @token ||= __signature.fetch('token')
36
23
  end
37
24
 
38
- # @return [void]
39
- def define_instance_methods(keys, options)
40
- __metaclass__.instance_eval do
41
- keys.each do |key|
42
- define_method(key) { @options[key] }
43
- next unless [FalseClass, TrueClass].include?(options[key].class)
25
+ def timestamp
26
+ @timestamp ||= __signature.fetch('timestamp')
27
+ end
28
+
29
+ def signature
30
+ @signature ||= __signature.fetch('signature')
31
+ end
32
+
33
+ private
34
+
35
+ def __signature
36
+ @__signature ||= @options.fetch('signature')
37
+ end
44
38
 
45
- define_method(:"#{key}?") { @options[key] }
46
- end
47
- end
39
+ def __event_data
40
+ @__event_data ||= @options.fetch('event-data')
48
41
  end
49
42
  end
50
43
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mailgun
4
+ module Tracking
5
+ class Payload
6
+ # Legacy payload object.
7
+ class Legacy
8
+ def initialize(options = {})
9
+ @options = options
10
+ warn(<<~DEPRECATION)
11
+ [Mailgun::Tracking] The Legacy class refers to a previous version of the API
12
+ which is deprecated and it will be removed in the next major version.
13
+ DEPRECATION
14
+ end
15
+
16
+ def body
17
+ @options
18
+ end
19
+
20
+ def event
21
+ @event ||= @options.fetch('event')
22
+ end
23
+
24
+ def token
25
+ @token ||= @options.fetch('token')
26
+ end
27
+
28
+ def timestamp
29
+ @timestamp ||= @options.fetch('timestamp')
30
+ end
31
+
32
+ def signature
33
+ @signature ||= @options.fetch('signature')
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -15,10 +15,38 @@ module Mailgun
15
15
  path == Configuration.instance.endpoint
16
16
  end
17
17
 
18
- # @return [Mailgun::Tracking::Payload]
18
+ # @return [Mailgun::Tracking::Payload, Mailgun::Tracking::Payload::Legacy]
19
19
  def payload
20
- @payload ||= Payload.new(params)
20
+ @payload ||= begin
21
+ if params.key?('timestamp')
22
+ ::Mailgun::Tracking::Payload::Legacy.new(params)
23
+ else
24
+ ::Mailgun::Tracking::Payload.new(params)
25
+ end
26
+ end
21
27
  end
28
+
29
+ # A Mailgun::Tracking::Request::JSON is used to parsing JSON requests.
30
+ module JSON
31
+ APPLICATION_JSON = 'application/json'
32
+ FORM_HASH = 'rack.request.form_hash'
33
+ FORM_INPUT = 'rack.request.form_input'
34
+
35
+ # Returns the data received in the request body.
36
+ #
37
+ # @return [Hash]
38
+ def POST
39
+ return super unless media_type == APPLICATION_JSON
40
+
41
+ body = self.body.read
42
+ self.body.rewind
43
+ env.update(FORM_HASH => ::JSON.parse(body), FORM_INPUT => body)
44
+
45
+ get_header(FORM_HASH)
46
+ end
47
+ end
48
+
49
+ include JSON
22
50
  end
23
51
  end
24
52
  end
@@ -26,14 +26,12 @@ module Mailgun
26
26
  #
27
27
  # @return [Mailgun::Tracking::Signature]
28
28
  def initialize(payload)
29
- @token = payload['token']
30
- @timestamp = payload['timestamp']
31
- @signature = payload['signature']
29
+ @payload = payload
32
30
  end
33
31
 
34
32
  # @return [Boolean]
35
33
  def valid?
36
- @signature == OpenSSL::HMAC.hexdigest(digest, Configuration.instance.api_key, data)
34
+ @payload.signature == OpenSSL::HMAC.hexdigest(digest, Configuration.instance.api_key, data)
37
35
  end
38
36
 
39
37
  private
@@ -47,7 +45,7 @@ module Mailgun
47
45
  #
48
46
  # @return [String]
49
47
  def data
50
- [@timestamp, @token].join
48
+ [@payload.timestamp, @payload.token].join
51
49
  end
52
50
  end
53
51
  end
@@ -19,7 +19,7 @@ module Mailgun
19
19
  #
20
20
  # @return [Integer]
21
21
  def minor
22
- 0
22
+ 1
23
23
  end
24
24
 
25
25
  # Patch version.
@@ -36,3 +36,18 @@ SystemExit (exit):
36
36
  lib/mailgun/tracking/middleware.rb:29:in `_call'
37
37
  lib/mailgun/tracking/middleware.rb:22:in `call'
38
38
  I, [2019-10-16T17:18:16.198543 #12320] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-10-16 17:18:16 +0300
39
+ I, [2019-11-07T18:53:57.134697 #53967] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-11-07 18:53:57 +0200
40
+ I, [2019-11-07T18:53:57.158453 #53967] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-11-07 18:53:57 +0200
41
+ F, [2019-11-07T18:53:57.160416 #53967] FATAL -- :
42
+ KeyError (key not found: "event"):
43
+ lib/mailgun/tracking/payload/legacy.rb:17:in `fetch'
44
+ lib/mailgun/tracking/payload/legacy.rb:17:in `event'
45
+ lib/mailgun/tracking/middleware.rb:60:in `handle_event'
46
+ lib/mailgun/tracking/middleware.rb:43:in `call!'
47
+ lib/mailgun/tracking/middleware.rb:20:in `call'
48
+
49
+
50
+ I, [2019-11-07T18:55:50.036561 #53989] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-11-07 18:55:50 +0200
51
+ I, [2019-11-07T18:55:50.076942 #53989] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-11-07 18:55:50 +0200
52
+ I, [2019-11-07T18:56:17.648709 #53999] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-11-07 18:56:17 +0200
53
+ I, [2019-11-07T18:56:17.662346 #53999] INFO -- : Started POST "/mailgun" for 127.0.0.1 at 2019-11-07 18:56:17 +0200
@@ -1,8 +1,65 @@
1
1
  {
2
- "domain": "mail.example.com",
3
- "Message-Id": "<20160329071939.35138.9413.6915422C@mail.example.com>",
4
- "event": "delivered",
5
- "timestamp": "1499697910",
6
- "token": "b5751a49a024483da8d41c3684f98b8f",
7
- "signature": "374e0b1a3deeb57318c783d43ff71093fbf26406a452761dab91bf346a93b49e"
2
+ "signature": {
3
+ "timestamp": "1572632560",
4
+ "token": "e71ad7ff8d6f43b62d31615083bde85fb55e4e2b5121cb1239",
5
+ "signature": "9d21d1689889ec5f4ffa3c7e5e6598c8450c3eada8f6cc03e47b2342a9c9da61"
6
+ },
7
+ "event-data": {
8
+ "tags": [
9
+ "my_tag_1",
10
+ "my_tag_2"
11
+ ],
12
+ "timestamp": 1521472262.908181,
13
+ "storage": {
14
+ "url": "https://se.api.mailgun.net/v3/domains/sandboxfb0641fa1b904bb28ba00cba62dca7f1.mailgun.org/messages/message_key",
15
+ "key": "message_key"
16
+ },
17
+ "envelope": {
18
+ "sending-ip": "209.61.154.250",
19
+ "sender": "bob@sandboxfb0641fa1b904bb28ba00cba62dca7f1.mailgun.org",
20
+ "transport": "smtp",
21
+ "targets": "alice@example.com"
22
+ },
23
+ "recipient-domain": "example.com",
24
+ "id": "CPgfbmQMTCKtHW6uIWtuVe",
25
+ "campaigns": [
26
+
27
+ ],
28
+ "user-variables": {
29
+ "my_var_1": "Mailgun Variable #1",
30
+ "my-var-2": "awesome"
31
+ },
32
+ "flags": {
33
+ "is-routed": false,
34
+ "is-authenticated": true,
35
+ "is-system-test": false,
36
+ "is-test-mode": false
37
+ },
38
+ "log-level": "info",
39
+ "message": {
40
+ "headers": {
41
+ "to": "Alice <alice@example.com>",
42
+ "message-id": "20130503182626.18666.16540@sandboxfb0641fa1b904bb28ba00cba62dca7f1.mailgun.org",
43
+ "from": "Bob <bob@sandboxfb0641fa1b904bb28ba00cba62dca7f1.mailgun.org>",
44
+ "subject": "Test delivered webhook"
45
+ },
46
+ "attachments": [
47
+
48
+ ],
49
+ "size": 111
50
+ },
51
+ "recipient": "alice@example.com",
52
+ "event": "delivered",
53
+ "delivery-status": {
54
+ "tls": true,
55
+ "mx-host": "smtp-in.example.com",
56
+ "attempt-no": 1,
57
+ "description": "",
58
+ "session-seconds": 0.4331989288330078,
59
+ "utf8": true,
60
+ "code": 250,
61
+ "message": "OK",
62
+ "certificate-verified": true
63
+ }
64
+ }
8
65
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "timestamp": "1499697910",
3
+ "token": "b5751a49a024483da8d41c3684f98b8f",
4
+ "signature": "374e0b1a3deeb57318c783d43ff71093fbf26406a452761dab91bf346a93b49e",
5
+ "domain": "mail.example.com",
6
+ "my_var_1": "Mailgun Variable #1",
7
+ "my-var-2": "awesome",
8
+ "message-headers": "[[\"Received\", \"by luna.mailgun.net with SMTP mgrt 8734663311733; Fri, 03 May 2013 18:26:27 +0000\"], [\"Content-Type\", [\"multipart/alternative\", {\"boundary\": \"eb663d73ae0a4d6c9153cc0aec8b7520\"}]], [\"Mime-Version\", \"1.0\"], [\"Subject\", \"Test deliver webhook\"], [\"From\", \"Bob <bob@sandboxfb0641fa1b904bb28ba00cba62dca7f1.mailgun.org>\"], [\"To\", \"Alice <alice@example.com>\"], [\"Message-Id\", \"<20130503182626.18666.16540@sandboxfb0641fa1b904bb28ba00cba62dca7f1.mailgun.org>\"], [\"X-Mailgun-Variables\", \"{\\\"my_var_1\\\": \\\"Mailgun Variable #1\\\", \\\"my-var-2\\\": \\\"awesome\\\"}\"], [\"Date\", \"Fri, 03 May 2013 18:26:27 +0000\"], [\"Sender\", \"bob@sandboxfb0641fa1b904bb28ba00cba62dca7f1.mailgun.org\"]]",
9
+ "Message-Id": "<20160329071939.35138.9413.6915422C@mail.example.com>",
10
+ "recipient": "alice@example.com",
11
+ "event": "delivered",
12
+ "body-plain": ""
13
+ }
@@ -24,7 +24,7 @@ RSpec.describe Mailgun::Tracking::Listener do
24
24
  end
25
25
 
26
26
  describe '#broadcast' do
27
- let(:payload) { fixture('delivered.json') }
27
+ let(:payload) { fixture('legacy/delivered.json') }
28
28
 
29
29
  before do
30
30
  allow(subscriber).to receive(:call)
@@ -5,12 +5,13 @@ RSpec.describe Mailgun::Tracking::Middleware do
5
5
 
6
6
  let(:app) { proc { [200, {}, []] } }
7
7
  let(:notifier) { instance_double(Mailgun::Tracking::Notifier) }
8
- let(:request) { instance_double(Mailgun::Tracking::Request) }
8
+ let(:request) do
9
+ instance_double(Mailgun::Tracking::Request, payload: payload, media_type: 'application/x-www-form-urlencoded')
10
+ end
9
11
  let(:env) { env_for('http://localhost:3000') }
10
- let(:payload) { instance_double(Mailgun::Tracking::Payload) }
12
+ let(:payload) { instance_double(Mailgun::Tracking::Payload::Legacy, event: 'delivered') }
11
13
 
12
14
  before do
13
- allow(request).to receive(:payload).and_return(payload)
14
15
  allow(Mailgun::Tracking).to receive(:notifier).and_return(notifier)
15
16
  allow(Mailgun::Tracking::Request).to receive(:new).with(env).and_return(request)
16
17
  end
@@ -31,7 +32,7 @@ RSpec.describe Mailgun::Tracking::Middleware do
31
32
  end
32
33
 
33
34
  context 'when request is respond to the specified URL and the signature comparison is unsuccessful' do
34
- let(:params) { fixture('delivered.json') }
35
+ let(:params) { fixture('legacy/delivered.json') }
35
36
 
36
37
  before do
37
38
  allow(notifier).to receive(:broadcast).and_raise(Mailgun::Tracking::InvalidSignature)
@@ -48,7 +49,7 @@ RSpec.describe Mailgun::Tracking::Middleware do
48
49
  end
49
50
 
50
51
  context 'when request is respond to the specified URL and the signature comparison is successful' do
51
- let(:params) { fixture('delivered.json') }
52
+ let(:params) { fixture('legacy/delivered.json') }
52
53
 
53
54
  before do
54
55
  allow(request).to receive(:mailgun_tracking?).and_return(true)
@@ -47,7 +47,7 @@ RSpec.describe Mailgun::Tracking::Notifier do
47
47
  end
48
48
 
49
49
  describe '#broadcast' do
50
- let(:payload) { fixture('delivered.json') }
50
+ let(:payload) { instance_double(Mailgun::Tracking::Payload, body: fixture('legacy/delivered.json')) }
51
51
 
52
52
  before do
53
53
  allow(Mailgun::Tracking::Signature).to receive(:verify!)
@@ -60,7 +60,7 @@ RSpec.describe Mailgun::Tracking::Notifier do
60
60
  end
61
61
 
62
62
  it 'broadcasts an event' do
63
- expect(listener).to have_received(:broadcast).with(:delivered, payload)
63
+ expect(listener).to have_received(:broadcast).with(:delivered, fixture('legacy/delivered.json'))
64
64
  end
65
65
  end
66
66
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Mailgun::Tracking::Payload::Legacy do
4
+ subject(:legacy) { described_class.new(options) }
5
+
6
+ let(:options) { fixture('legacy/delivered.json') }
7
+
8
+ describe '#body' do
9
+ it 'returns body' do
10
+ expect(legacy.body).to eq(options)
11
+ end
12
+ end
13
+
14
+ describe '#event' do
15
+ it 'returns event' do
16
+ expect(legacy.event).to eq(options.fetch('event'))
17
+ end
18
+ end
19
+
20
+ describe '#token' do
21
+ it 'returns token' do
22
+ expect(legacy.token).to eq(options.fetch('token'))
23
+ end
24
+ end
25
+
26
+ describe '#timestamp' do
27
+ it 'returns timestamp' do
28
+ expect(legacy.timestamp).to eq(options.fetch('timestamp'))
29
+ end
30
+ end
31
+
32
+ describe '#signature' do
33
+ it 'returns signature' do
34
+ expect(legacy.signature).to eq(options.fetch('signature'))
35
+ end
36
+ end
37
+ end
@@ -3,38 +3,35 @@
3
3
  RSpec.describe Mailgun::Tracking::Payload do
4
4
  subject(:payload) { described_class.new(options) }
5
5
 
6
- describe '#[]' do
7
- let(:options) do
8
- {
9
- 'Message-Id' => '<payload@mailgun-tracking.com>'
10
- }
11
- end
6
+ let(:options) { fixture('delivered.json') }
12
7
 
13
- it 'returns the value object from original payload' do
14
- expect(payload['Message-Id']).to eq(options['Message-Id'])
8
+ describe '#body' do
9
+ it 'returns body' do
10
+ expect(payload.body).to eq(options)
15
11
  end
16
12
  end
17
13
 
18
- describe '#respond_to?' do
19
- let(:options) do
20
- {
21
- 'Message-Id' => '<payload@mailgun-tracking.com>'
22
- }
14
+ describe '#event' do
15
+ it 'returns event' do
16
+ expect(payload.event).to eq(options.fetch('event-data').fetch('event'))
23
17
  end
18
+ end
24
19
 
25
- it { is_expected.to respond_to(:message_id) }
26
- it { expect(payload.message_id).to eq(options['Message-Id']) }
20
+ describe '#token' do
21
+ it 'returns token' do
22
+ expect(payload.token).to eq(options.fetch('signature').fetch('token'))
23
+ end
27
24
  end
28
25
 
29
- context 'when the options include a boolean data type' do
30
- let(:options) do
31
- {
32
- boolean: true,
33
- string: 'string'
34
- }
26
+ describe '#timestamp' do
27
+ it 'returns timestamp' do
28
+ expect(payload.timestamp).to eq(options.fetch('signature').fetch('timestamp'))
35
29
  end
30
+ end
36
31
 
37
- it { is_expected.to be_boolean }
38
- it { is_expected.to respond_to(:boolean?) }
32
+ describe '#signature' do
33
+ it 'returns signature' do
34
+ expect(payload.signature).to eq(options.fetch('signature').fetch('signature'))
35
+ end
39
36
  end
40
37
  end
@@ -22,4 +22,40 @@ RSpec.describe Mailgun::Tracking::Request do
22
22
  it { is_expected.not_to be_mailgun_tracking }
23
23
  end
24
24
  end
25
+
26
+ describe '#payload' do
27
+ context 'when the parameters contain the timestamp' do
28
+ let(:env) { env_for('http://localhost:3000/mailgun', method: :post, params: { 'timestamp' => '1572632560' }) }
29
+
30
+ it 'returns legacy payload' do
31
+ expect(request.payload).to be_an_instance_of(Mailgun::Tracking::Payload::Legacy)
32
+ end
33
+ end
34
+
35
+ context 'when the parameters do not contain the timestamp' do
36
+ let(:env) { env_for('http://localhost:3000/mailgun', method: :post, params: { 'signature' => {} }) }
37
+
38
+ it 'returns payload' do
39
+ expect(request.payload).to be_an_instance_of(Mailgun::Tracking::Payload)
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'when application/json request' do
45
+ let(:env) { env_for('/', method: :post, input: input, 'CONTENT_TYPE' => content_type) }
46
+ let(:input) { 'foo=bar' }
47
+ let(:content_type) { 'application/json; charset=utf-8' }
48
+
49
+ it 'rewinds input' do
50
+ expect(request.body.read).to eq(input)
51
+ end
52
+
53
+ context 'when input is a hash' do
54
+ let(:input) { '{"qux": "bin"}' }
55
+
56
+ it 'adds a parsed hash to POST params' do
57
+ expect(request.params['qux']).to eq('bin')
58
+ end
59
+ end
60
+ end
25
61
  end
@@ -3,15 +3,29 @@
3
3
  RSpec.describe Mailgun::Tracking::Signature do
4
4
  subject(:signature) { described_class.new(payload) }
5
5
 
6
- let(:payload) { fixture('delivered.json') }
7
-
8
6
  describe '.verify!' do
9
7
  context 'when the signature comparison is successful' do
8
+ let(:payload) do
9
+ instance_double(
10
+ Mailgun::Tracking::Payload,
11
+ timestamp: '1499697910',
12
+ token: 'b5751a49a024483da8d41c3684f98b8f',
13
+ signature: '374e0b1a3deeb57318c783d43ff71093fbf26406a452761dab91bf346a93b49e'
14
+ )
15
+ end
16
+
10
17
  it { expect(described_class.verify!(payload)).to be true }
11
18
  end
12
19
 
13
20
  context 'when the signature comparison is unsuccessful' do
14
- before { payload['timestamp'] = '' }
21
+ let(:payload) do
22
+ instance_double(
23
+ Mailgun::Tracking::Payload,
24
+ timestamp: '',
25
+ token: 'b5751a49a024483da8d41c3684f98b8f',
26
+ signature: '374e0b1a3deeb57318c783d43ff71093fbf26406a452761dab91bf346a93b49e'
27
+ )
28
+ end
15
29
 
16
30
  it { expect { described_class.verify!(payload) }.to raise_error(Mailgun::Tracking::InvalidSignature) }
17
31
  end
@@ -19,11 +33,27 @@ RSpec.describe Mailgun::Tracking::Signature do
19
33
 
20
34
  describe '#valid?' do
21
35
  context 'when the signature comparison is successful' do
36
+ let(:payload) do
37
+ instance_double(
38
+ Mailgun::Tracking::Payload,
39
+ timestamp: '1499697910',
40
+ token: 'b5751a49a024483da8d41c3684f98b8f',
41
+ signature: '374e0b1a3deeb57318c783d43ff71093fbf26406a452761dab91bf346a93b49e'
42
+ )
43
+ end
44
+
22
45
  it { is_expected.to be_valid }
23
46
  end
24
47
 
25
48
  context 'when the signature comparison is unsuccessful' do
26
- before { payload['timestamp'] = '' }
49
+ let(:payload) do
50
+ instance_double(
51
+ Mailgun::Tracking::Payload,
52
+ timestamp: '',
53
+ token: 'b5751a49a024483da8d41c3684f98b8f',
54
+ signature: '374e0b1a3deeb57318c783d43ff71093fbf26406a452761dab91bf346a93b49e'
55
+ )
56
+ end
27
57
 
28
58
  it { is_expected.not_to be_valid }
29
59
  end
@@ -6,6 +6,12 @@ RSpec.describe Mailgun::Tracking do
6
6
  it { is_expected.to respond_to(:api_key=) }
7
7
  it { is_expected.to respond_to(:endpoint=) }
8
8
 
9
+ it do
10
+ expect do
11
+ described_class.non_existent_method
12
+ end.to raise_error(NoMethodError)
13
+ end
14
+
9
15
  describe '.configure' do
10
16
  before do
11
17
  described_class.configure do |config|
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'simplecov' if ENV['COVERAGE']
4
+
3
5
  require 'rack/test'
4
6
  require 'bundler/setup'
5
7
  require 'mailgun/tracking'
@@ -6,7 +6,7 @@ end
6
6
 
7
7
  RSpec.shared_examples 'acts as rack' do
8
8
  let(:app) { Dummy::Application }
9
- let(:payload) { fixture('delivered.json') }
9
+ let(:payload) { fixture('legacy/delivered.json') }
10
10
  let(:delivered) { instance_double(Delivered) }
11
11
 
12
12
  before do
@@ -24,7 +24,7 @@ RSpec.shared_examples 'acts as rack' do
24
24
 
25
25
  it do
26
26
  post('/mailgun', payload)
27
- expect(delivered).to have_received(:call).with(instance_of(Mailgun::Tracking::Payload)).twice
27
+ expect(delivered).to have_received(:call).with(payload).twice
28
28
  end
29
29
 
30
30
  context 'when the signature comparison is unsuccessful' do
@@ -3,7 +3,7 @@
3
3
  RSpec.shared_examples 'subscriber' do
4
4
  describe '#call' do
5
5
  let(:callable) { proc {} }
6
- let(:payload) { fixture('delivered.json') }
6
+ let(:payload) { fixture('legacy/delivered.json') }
7
7
 
8
8
  before { allow(callable).to receive(:call).with(payload) }
9
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailgun-tracking
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Chubchenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-16 00:00:00.000000000 Z
11
+ date: 2019-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -100,14 +100,14 @@ dependencies:
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 0.75.1
103
+ version: 0.76.0
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 0.75.1
110
+ version: 0.76.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: rubocop-performance
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -166,6 +166,7 @@ files:
166
166
  - lib/mailgun/tracking/middleware.rb
167
167
  - lib/mailgun/tracking/notifier.rb
168
168
  - lib/mailgun/tracking/payload.rb
169
+ - lib/mailgun/tracking/payload/legacy.rb
169
170
  - lib/mailgun/tracking/railtie.rb
170
171
  - lib/mailgun/tracking/request.rb
171
172
  - lib/mailgun/tracking/signature.rb
@@ -179,6 +180,7 @@ files:
179
180
  - spec/dummy/rails/logs/test.log
180
181
  - spec/dummy/sinatra/application.rb
181
182
  - spec/fixtures/delivered.json
183
+ - spec/fixtures/legacy/delivered.json
182
184
  - spec/integration/rack/rack_spec.rb
183
185
  - spec/integration/rails/rails_spec.rb
184
186
  - spec/integration/sinatra/sinatra_spec.rb
@@ -186,6 +188,7 @@ files:
186
188
  - spec/mailgun/tracking/listener_spec.rb
187
189
  - spec/mailgun/tracking/middleware_spec.rb
188
190
  - spec/mailgun/tracking/notifier_spec.rb
191
+ - spec/mailgun/tracking/payload/legacy_spec.rb
189
192
  - spec/mailgun/tracking/payload_spec.rb
190
193
  - spec/mailgun/tracking/request_spec.rb
191
194
  - spec/mailgun/tracking/signature_spec.rb
@@ -200,11 +203,13 @@ files:
200
203
  - spec/support/rack_helpers.rb
201
204
  - spec/support/shared_examples/integration/acts_as_rack.rb
202
205
  - spec/support/shared_examples/subscriber.rb
203
- - spec/support/simplecov.rb
204
206
  homepage: https://github.com/chubchenko/mailgun-tracking
205
207
  licenses:
206
208
  - MIT
207
- metadata: {}
209
+ metadata:
210
+ bug_tracker_uri: https://github.com/chubchenko/mailgun-tracking/issues
211
+ changelog_uri: https://github.com/chubchenko/mailgun-tracking/blob/master/CHANGELOG.md
212
+ source_code_uri: https://github.com/chubchenko/mailgun-tracking
208
213
  post_install_message:
209
214
  rdoc_options: []
210
215
  require_paths:
@@ -220,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
225
  - !ruby/object:Gem::Version
221
226
  version: '0'
222
227
  requirements: []
223
- rubygems_version: 3.0.6
228
+ rubygems_version: 3.0.2
224
229
  signing_key:
225
230
  specification_version: 4
226
231
  summary: Integration with Mailgun Webhooks
@@ -233,16 +238,17 @@ test_files:
233
238
  - spec/integration/sinatra/sinatra_spec.rb
234
239
  - spec/integration/rack/rack_spec.rb
235
240
  - spec/integration/rails/rails_spec.rb
236
- - spec/support/simplecov.rb
237
241
  - spec/support/rack_helpers.rb
238
242
  - spec/support/fixture.rb
239
243
  - spec/support/shared_examples/integration/acts_as_rack.rb
240
244
  - spec/support/shared_examples/subscriber.rb
245
+ - spec/fixtures/legacy/delivered.json
241
246
  - spec/fixtures/delivered.json
242
247
  - spec/mailgun/tracking_spec.rb
243
248
  - spec/mailgun/tracking/configuration_spec.rb
244
249
  - spec/mailgun/tracking/version_spec.rb
245
250
  - spec/mailgun/tracking/signature_spec.rb
251
+ - spec/mailgun/tracking/payload/legacy_spec.rb
246
252
  - spec/mailgun/tracking/notifier_spec.rb
247
253
  - spec/mailgun/tracking/subscriber_spec.rb
248
254
  - spec/mailgun/tracking/middleware_spec.rb
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- if ENV['COVERAGE'] == 'true'
4
- require 'simplecov'
5
-
6
- SimpleCov.start do
7
- add_filter('integration')
8
- end
9
- end