mandrill-rails 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.travis.yml +11 -0
- data/Gemfile +5 -0
- data/Guardfile +10 -0
- data/LICENSE +22 -0
- data/README.rdoc +128 -0
- data/Rakefile +21 -0
- data/lib/mandrill-rails.rb +7 -0
- data/lib/mandrill-rails/version.rb +5 -0
- data/lib/mandrill-rails/web_hook_processor.rb +54 -0
- data/lib/mandrill/web_hook.rb +7 -0
- data/lib/mandrill/web_hook/event_decorator.rb +77 -0
- data/lib/mandrill/web_hook/processor.rb +31 -0
- data/mandrill-rails.gemspec +26 -0
- data/spec/mandrill-rails/web_hook_processor_spec.rb +33 -0
- data/spec/mandrill/web_hook/event_decorator_spec.rb +105 -0
- data/spec/mandrill/web_hook/processor_spec.rb +29 -0
- data/spec/spec_helper.rb +24 -0
- metadata +186 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Paul Gallagher
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
= Mandrill::Rails {<img src="https://secure.travis-ci.org/evendis/mandrill-rails.png" />}[http://travis-ci.org/evendis/mandrill-rails]
|
2
|
+
|
3
|
+
Mandrill::Rails extends the capabilities of the
|
4
|
+
{Mandrill}[https://github.com/tatemae-consultancy/mandrill] gem to provide tighter integration for Rails projects.
|
5
|
+
|
6
|
+
The primary goal of Mandrill::Rails is to make supporting Mandrill web hooks as easy and Rails-native as possible. As other opportunities for better Rails integration of the Mandrill API are discovered, these may be rolled in too.
|
7
|
+
|
8
|
+
FYI, {Mandrill}[http://mandrill.com/] is the transactional email service by the same folks who do MailChimp.
|
9
|
+
|
10
|
+
== Requirements and Known Limitations
|
11
|
+
|
12
|
+
* Tested with MRI 1.9.3
|
13
|
+
* Requires Rails >= 3.0.3 (including 3.1 and 3.2)
|
14
|
+
* Includes {Mandrill}[https://github.com/tatemae-consultancy/mandrill] ~> 0.0.2 as a dependency
|
15
|
+
|
16
|
+
Food for thought (upcoming features maybe)..
|
17
|
+
* some generators may be handy to avoid the manual coding to hook up web hooks
|
18
|
+
* I thought about implementing this as an engine, but the overhead did not seem appropriate. Maybe that view will change..
|
19
|
+
|
20
|
+
== The Mandrill::Rails Cookbook
|
21
|
+
|
22
|
+
=== How do I install it for normal use?
|
23
|
+
|
24
|
+
Add this line to your application's Gemfile:
|
25
|
+
|
26
|
+
gem 'mandrill-rails'
|
27
|
+
|
28
|
+
And then execute:
|
29
|
+
|
30
|
+
$ bundle
|
31
|
+
|
32
|
+
Or install it yourself as:
|
33
|
+
|
34
|
+
$ gem install mandrill-rails
|
35
|
+
|
36
|
+
=== How do I install it for gem development?
|
37
|
+
|
38
|
+
If you want to work on enhancements of fix bugs in Mandrill::Rails, fork and clone the github repository. If you are using bundler (recommended), run <tt>bundle</tt> to install development dependencies.
|
39
|
+
|
40
|
+
See the section below on 'Contributing to Mandrill::Rails' for more information.
|
41
|
+
|
42
|
+
=== How do I configure my app for incoming Mandrill WebHooks?
|
43
|
+
|
44
|
+
Say we have configured Mandrill to send requests to /inbox at our site (see the next recipes for how you do that).
|
45
|
+
|
46
|
+
Once we have Mandrill::Rails in our project, we just need to do two things. There's no generator to help you do this at the moment, but it is pretty simple:
|
47
|
+
|
48
|
+
First, configure a resource route:
|
49
|
+
|
50
|
+
resource :inbox, :controller => 'inbox', :only => [:show,:create]
|
51
|
+
|
52
|
+
Next, create the corresponding controller:
|
53
|
+
|
54
|
+
class InboxController < ApplicationController
|
55
|
+
include Mandrill::Rails::WebHookProcessor
|
56
|
+
end
|
57
|
+
|
58
|
+
That's all for the basic do-nothing endpoint setup. Note that we need both the GET and POST routes (Mandrill sends data to the POST route, but it uses GET to test the availability of the endpoint).
|
59
|
+
|
60
|
+
You can setup as many of these controllers as you need, if you wish different types of events to be handled by different routes.
|
61
|
+
|
62
|
+
=== How do I configure Mandrill to send inbound email to my app?
|
63
|
+
|
64
|
+
See {Mandrill Inbound Domains}[https://mandrillapp.com/inbound]
|
65
|
+
* enter the mail route you want to match on e.g. *@app.mydomain.com
|
66
|
+
* set the WebHook enpoint to match e.g. http://mydomain.com/inbox
|
67
|
+
|
68
|
+
=== How do I configure Mandrill to send WebHook requests to my app?
|
69
|
+
|
70
|
+
See {Mandrill WebHooks}[https://mandrillapp.com/settings/webhooks]
|
71
|
+
* select the events you want to trigger on
|
72
|
+
* set the "Post to URL" to point to your controller e.g. http://mydomain.com/inbox
|
73
|
+
|
74
|
+
=== How do I handle a specific Mandrill event payload in my app?
|
75
|
+
|
76
|
+
Once you have configured Mandrill and setup your routes and controllers, we can successfully
|
77
|
+
receive WebHook event notifications from Mandrill. But we are not doing anything with the payload yet.
|
78
|
+
|
79
|
+
To handle specific Mandrill event payloads, we just need to implement a handler for each event type
|
80
|
+
we are interested in.
|
81
|
+
|
82
|
+
The list of available event types includes: inbound, send, hard_bounce, soft_bounce, open,
|
83
|
+
click, spam, unsub, and reject.
|
84
|
+
|
85
|
+
In our controller, we simply write a method called handle_<event-type> and it will be called
|
86
|
+
for each event payload received. The event payload will be passed to this method
|
87
|
+
as an Mandrill::WebHook::EventDecorator - basically a Hash with some additional methods to
|
88
|
+
help extract payload-specific elements.
|
89
|
+
|
90
|
+
For example, to handle inbound email:
|
91
|
+
|
92
|
+
class InboxController < ApplicationController
|
93
|
+
include Mandrill::Rails::WebHookProcessor
|
94
|
+
|
95
|
+
def handle_inbound(event_payload)
|
96
|
+
Item.save_inbound_mail(event_payload)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
If the handling of the payload may be time-consuming, you could throw it onto a background
|
102
|
+
queue at this point instead.
|
103
|
+
|
104
|
+
Note that Mandrill may send multiple event payloads in a single request, but you don't need
|
105
|
+
to worry about that. Each event payload will be unpacked from the request and dispatched to
|
106
|
+
your handler individually.
|
107
|
+
|
108
|
+
And if you don't care to handle a specific payload type - then just don't implement the associated handler.
|
109
|
+
|
110
|
+
=== How do I use Mandrill gem features with Mandrill::Rails?
|
111
|
+
|
112
|
+
{Mandrill}[https://github.com/tatemae-consultancy/mandrill] is included with Mandrill::Rails
|
113
|
+
and its behaviour is unchanged. You can use all the features of the Mandrill gem as normal.
|
114
|
+
|
115
|
+
== Contributing to Mandrill::Rails
|
116
|
+
|
117
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
118
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
119
|
+
* Fork the project
|
120
|
+
* Start a feature/bugfix branch
|
121
|
+
* Commit and push until you are happy with your contribution
|
122
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
123
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
124
|
+
|
125
|
+
== Copyright
|
126
|
+
|
127
|
+
Copyright (c) 2012 Paul Gallagher. See LICENSE for further details.
|
128
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
|
7
|
+
desc "Run all RSpec test examples"
|
8
|
+
RSpec::Core::RakeTask.new do |spec|
|
9
|
+
spec.rspec_opts = ["-c", "-f progress"]
|
10
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
require 'rdoc/task'
|
16
|
+
RDoc::Task.new do |rdoc|
|
17
|
+
rdoc.main = "README.rdoc"
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = "mandrill-rails"
|
20
|
+
rdoc.rdoc_files.include('README*', 'lib/**/*.rb')
|
21
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# WebHookProcessor is a module that mixes in Mandrill web hook processing support
|
2
|
+
# to a controller in your application.
|
3
|
+
#
|
4
|
+
# The controller is expected to be a singlular resource controller.
|
5
|
+
# WebHookProcessor provides the :show and :create method implementation.
|
6
|
+
#
|
7
|
+
# 1. Create a controller that includes Mandrill::Rails::WebHookProcessor
|
8
|
+
# 2. Direct a GET :show and POST :create route to the controller
|
9
|
+
# 3. Define handlers for each of the event types you want to handle
|
10
|
+
#
|
11
|
+
# e.g. in routes.rb:
|
12
|
+
#
|
13
|
+
# resource :webhook, :controller => 'webhook', :only => [:show,:create]
|
14
|
+
#
|
15
|
+
# e.g. a Webhook controller:
|
16
|
+
#
|
17
|
+
# class WebhookController < ApplicationController
|
18
|
+
# include Mandrill::Rails::WebHookProcessor
|
19
|
+
#
|
20
|
+
# # Command: handle each 'inbound' +event_payload+ from Mandrill
|
21
|
+
# def handle_inbound(event_payload)
|
22
|
+
# # do some stuff
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # Define other handlers for each event type required.
|
26
|
+
# # Possible event types: inbound, send, hard_bounce, soft_bounce, open, click, spam, unsub, or reject
|
27
|
+
# # def handle_<event_type>(event_payload)
|
28
|
+
# # # do some stuff
|
29
|
+
# # end
|
30
|
+
#
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
module Mandrill::Rails::WebHookProcessor
|
34
|
+
extend ActiveSupport::Concern
|
35
|
+
|
36
|
+
included do
|
37
|
+
skip_before_filter :verify_authenticity_token
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns 200 and does nothing else (this is a test done by the mandrill service)
|
41
|
+
def show
|
42
|
+
head(:ok)
|
43
|
+
end
|
44
|
+
|
45
|
+
def create
|
46
|
+
if processor = Mandrill::WebHook::Processor.new(params)
|
47
|
+
processor.callback_host = self
|
48
|
+
processor.run!
|
49
|
+
end
|
50
|
+
head(:ok)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Wraps an individual Mandrill web hook event payload,
|
2
|
+
# providing some convenience methods handling the payload.
|
3
|
+
#
|
4
|
+
# Given a raw event payload Hash, wrap it thus:
|
5
|
+
#
|
6
|
+
# JSON.parse(params['mandrill_events']).each do |raw_event|
|
7
|
+
# event = Mandrill::WebHook::EventDecorator[raw_event]
|
8
|
+
# ..
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
class Mandrill::WebHook::EventDecorator < Hash
|
12
|
+
|
13
|
+
# Returns the event type
|
14
|
+
def event_type
|
15
|
+
self['event']
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the subject
|
19
|
+
def subject
|
20
|
+
self['subject'] || msg['subject']
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the msg Hash (as used for inbound messages )
|
24
|
+
def msg
|
25
|
+
self['msg']||{}
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the message_id (as used for inbound messages )
|
29
|
+
def message_id
|
30
|
+
headers['Message-Id']
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the reply-to ID (as used for inbound messages )
|
34
|
+
def in_reply_to
|
35
|
+
headers['In-Reply-To']
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns an array of reference IDs (as used for inbound messages )
|
39
|
+
def references
|
40
|
+
(headers['References']||'').scan(/(<[^<]+?>)/).flatten
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns the headers Hash (as used for inbound messages )
|
44
|
+
def headers
|
45
|
+
msg['headers']||{}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns the email (String) of the sender
|
49
|
+
def sender_email
|
50
|
+
msg['from_email']
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns an array of all unique recipient emails (to/cc)
|
54
|
+
# [ email, email, .. ]
|
55
|
+
def recipients
|
56
|
+
(Array(msg['to']) | Array(msg['cc'])).compact
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns an array of all unique recipients (to/cc)
|
60
|
+
# [ [email,name], [email,name], .. ]
|
61
|
+
def recipient_emails
|
62
|
+
recipients.map(&:first)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the +format+ (:text,:html,:raw) message body
|
66
|
+
def message_body(format=:text)
|
67
|
+
case format
|
68
|
+
when :text
|
69
|
+
msg['text']
|
70
|
+
when :html
|
71
|
+
msg['html']
|
72
|
+
when :raw
|
73
|
+
msg['raw_msg']
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Mandrill::WebHook::Processor
|
2
|
+
|
3
|
+
attr_accessor :mandrill_events, :callback_host
|
4
|
+
|
5
|
+
# Command initialise the processor with +params+ Hash.
|
6
|
+
# +params+ is expected to contain an array of mandrill_events
|
7
|
+
def initialize(params={})
|
8
|
+
@mandrill_events = JSON.parse(params['mandrill_events'] || '[]')
|
9
|
+
end
|
10
|
+
|
11
|
+
# Command: processes all +mandrill_events+
|
12
|
+
def run!
|
13
|
+
mandrill_events.each do |raw_payload|
|
14
|
+
event_payload = wrap_payload(raw_payload)
|
15
|
+
handler = "handle_#{event_payload.event_type}".to_sym
|
16
|
+
if callback_host && callback_host.respond_to?(handler)
|
17
|
+
callback_host.send(handler,event_payload)
|
18
|
+
elsif self.respond_to?(handler)
|
19
|
+
self.send(handler,event_payload)
|
20
|
+
else
|
21
|
+
# TODO raise an error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns a suitably ecapsulated +raw_event_payload+
|
27
|
+
def wrap_payload(raw_event_payload)
|
28
|
+
Mandrill::WebHook::EventDecorator[raw_event_payload]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/mandrill-rails/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Paul Gallagher"]
|
6
|
+
gem.email = ["gallagher.paul@gmail.com"]
|
7
|
+
gem.description = %q{Rails integration for working with Mandrill}
|
8
|
+
gem.summary = %q{Rails integration for working with Mandrill}
|
9
|
+
gem.homepage = "https://github.com/evendis/mandrill-rails"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "mandrill-rails"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Mandrill::Rails::VERSION
|
17
|
+
|
18
|
+
gem.add_runtime_dependency(%q<mandrill>, ["~> 0.0.2"])
|
19
|
+
gem.add_runtime_dependency(%q<activesupport>, [">= 3.0.3"])
|
20
|
+
gem.add_development_dependency(%q<bundler>, ["~> 1.1.0"])
|
21
|
+
gem.add_development_dependency(%q<rake>, ["~> 0.9.2.2"])
|
22
|
+
gem.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
|
23
|
+
gem.add_development_dependency(%q<rdoc>, ["~> 3.11"])
|
24
|
+
gem.add_development_dependency(%q<guard-rspec>, ["~> 1.2.0"])
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class WebHookProcessorTestHarness
|
4
|
+
def self.skip_before_filter(*args) ; end
|
5
|
+
def head(*args) ; end
|
6
|
+
attr_accessor :params
|
7
|
+
|
8
|
+
include Mandrill::Rails::WebHookProcessor
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Mandrill::Rails::WebHookProcessor do
|
12
|
+
let(:processor_instance) { WebHookProcessorTestHarness.new }
|
13
|
+
let(:params) { {} }
|
14
|
+
before { processor_instance.params = params}
|
15
|
+
|
16
|
+
subject { processor_instance }
|
17
|
+
|
18
|
+
describe "#show" do
|
19
|
+
it "should return head(:ok)" do
|
20
|
+
processor_instance.should_receive(:head).with(:ok)
|
21
|
+
processor_instance.show
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#create" do
|
26
|
+
it "should return head(:ok)" do
|
27
|
+
Mandrill::WebHook::Processor.any_instance.should_receive(:run!)
|
28
|
+
processor_instance.should_receive(:head).with(:ok)
|
29
|
+
processor_instance.create
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mandrill::WebHook::EventDecorator do
|
4
|
+
|
5
|
+
|
6
|
+
let(:event_payload) { Mandrill::WebHook::EventDecorator[raw_event] }
|
7
|
+
subject { event_payload }
|
8
|
+
|
9
|
+
context "with 'inbound' event_type" do
|
10
|
+
|
11
|
+
let(:event_type) { 'inbound' }
|
12
|
+
let(:subject_line) { 'a subject line' }
|
13
|
+
let(:sender_email) { 'test@example.com' }
|
14
|
+
let(:message_text) { "raw message text\n\n" }
|
15
|
+
let(:message_html) { "<div>some content</div>" }
|
16
|
+
let(:message_raw) { "the raw message text" }
|
17
|
+
let(:message_id) { "<111111>" }
|
18
|
+
let(:in_reply_to) { "<222222>" }
|
19
|
+
let(:references) { "<222222> <333333>" }
|
20
|
+
let(:references_array) { ["<222222>","<333333>"] }
|
21
|
+
|
22
|
+
let(:raw_event) { {
|
23
|
+
'event' => event_type,
|
24
|
+
'msg' => {
|
25
|
+
'from_email' => sender_email,
|
26
|
+
'subject' => subject_line,
|
27
|
+
'headers' => {
|
28
|
+
'Cc' => "c@example.com,b@example.com",
|
29
|
+
'Message-Id' => message_id,
|
30
|
+
'In-Reply-To' => in_reply_to,
|
31
|
+
'References' => references
|
32
|
+
},
|
33
|
+
'html' => message_html,
|
34
|
+
'raw_msg' => message_raw,
|
35
|
+
'text' => message_text,
|
36
|
+
'cc' => [ [ "c@example.com", "C"],[ "b@example.com", nil] ],
|
37
|
+
'to' => [ [ "a@example.com", "A"],[ "b@example.com", nil] ]
|
38
|
+
}
|
39
|
+
} }
|
40
|
+
|
41
|
+
its(:event_type) { should eql(event_type) }
|
42
|
+
its(:subject) { should eql(subject_line) }
|
43
|
+
its(:sender_email) { should eql(sender_email) }
|
44
|
+
its(:recipients) { should eql([["a@example.com", "A"], ["b@example.com", nil], ["c@example.com", "C"]]) }
|
45
|
+
its(:message_id) { should eql(message_id) }
|
46
|
+
its(:in_reply_to) { should eql(in_reply_to) }
|
47
|
+
|
48
|
+
describe "#references" do
|
49
|
+
its(:references) { should eql(references_array) }
|
50
|
+
context "when no references element" do
|
51
|
+
let(:raw_event) { {} }
|
52
|
+
its(:references) { should eql([]) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#recipient_emails" do
|
57
|
+
its(:recipient_emails) { should eql(["a@example.com", "b@example.com", "c@example.com"]) }
|
58
|
+
context "when no to or Cc elements" do
|
59
|
+
let(:raw_event) { {} }
|
60
|
+
its(:recipient_emails) { should eql([]) }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#message_body" do
|
65
|
+
subject { event_payload.message_body(format) }
|
66
|
+
describe ":text" do
|
67
|
+
let(:format) { :text }
|
68
|
+
it { should eql(message_text) }
|
69
|
+
end
|
70
|
+
describe ":html" do
|
71
|
+
let(:format) { :html }
|
72
|
+
it { should eql(message_html) }
|
73
|
+
end
|
74
|
+
describe ":raw" do
|
75
|
+
let(:format) { :raw }
|
76
|
+
it { should eql(message_raw) }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# TODO: elaborate specs for send web hook (need some real payload examples)
|
84
|
+
context "with 'send' event_type" do
|
85
|
+
let(:event_type) { 'send' }
|
86
|
+
let(:subject_line) { 'a subject line' }
|
87
|
+
let(:raw_event) { {
|
88
|
+
'event' => event_type,
|
89
|
+
'subject' => subject_line
|
90
|
+
} }
|
91
|
+
|
92
|
+
its(:event_type) { should eql(event_type) }
|
93
|
+
its(:subject) { should eql(subject_line) }
|
94
|
+
end
|
95
|
+
|
96
|
+
# TODO: other web hook types
|
97
|
+
# send - message has been sent
|
98
|
+
# hard_bounce - message has hard bounced
|
99
|
+
# soft_bounce - message has soft bounced
|
100
|
+
# open - recipient opened a message; will only occur when open tracking is enabled
|
101
|
+
# click - recipient clicked a link in a message; will only occur when click tracking is enabled
|
102
|
+
# spam - recipient marked a message as spam
|
103
|
+
# unsub - recipient unsubscribed
|
104
|
+
# reject - message was rejected
|
105
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mandrill::WebHook::Processor do
|
4
|
+
|
5
|
+
let(:params) { {} }
|
6
|
+
let(:processor) { Mandrill::WebHook::Processor.new(params) }
|
7
|
+
|
8
|
+
describe "#run!" do
|
9
|
+
context "with inbound events" do
|
10
|
+
before do
|
11
|
+
Mandrill::WebHook::Processor.stub(:handle_inbound)
|
12
|
+
end
|
13
|
+
let(:event1) { { "event" => "inbound" } }
|
14
|
+
let(:event2) { { "event" => "inbound" } }
|
15
|
+
let(:params) { { "mandrill_events" => [event1,event2].to_json } }
|
16
|
+
it "should pass event payload to the handler" do
|
17
|
+
processor.should_receive(:handle_inbound).twice
|
18
|
+
processor.run!
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#wrap_payload" do
|
24
|
+
let(:raw_payload) { {} }
|
25
|
+
subject { processor.wrap_payload(raw_payload) }
|
26
|
+
its(:class) { should eql(Mandrill::WebHook::EventDecorator) }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'mandrill-rails'
|
2
|
+
|
3
|
+
# Requires supporting files with custom matchers and macros, etc,
|
4
|
+
# in ./support/ and its subdirectories.
|
5
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
6
|
+
|
7
|
+
RSpec.configure do |config|
|
8
|
+
# == Mock Framework
|
9
|
+
#
|
10
|
+
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
|
11
|
+
#
|
12
|
+
# config.mock_with :mocha
|
13
|
+
# config.mock_with :flexmock
|
14
|
+
# config.mock_with :rr
|
15
|
+
config.mock_with :rspec
|
16
|
+
|
17
|
+
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
18
|
+
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
19
|
+
|
20
|
+
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
21
|
+
# examples within a transaction, remove the following line or assign false
|
22
|
+
# instead of true.
|
23
|
+
# config.use_transactional_fixtures = true
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mandrill-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Paul Gallagher
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mandrill
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.0.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.0.2
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: activesupport
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 3.0.3
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 3.0.3
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.1.0
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.1.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.9.2.2
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.2.2
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.8.0
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 2.8.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: rdoc
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '3.11'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '3.11'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: guard-rspec
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 1.2.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: 1.2.0
|
126
|
+
description: Rails integration for working with Mandrill
|
127
|
+
email:
|
128
|
+
- gallagher.paul@gmail.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- .gitignore
|
134
|
+
- .rspec
|
135
|
+
- .travis.yml
|
136
|
+
- Gemfile
|
137
|
+
- Guardfile
|
138
|
+
- LICENSE
|
139
|
+
- README.rdoc
|
140
|
+
- Rakefile
|
141
|
+
- lib/mandrill-rails.rb
|
142
|
+
- lib/mandrill-rails/version.rb
|
143
|
+
- lib/mandrill-rails/web_hook_processor.rb
|
144
|
+
- lib/mandrill/web_hook.rb
|
145
|
+
- lib/mandrill/web_hook/event_decorator.rb
|
146
|
+
- lib/mandrill/web_hook/processor.rb
|
147
|
+
- mandrill-rails.gemspec
|
148
|
+
- spec/mandrill-rails/web_hook_processor_spec.rb
|
149
|
+
- spec/mandrill/web_hook/event_decorator_spec.rb
|
150
|
+
- spec/mandrill/web_hook/processor_spec.rb
|
151
|
+
- spec/spec_helper.rb
|
152
|
+
homepage: https://github.com/evendis/mandrill-rails
|
153
|
+
licenses: []
|
154
|
+
post_install_message:
|
155
|
+
rdoc_options: []
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
none: false
|
160
|
+
requirements:
|
161
|
+
- - ! '>='
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
segments:
|
165
|
+
- 0
|
166
|
+
hash: 1652128042679890864
|
167
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
168
|
+
none: false
|
169
|
+
requirements:
|
170
|
+
- - ! '>='
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
segments:
|
174
|
+
- 0
|
175
|
+
hash: 1652128042679890864
|
176
|
+
requirements: []
|
177
|
+
rubyforge_project:
|
178
|
+
rubygems_version: 1.8.24
|
179
|
+
signing_key:
|
180
|
+
specification_version: 3
|
181
|
+
summary: Rails integration for working with Mandrill
|
182
|
+
test_files:
|
183
|
+
- spec/mandrill-rails/web_hook_processor_spec.rb
|
184
|
+
- spec/mandrill/web_hook/event_decorator_spec.rb
|
185
|
+
- spec/mandrill/web_hook/processor_spec.rb
|
186
|
+
- spec/spec_helper.rb
|