griddler-mandrill 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c2197b9fa59d9e6c1006d3083dd0563653ea5cda
4
+ data.tar.gz: 68d153dde2a5762904f4bc445d252f2b46c32a24
5
+ SHA512:
6
+ metadata.gz: 52aa06aaabeb9b813b737c3024f8187c799fd5b050b2c42908e31d6a44c4f1fb702039501047ed36b2abb6d2abb64f6c139a928234a1ebefa1c69c52d64933d6
7
+ data.tar.gz: 13979ab10338f143699a488afa39f92ea892e7fc2cc09a65b15a1e85c586798f1bec980c8c1b465c4359dd03c892d40c551a5149e9727dd017605e80ddf5e29d
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0
4
+ - 2.1
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,8 @@
1
+ ## Contributing
2
+
3
+ 1. Fork it ( https://github.com/[my-github-username]/griddler-mandrill/fork )
4
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
5
+ 3. Make your changes (with tests!)
6
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
7
+ 5. Push to the branch (`git push origin my-new-feature`)
8
+ 6. Create a new Pull Request
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'griddler', github: 'thoughtbot/griddler'
4
+
5
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Stafford Brunk
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.md ADDED
@@ -0,0 +1,41 @@
1
+ # Griddler::Mandrill
2
+ [![Build Status](http://img.shields.io/travis/wingrunr21/griddler-mandrill.svg?style=flat)](https://travis-ci.org/wingrunr21/griddler-mandrill)
3
+ [![Dependency Status](http://img.shields.io/gemnasium/wingrunr21/griddler-mandrill.svg?style=flat)](https://gemnasium.com/wingrunr21/griddler-mandrill)
4
+ [![Gem Version](http://img.shields.io/gem/v/griddler-mandrill.svg?style=flat)](https://rubygems.org/gems/griddler-mandrill)
5
+
6
+ This is an adapter that allows [Griddler](https://github.com/thoughtbot/griddler) to be used with [Mandrill's Inbound Email Processing](http://help.mandrill.com/entries/21699367-Inbound-Email-Processing-Overview).
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'griddler'
13
+ gem 'griddler-mandrill'
14
+
15
+
16
+ ## Usage
17
+
18
+ [thoughtbot](http://thoughtbot.com) has a blog post on how to use Griddler over on their blog: [Giant
19
+ Robots](http://robots.thoughtbot.com/handle-incoming-email-with-griddler).
20
+
21
+ ### Additional Setup
22
+
23
+ When adding a webhook in their administration panel, Mandrill will issue a HEAD
24
+ request to check if the webhook is valid (see [Adding Routes]). If the HEAD
25
+ request fails, Mandrill will not allow you to add the webhook. Since Griddler
26
+ is only configured to handle POST requests, you will not be able to add the
27
+ webhook as-is. To solve this, add a temporary route to your application that can
28
+ handle the HEAD request:
29
+
30
+ # config/routes.rb
31
+ get "/email_processor", to: proc { [200, {}, ["OK"]] }, as: "mandrill_head_test_request"
32
+
33
+ Once you have correctly configured Mandrill, you can go ahead and delete this code.
34
+
35
+ [Adding Routes]: http://help.mandrill.com/entries/21699367-Inbound-Email-Processing-Overview
36
+
37
+ ## Credits
38
+
39
+ Griddler::Mandrill was extracted from Griddler by [Stafford Brunk](https://github.com/wingrunr21).
40
+
41
+ Griddler was written by [Caleb Thompson](https://github.com/calebthompson) and [Joel Oliveira](https://github.com/jayroh).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ RSpec::Core::RakeTask.new(:spec)
4
+ task default: :spec
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'griddler/mandrill/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'griddler-mandrill'
8
+ spec.version = Griddler::Mandrill::VERSION
9
+ spec.authors = ['Stafford Brunk']
10
+ spec.email = ['stafford.brunk@gmail.com']
11
+ spec.summary = %q{Mandrill adapter for Griddler}
12
+ spec.description = %q{Adapter to allow the use of Mandrill's Inboud Email Processing with Griddler}
13
+ spec.homepage = 'https://github.com/wingrunr21/griddler-mandrill'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'griddler'
22
+
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'activesupport'
26
+ end
@@ -0,0 +1,71 @@
1
+ module Griddler
2
+ module Mandrill
3
+ class Adapter
4
+ def initialize(params)
5
+ @params = params
6
+ end
7
+
8
+ def self.normalize_params(params)
9
+ adapter = new(params)
10
+ adapter.normalize_params
11
+ end
12
+
13
+ def normalize_params
14
+ events.map do |event|
15
+ {
16
+ to: recipients(:to, event),
17
+ cc: recipients(:cc, event),
18
+ from: full_email([ event[:from_email], event[:from_name] ]),
19
+ subject: event[:subject],
20
+ text: event.fetch(:text, ''),
21
+ html: event.fetch(:html, ''),
22
+ raw_body: event[:raw_msg],
23
+ attachments: attachment_files(event)
24
+ }
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :params
31
+
32
+ def events
33
+ @events ||= ActiveSupport::JSON.decode(params[:mandrill_events]).map do |event|
34
+ event['msg'].with_indifferent_access
35
+ end
36
+ end
37
+
38
+ def recipients(field, event)
39
+ Array.wrap(event[field]).map { |recipient| full_email(recipient) }
40
+ end
41
+
42
+ def full_email(contact_info)
43
+ email = contact_info[0]
44
+ if contact_info[1]
45
+ "#{contact_info[1]} <#{email}>"
46
+ else
47
+ email
48
+ end
49
+ end
50
+
51
+ def attachment_files(event)
52
+ attachments = event[:attachments] || Array.new
53
+ attachments.map do |key, attachment|
54
+ ActionDispatch::Http::UploadedFile.new({
55
+ filename: attachment[:name],
56
+ type: attachment[:type],
57
+ tempfile: create_tempfile(attachment)
58
+ })
59
+ end
60
+ end
61
+
62
+ def create_tempfile(attachment)
63
+ filename = attachment[:name]
64
+ tempfile = Tempfile.new(filename, Dir::tmpdir, encoding: 'ascii-8bit')
65
+ tempfile.write(Base64.decode64(attachment[:content]))
66
+ tempfile.rewind
67
+ tempfile
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,5 @@
1
+ module Griddler
2
+ module Mandrill
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'griddler'
2
+ require 'griddler/mandrill/version'
3
+ require 'griddler/mandrill/adapter'
4
+
5
+ Griddler.adapter_registry.register(:mandrill, Griddler::Mandrill::Adapter)
@@ -0,0 +1,183 @@
1
+ require 'spec_helper'
2
+
3
+ describe Griddler::Mandrill::Adapter do
4
+ it 'registers itself with griddler' do
5
+ expect(Griddler.adapter_registry[:mandrill]).to eq Griddler::Mandrill::Adapter
6
+ end
7
+ end
8
+
9
+ describe Griddler::Mandrill::Adapter, '.normalize_params' do
10
+ it 'normalizes parameters' do
11
+ Griddler::Mandrill::Adapter.normalize_params(default_params).each do |params|
12
+ expect(params).to be_normalized_to({
13
+ to: ['The Token <token@reply.example.com>'],
14
+ cc: ['Emily <emily@example.mandrillapp.com>',
15
+ 'Joey <joey@example.mandrillapp.com>'],
16
+ from: 'Hernan Example <hernan@example.com>',
17
+ subject: 'hello',
18
+ text: %r{Dear bob},
19
+ html: %r{<p>Dear bob</p>},
20
+ raw_body: %r{raw}
21
+ })
22
+ end
23
+ end
24
+
25
+ it 'passes the received array of files' do
26
+ params = params_with_attachments
27
+
28
+ normalized_params = Griddler::Mandrill::Adapter.normalize_params(params)
29
+
30
+ first, second = *normalized_params[0][:attachments]
31
+
32
+ expect(first.original_filename).to eq('photo1.jpg')
33
+ expect(first.size).to eq(upload_1_params[:length])
34
+
35
+ expect(second.original_filename).to eq('photo2.jpg')
36
+ expect(second.size).to eq(upload_2_params[:length])
37
+ end
38
+
39
+ it 'has no attachments' do
40
+ params = default_params
41
+
42
+ normalized_params = Griddler::Mandrill::Adapter.normalize_params(params)
43
+
44
+ expect(normalized_params[0][:attachments]).to be_empty
45
+ end
46
+
47
+ describe 'when the email has no text part' do
48
+ before do
49
+ @params = params_hash
50
+ @params.first[:msg].delete(:text)
51
+ end
52
+
53
+ it 'sets :text to an empty string' do
54
+ params = default_params(@params)
55
+ normalized_params = Griddler::Mandrill::Adapter.normalize_params(params)
56
+ normalized_params.each do |p|
57
+ expect(p[:text]).to eq ''
58
+ end
59
+ end
60
+ end
61
+
62
+ describe 'when the email has no html part' do
63
+ before do
64
+ @params = params_hash
65
+ @params.first[:msg].delete(:html)
66
+ end
67
+
68
+ it 'sets :html to an empty string' do
69
+ params = default_params(@params)
70
+ normalized_params = Griddler::Mandrill::Adapter.normalize_params(params)
71
+ normalized_params.each do |p|
72
+ expect(p[:html]).to eq ''
73
+ end
74
+ end
75
+ end
76
+
77
+ describe 'when the email has no CC recipients' do
78
+ before do
79
+ @params = params_hash
80
+ @params.first[:msg][:cc] = nil
81
+ end
82
+
83
+ it 'should return an empty cc array' do
84
+ params = default_params(@params)
85
+ normalized_params = Griddler::Mandrill::Adapter.normalize_params(params)
86
+ normalized_params.each do |p|
87
+ expect(p[:cc]).to eq []
88
+ end
89
+ end
90
+ end
91
+
92
+ def default_params(params = params_hash)
93
+ mandrill_events (params * 2).to_json
94
+ end
95
+
96
+ def mandrill_events(json)
97
+ { mandrill_events: json }
98
+ end
99
+
100
+ def params_hash
101
+ [{
102
+ event: 'inbound',
103
+ ts: 1364601140,
104
+ msg:
105
+ {
106
+ raw_msg: 'raw',
107
+ headers: {},
108
+ text: text_body,
109
+ html: text_html,
110
+ from_email: 'hernan@example.com',
111
+ from_name: 'Hernan Example',
112
+ to: [['token@reply.example.com', 'The Token']],
113
+ cc: [['emily@example.mandrillapp.com', 'Emily'],
114
+ ['joey@example.mandrillapp.com', 'Joey']],
115
+ subject: "hello",
116
+ spam_report: {
117
+ score: -0.8,
118
+ matched_rules: '...'
119
+ },
120
+ dkim: { signed: true, valid: true },
121
+ spf: { result: 'pass', detail: 'sender SPF authorized' },
122
+ email: 'token@reply.example.com',
123
+ tags: [],
124
+ sender: nil
125
+ }
126
+ }]
127
+ end
128
+
129
+ def params_with_attachments
130
+ params = params_hash
131
+ params[0][:msg][:attachments] = {
132
+ 'photo1.jpg' => upload_1_params,
133
+ 'photo2.jpg' => upload_2_params
134
+ }
135
+ mandrill_events params.to_json
136
+ end
137
+
138
+ def text_body
139
+ <<-EOS.strip_heredoc.strip
140
+ Dear bob
141
+
142
+ Reply ABOVE THIS LINE
143
+
144
+ hey sup
145
+ EOS
146
+ end
147
+
148
+ def text_html
149
+ <<-EOS.strip_heredoc.strip
150
+ <p>Dear bob</p>
151
+
152
+ Reply ABOVE THIS LINE
153
+
154
+ hey sup
155
+ EOS
156
+ end
157
+
158
+ def upload_1_params
159
+ @upload_1_params ||= begin
160
+ file = upload_1
161
+ size = file.size
162
+ {
163
+ name: 'photo1.jpg',
164
+ content: Base64.encode64(file.read),
165
+ type: 'image/jpeg',
166
+ length: size
167
+ }
168
+ end
169
+ end
170
+
171
+ def upload_2_params
172
+ @upload_2_params ||= begin
173
+ file = upload_2
174
+ size = file.size
175
+ {
176
+ name: 'photo2.jpg',
177
+ content: Base64.encode64(file.read),
178
+ type: 'image/jpeg',
179
+ length: size
180
+ }
181
+ end
182
+ end
183
+ end
@@ -0,0 +1,35 @@
1
+ require 'griddler/testing'
2
+ require 'griddler/mandrill'
3
+ require 'action_dispatch'
4
+ require 'active_support/core_ext/string'
5
+ require 'active_support/core_ext/hash'
6
+
7
+ RSpec.configure do |config|
8
+ config.run_all_when_everything_filtered = true
9
+ config.order = 'random'
10
+ config.include Griddler::Testing
11
+ end
12
+
13
+ RSpec::Matchers.define :be_normalized_to do |expected|
14
+ failure_message do |actual|
15
+ message = ""
16
+ expected.each do |k, v|
17
+ message << "expected :#{k} to be normalized to #{expected[k].inspect}, "\
18
+ "but received #{actual[k].inspect}\n" unless actual[k] == expected[k]
19
+ end
20
+ message
21
+ end
22
+
23
+ description do
24
+ "be normalized to #{expected}"
25
+ end
26
+
27
+ match do |actual|
28
+ expected.each do |k, v|
29
+ case v
30
+ when Regexp then expect(actual[k]).to match v
31
+ else expect(actual[k]).to eq v
32
+ end
33
+ end
34
+ end
35
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: griddler-mandrill
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Stafford Brunk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: griddler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Adapter to allow the use of Mandrill's Inboud Email Processing with Griddler
70
+ email:
71
+ - stafford.brunk@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - CONTRIBUTING.md
80
+ - Gemfile
81
+ - LICENSE.txt
82
+ - README.md
83
+ - Rakefile
84
+ - griddler-mandrill.gemspec
85
+ - lib/griddler/mandrill.rb
86
+ - lib/griddler/mandrill/adapter.rb
87
+ - lib/griddler/mandrill/version.rb
88
+ - spec/griddler/mandrill/adapter_spec.rb
89
+ - spec/spec_helper.rb
90
+ homepage: https://github.com/wingrunr21/griddler-mandrill
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.2.2
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Mandrill adapter for Griddler
114
+ test_files:
115
+ - spec/griddler/mandrill/adapter_spec.rb
116
+ - spec/spec_helper.rb