griddler-mandrill-acd 1.0.1

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: c112ade322f6f6a3b4ac4a9c906a9bc7030b0435
4
+ data.tar.gz: d2affb4fd46b507434d537a03cccbd35fa534bbf
5
+ SHA512:
6
+ metadata.gz: 5ed3d770cd64c3cc7efce7e64b828e1d8c50d670b493627794a5436b6e4d99f556c4e1041e2da375559d2e96f869959a27202e1633d9b2ac002bcf0eb7029636
7
+ data.tar.gz: 9caafc8bfb5442979470ce01f2aedff13c2558815fb72b33c38afa2a542380a00e91b08302297842b98df5c41eb17a282a62f3dd2e6fa00a3ea39e6294891c5d
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/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ ## 1.0.1
2
+ * Respect Mandrill's base64 flag to determine whether text attachments should be
3
+ base64 decoded. #4 via [bdmac](https://github.com/bdmac)
4
+
5
+ ## 1.0.0
6
+ * Initial extraction of the Mandrill adapter from griddler
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-acd'
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-acd'
22
+
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'activesupport'
26
+ end
@@ -0,0 +1,73 @@
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
+ content = attachment[:content]
66
+ content = Base64.decode64(content) if attachment[:base64]
67
+ tempfile.write(content)
68
+ tempfile.rewind
69
+ tempfile
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,5 @@
1
+ module Griddler
2
+ module Mandrill
3
+ VERSION = '1.0.1'
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,217 @@
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
+ it 'works with non-base64 encoded files' do
48
+ params = params_with_csv_attachment
49
+
50
+ normalized_params = Griddler::Mandrill::Adapter.normalize_params(params)
51
+
52
+ file, = *normalized_params[0][:attachments]
53
+
54
+ expect(file.original_filename).to eq('file.csv')
55
+ expect(file.size).to eq(upload_3_params[:length])
56
+ end
57
+
58
+ describe 'when the email has no text part' do
59
+ before do
60
+ @params = params_hash
61
+ @params.first[:msg].delete(:text)
62
+ end
63
+
64
+ it 'sets :text to an empty string' do
65
+ params = default_params(@params)
66
+ normalized_params = Griddler::Mandrill::Adapter.normalize_params(params)
67
+ normalized_params.each do |p|
68
+ expect(p[:text]).to eq ''
69
+ end
70
+ end
71
+ end
72
+
73
+ describe 'when the email has no html part' do
74
+ before do
75
+ @params = params_hash
76
+ @params.first[:msg].delete(:html)
77
+ end
78
+
79
+ it 'sets :html to an empty string' do
80
+ params = default_params(@params)
81
+ normalized_params = Griddler::Mandrill::Adapter.normalize_params(params)
82
+ normalized_params.each do |p|
83
+ expect(p[:html]).to eq ''
84
+ end
85
+ end
86
+ end
87
+
88
+ describe 'when the email has no CC recipients' do
89
+ before do
90
+ @params = params_hash
91
+ @params.first[:msg][:cc] = nil
92
+ end
93
+
94
+ it 'should return an empty cc array' do
95
+ params = default_params(@params)
96
+ normalized_params = Griddler::Mandrill::Adapter.normalize_params(params)
97
+ normalized_params.each do |p|
98
+ expect(p[:cc]).to eq []
99
+ end
100
+ end
101
+ end
102
+
103
+ def default_params(params = params_hash)
104
+ mandrill_events (params * 2).to_json
105
+ end
106
+
107
+ def mandrill_events(json)
108
+ { mandrill_events: json }
109
+ end
110
+
111
+ def params_hash
112
+ [{
113
+ event: 'inbound',
114
+ ts: 1364601140,
115
+ msg:
116
+ {
117
+ raw_msg: 'raw',
118
+ headers: {},
119
+ text: text_body,
120
+ html: text_html,
121
+ from_email: 'hernan@example.com',
122
+ from_name: 'Hernan Example',
123
+ to: [['token@reply.example.com', 'The Token']],
124
+ cc: [['emily@example.mandrillapp.com', 'Emily'],
125
+ ['joey@example.mandrillapp.com', 'Joey']],
126
+ subject: "hello",
127
+ spam_report: {
128
+ score: -0.8,
129
+ matched_rules: '...'
130
+ },
131
+ dkim: { signed: true, valid: true },
132
+ spf: { result: 'pass', detail: 'sender SPF authorized' },
133
+ email: 'token@reply.example.com',
134
+ tags: [],
135
+ sender: nil
136
+ }
137
+ }]
138
+ end
139
+
140
+ def params_with_attachments
141
+ params = params_hash
142
+ params[0][:msg][:attachments] = {
143
+ 'photo1.jpg' => upload_1_params,
144
+ 'photo2.jpg' => upload_2_params
145
+ }
146
+ mandrill_events params.to_json
147
+ end
148
+
149
+ def params_with_csv_attachment
150
+ params = params_hash
151
+ params[0][:msg][:attachments] = {
152
+ 'file.csv' => upload_3_params
153
+ }
154
+ mandrill_events params.to_json
155
+ end
156
+
157
+ def text_body
158
+ <<-EOS.strip_heredoc.strip
159
+ Dear bob
160
+
161
+ Reply ABOVE THIS LINE
162
+
163
+ hey sup
164
+ EOS
165
+ end
166
+
167
+ def text_html
168
+ <<-EOS.strip_heredoc.strip
169
+ <p>Dear bob</p>
170
+
171
+ Reply ABOVE THIS LINE
172
+
173
+ hey sup
174
+ EOS
175
+ end
176
+
177
+ def upload_1_params
178
+ @upload_1_params ||= begin
179
+ file = upload_1
180
+ size = file.size
181
+ {
182
+ name: 'photo1.jpg',
183
+ content: Base64.encode64(file.read),
184
+ type: 'image/jpeg',
185
+ length: size,
186
+ base64: true
187
+ }
188
+ end
189
+ end
190
+
191
+ def upload_2_params
192
+ @upload_2_params ||= begin
193
+ file = upload_2
194
+ size = file.size
195
+ {
196
+ name: 'photo2.jpg',
197
+ content: Base64.encode64(file.read),
198
+ type: 'image/jpeg',
199
+ length: size,
200
+ base64: true
201
+ }
202
+ end
203
+ end
204
+
205
+ def upload_3_params
206
+ @upload_2_params ||= begin
207
+ content = 'Some | csv | file | here'
208
+ {
209
+ name: 'file.csv',
210
+ content: content,
211
+ type: 'text/plain',
212
+ length: content.length,
213
+ base64: false
214
+ }
215
+ end
216
+ end
217
+ 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,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: griddler-mandrill-acd
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Stafford Brunk
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: griddler-acd
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
+ - CHANGELOG.md
80
+ - CONTRIBUTING.md
81
+ - Gemfile
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - griddler-mandrill.gemspec
86
+ - lib/griddler/mandrill.rb
87
+ - lib/griddler/mandrill/adapter.rb
88
+ - lib/griddler/mandrill/version.rb
89
+ - spec/griddler/mandrill/adapter_spec.rb
90
+ - spec/spec_helper.rb
91
+ homepage: https://github.com/wingrunr21/griddler-mandrill
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.3.0
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Mandrill adapter for Griddler
115
+ test_files:
116
+ - spec/griddler/mandrill/adapter_spec.rb
117
+ - spec/spec_helper.rb
118
+ has_rdoc: