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 +4 -4
- data/lib/generators/mailgun/tracking/install_generator.rb +1 -1
- data/lib/mailgun/tracking.rb +1 -0
- data/lib/mailgun/tracking/middleware.rb +2 -1
- data/lib/mailgun/tracking/notifier.rb +1 -1
- data/lib/mailgun/tracking/payload.rb +24 -31
- data/lib/mailgun/tracking/payload/legacy.rb +38 -0
- data/lib/mailgun/tracking/request.rb +30 -2
- data/lib/mailgun/tracking/signature.rb +3 -5
- data/lib/mailgun/tracking/version.rb +1 -1
- data/spec/dummy/rails/logs/test.log +15 -0
- data/spec/fixtures/delivered.json +63 -6
- data/spec/fixtures/legacy/delivered.json +13 -0
- data/spec/mailgun/tracking/listener_spec.rb +1 -1
- data/spec/mailgun/tracking/middleware_spec.rb +6 -5
- data/spec/mailgun/tracking/notifier_spec.rb +2 -2
- data/spec/mailgun/tracking/payload/legacy_spec.rb +37 -0
- data/spec/mailgun/tracking/payload_spec.rb +20 -23
- data/spec/mailgun/tracking/request_spec.rb +36 -0
- data/spec/mailgun/tracking/signature_spec.rb +34 -4
- data/spec/mailgun/tracking_spec.rb +6 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/support/shared_examples/integration/acts_as_rack.rb +2 -2
- data/spec/support/shared_examples/subscriber.rb +1 -1
- metadata +14 -8
- data/spec/support/simplecov.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e61daca288034107cca6ca891a80fa601016a555fb1fb2d07ab9b9755d52a12e
|
4
|
+
data.tar.gz: 6bc9cac63844b3190418dbf6b2fa14964bfbe372bf6eb23ef55ea6d6aaf8b739
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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__)
|
data/lib/mailgun/tracking.rb
CHANGED
@@ -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.
|
49
|
+
Mailgun::Tracking.notifier.broadcast(@request.payload.event, @request.payload)
|
49
50
|
null_response
|
50
51
|
rescue InvalidSignature
|
51
52
|
bad_request
|
@@ -1,50 +1,43 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
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 =
|
16
|
-
@original = options
|
17
|
-
define_instance_methods(Set.new(@options.keys), @options)
|
10
|
+
@options = options
|
18
11
|
end
|
19
12
|
|
20
|
-
|
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
|
-
|
17
|
+
def event
|
18
|
+
@event ||= __event_data.fetch('event')
|
19
|
+
end
|
30
20
|
|
31
|
-
|
32
|
-
|
33
|
-
class << self
|
34
|
-
self
|
35
|
-
end
|
21
|
+
def token
|
22
|
+
@token ||= __signature.fetch('token')
|
36
23
|
end
|
37
24
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
46
|
-
|
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 ||=
|
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
|
-
@
|
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
|
@@ -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
|
-
"
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
"
|
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
|
+
}
|
@@ -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)
|
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,
|
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
|
-
|
7
|
-
let(:options) do
|
8
|
-
{
|
9
|
-
'Message-Id' => '<payload@mailgun-tracking.com>'
|
10
|
-
}
|
11
|
-
end
|
6
|
+
let(:options) { fixture('delivered.json') }
|
12
7
|
|
13
|
-
|
14
|
-
|
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 '#
|
19
|
-
|
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
|
-
|
26
|
-
it
|
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
|
-
|
30
|
-
|
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
|
-
|
38
|
-
it
|
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
|
-
|
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
|
-
|
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|
|
data/spec/spec_helper.rb
CHANGED
@@ -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(
|
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
|
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.
|
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-
|
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.
|
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.
|
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.
|
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
|