griddler 0.4.1 → 0.5.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
  SHA1:
3
- metadata.gz: 25118b339d00976897148f6999e07b31a7b430e5
4
- data.tar.gz: 10c89b94dd65253620018490b1b84290885ee9b1
3
+ metadata.gz: 3573025fb9bfe09cc1746e637a3992d7349d58e5
4
+ data.tar.gz: 1c818804c1f63e95613531fc79afba41c5964213
5
5
  SHA512:
6
- metadata.gz: d33d3fac3fdad15c1ee4b1aa957fa667f52d5aad4c17f5aa7572b0199c33598a283689837192f9373faff4dd32b1ac951e8fceda4db7de27ed530d5da946806c
7
- data.tar.gz: dd09ef830ab90a1e6cebbef4cefc744cb0ae94a1a21cf644ad6a93b3052a667b05683045202a607a8117caa7cb94a3b2efd6b43a7e06b8b194d6c082237b1188
6
+ metadata.gz: c3c628a41d84ee8f0319b0d4016916c60f50b42e97b0358a5772bd79301d67b132b8712525f18aca403b1e6b9636fe28aef1f2d629a1f7c3da969b2ce1e1d19d
7
+ data.tar.gz: 951ecc70b7cf18c8b8ef81b303098ff5139a64f15c7fa0c8b70d0d631a44f86b59478c031881b6e1b957ab8e44b07114840a3687a470c14666051f6e0b9470d2
data/README.md CHANGED
@@ -8,8 +8,9 @@ Griddler
8
8
 
9
9
  Griddler is a Rails engine (full plugin) that provides an endpoint for the
10
10
  [SendGrid parse api](http://sendgrid.com/docs/API%20Reference/Webhooks/parse.html),
11
- [Cloudmailin parse api](http://cloudmailin.com) or
12
- [Postmark parse api](http://developer.postmarkapp.com/developer-inbound-parse.html)
11
+ [Cloudmailin parse api](http://cloudmailin.com),
12
+ [Postmark parse api](http://developer.postmarkapp.com/developer-inbound-parse.html) or
13
+ [Mandrill parse api](http://help.mandrill.com/entries/21699367-Inbound-Email-Processing-Overview)
13
14
  that hands off a built email object to a class implemented by you.
14
15
 
15
16
  Tutorials
@@ -62,6 +63,8 @@ that responds to:
62
63
  * `.from`
63
64
  * `.subject`
64
65
  * `.body`
66
+ * `.raw_text`
67
+ * `.raw_html`
65
68
  * `.raw_body`
66
69
  * `.attachments`
67
70
  * `.headers`
@@ -95,7 +98,7 @@ are shown below with sample overrides following. In `config/initializer/griddler
95
98
  ```ruby
96
99
  Griddler.configure do |config|
97
100
  config.processor_class = EmailProcessor # MyEmailProcessor
98
- config.to = :token # :raw, :email, :hash
101
+ config.to = :token # :full, :email, :hash
99
102
  # :raw => 'AppName <s13.6b2d13dc6a1d33db7644@mail.myapp.com>'
100
103
  # :email => 's13.6b2d13dc6a1d33db7644@mail.myapp.com'
101
104
  # :token => 's13.6b2d13dc6a1d33db7644'
@@ -111,18 +114,19 @@ end
111
114
  the email object. `:hash` will return all options within a -- (surprise!) -- hash.
112
115
  * `config.email_service` tells Griddler which email service you are using. The supported
113
116
  email service options are `:sendgrid` (the default), `:cloudmailin` (expects
114
- multipart format) and `:postmark`.
117
+ multipart format), `:postmark` and `:mandrill`.
115
118
 
116
119
  Testing In Your App
117
120
  -------------------
118
121
 
119
122
  You may want to create a factory for when testing the integration of Griddler into
120
- your application. If you're using factory_girl this can be accomplished with the
123
+ your application. If you're using factory\_girl this can be accomplished with the
121
124
  following sample factory.
122
125
 
123
126
  ```ruby
124
127
  factory :email, class: OpenStruct do
125
- to 'email-token'
128
+ # Assumes Griddler.configure.to is :hash (default)
129
+ to [{ raw: 'to_user@email.com', email: 'to_user@email.com', token: 'to_user', host: 'email.com' }]
126
130
  from 'user@email.com'
127
131
  subject 'email subject'
128
132
  body 'Hello!'
@@ -164,6 +168,57 @@ of your adapter returns a hash with these keys:
164
168
  * `:charsets` (optional) A JSON string containing the character sets of the
165
169
  fields extracted from the message
166
170
 
171
+ Upgrading to Griddler 0.5.0
172
+ ---------------------------
173
+
174
+ Because of an issue with the way Griddler handled recipients in the `To` header,
175
+ a breaking change was introduced in Griddler 0.5.0 that requires a minor change
176
+ to `EmailProcessor` or `processor_class`.
177
+
178
+ Previously, a single address was returned from `Griddler::Email#to`. Moving
179
+ forward, this field will always be an array. Generally speaking, you will want
180
+ to do something like this to handle the change:
181
+
182
+ ```ruby
183
+ # before
184
+ def initialize(email)
185
+ @to = email.to
186
+ @from = email.from
187
+ @body = email.body
188
+ end
189
+
190
+ # after
191
+ def initialize(email)
192
+ @to = pick_meaningful_recipient(email.to)
193
+ @from = email.from
194
+ @body = email.body
195
+ end
196
+
197
+ private
198
+
199
+ def pick_meaningful_recipient(recipients)
200
+ recipients.find { |address| address =~ /@mydomain.com$/ }
201
+ end
202
+ ```
203
+
204
+ Using Griddler with Mandrill
205
+ ----------------------------
206
+
207
+ When adding a webhook in their administration panel, Mandrill will issue a HEAD
208
+ request to check if the webhook is valid (see
209
+ [Adding Routes](http://help.mandrill.com/entries/21699367-Inbound-Email-Processing-Overview)).
210
+ If the HEAD request fails, Mandrill will not allow you to add the webhook.
211
+ Since Griddler is only configured to handle POST requests, you will not be able
212
+ to add the webhook as-is. To solve this, add a temporary route to your
213
+ application that can handle the HEAD request:
214
+
215
+ ```ruby
216
+ # routes.rb
217
+ get '/email_processor', :to => proc { [200, {}, ["OK"]] }
218
+ ```
219
+
220
+ Once you have correctly configured Mandrill, you can go ahead and delete this code.
221
+
167
222
  More Information
168
223
  ----------------
169
224
 
@@ -173,6 +228,8 @@ More Information
173
228
  * [Cloudmailin Docs](http://docs.cloudmailin.com/)
174
229
  * [Postmark](http://postmarkapp.com)
175
230
  * [Postmark Docs](http://developer.postmarkapp.com/)
231
+ * [Mandrill](http://mandrill.com)
232
+ * [Mandrill Docs](http://help.mandrill.com/forums/21092258-Inbound-Email-Processing)
176
233
 
177
234
  Credits
178
235
  -------
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env rake
2
2
  begin
3
3
  require 'bundler/setup'
4
+ require 'bundler/gem_tasks'
4
5
  rescue LoadError
5
6
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
7
  end
@@ -1,12 +1,14 @@
1
1
  class Griddler::EmailsController < ActionController::Base
2
2
  def create
3
- Griddler::Email.new(normalized_params).process
3
+ normalized_params.each do |p|
4
+ Griddler::Email.new(p).process
5
+ end
4
6
  head :ok
5
7
  end
6
8
 
7
9
  private
8
10
 
9
11
  def normalized_params
10
- Griddler.configuration.email_service.normalize_params(params)
12
+ Array.wrap(Griddler.configuration.email_service.normalize_params(params))
11
13
  end
12
14
  end
data/lib/griddler.rb CHANGED
@@ -8,6 +8,7 @@ require 'griddler/configuration'
8
8
  require 'griddler/adapters/sendgrid_adapter'
9
9
  require 'griddler/adapters/cloudmailin_adapter'
10
10
  require 'griddler/adapters/postmark_adapter'
11
+ require 'griddler/adapters/mandrill_adapter'
11
12
 
12
13
  module Griddler
13
14
  end
@@ -12,7 +12,7 @@ module Griddler
12
12
 
13
13
  def normalize_params
14
14
  {
15
- to: params[:envelope][:to],
15
+ to: params[:envelope][:to].split(','),
16
16
  from: params[:envelope][:from],
17
17
  subject: params[:headers][:Subject],
18
18
  text: params[:plain],
@@ -0,0 +1,70 @@
1
+ module Griddler
2
+ module Adapters
3
+ class MandrillAdapter
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(event),
17
+ from: event[:from_email],
18
+ subject: event[:subject],
19
+ text: event[:text],
20
+ html: event[:html],
21
+ raw_body: event[:raw_msg],
22
+ attachments: attachment_files(event)
23
+ }
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :params
30
+
31
+ def events
32
+ @events ||= ActiveSupport::JSON.decode(params[:mandrill_events]).map do |event|
33
+ event['msg'].with_indifferent_access
34
+ end
35
+ end
36
+
37
+ def recipients(event)
38
+ event[:to].map { |recipient| full_email(recipient) }
39
+ end
40
+
41
+ def full_email(contact_info)
42
+ email = contact_info[0]
43
+ if contact_info[1]
44
+ "#{contact_info[1]} <#{email}>"
45
+ else
46
+ email
47
+ end
48
+ end
49
+
50
+ def attachment_files(event)
51
+ attachments = event[:attachments] || Array.new
52
+ attachments.map do |key, attachment|
53
+ ActionDispatch::Http::UploadedFile.new({
54
+ filename: attachment[:name],
55
+ type: attachment[:type],
56
+ tempfile: create_tempfile(attachment)
57
+ })
58
+ end
59
+ end
60
+
61
+ def create_tempfile(attachment)
62
+ filename = attachment[:name]
63
+ tempfile = Tempfile.new(filename, Dir::tmpdir, encoding: 'ascii-8bit')
64
+ tempfile.write(Base64.decode64(attachment[:content]))
65
+ tempfile.rewind
66
+ tempfile
67
+ end
68
+ end
69
+ end
70
+ end
@@ -12,7 +12,7 @@ module Griddler
12
12
 
13
13
  def normalize_params
14
14
  {
15
- to: full_email(params[:ToFull].first),
15
+ to: extract_recipients,
16
16
  from: params[:FromFull][:Email],
17
17
  subject: params[:Subject],
18
18
  text: params[:TextBody],
@@ -25,6 +25,10 @@ module Griddler
25
25
 
26
26
  attr_reader :params
27
27
 
28
+ def extract_recipients
29
+ params[:ToFull].map { |recipient| full_email(recipient) }
30
+ end
31
+
28
32
  def full_email(contact_info)
29
33
  email = contact_info[:Email]
30
34
  if contact_info[:Name].present?
@@ -11,14 +11,20 @@ module Griddler
11
11
  end
12
12
 
13
13
  def normalize_params
14
- params[:attachments] = attachment_files
15
- params
14
+ params.merge(
15
+ to: recipients,
16
+ attachments: attachment_files,
17
+ )
16
18
  end
17
19
 
18
20
  private
19
21
 
20
22
  attr_reader :params
21
23
 
24
+ def recipients
25
+ params[:to].split(',')
26
+ end
27
+
22
28
  def attachment_files
23
29
  params.delete('attachment-info')
24
30
  attachment_count = params[:attachments].to_i
@@ -16,10 +16,21 @@ module Griddler
16
16
  end
17
17
 
18
18
  class Configuration
19
- attr_accessor :processor_class, :reply_delimiter, :to
19
+ attr_accessor :processor_class, :reply_delimiter
20
20
 
21
21
  def to
22
- @to ||= :token
22
+ @to ||= :hash
23
+ end
24
+
25
+ def to=(type)
26
+ if type == :token
27
+ Kernel.warn <<-WARN.strip_heredoc
28
+ [Deprecation] the :token option is deprecated and will be removed in v0.6.
29
+ For tokens use :hash and retrieve the token from email.to[:token] or choose any of [:email, :full, :hash]
30
+ WARN
31
+ end
32
+
33
+ @to = type
23
34
  end
24
35
 
25
36
  def processor_class
@@ -45,6 +56,7 @@ module Griddler
45
56
  sendgrid: Griddler::Adapters::SendgridAdapter,
46
57
  cloudmailin: Griddler::Adapters::CloudmailinAdapter,
47
58
  postmark: Griddler::Adapters::PostmarkAdapter,
59
+ mandrill: Griddler::Adapters::MandrillAdapter,
48
60
  }
49
61
  end
50
62
  end
@@ -3,18 +3,20 @@ require 'htmlentities'
3
3
  module Griddler
4
4
  class Email
5
5
  include ActionView::Helpers::SanitizeHelper
6
- attr_reader :to, :from, :subject, :body, :raw_body,
6
+ attr_reader :to, :from, :subject, :body, :raw_body, :raw_text, :raw_html,
7
7
  :headers, :raw_headers, :attachments
8
8
 
9
9
  def initialize(params)
10
10
  @params = params
11
11
 
12
- @to = extract_address(params[:to], config.to)
12
+ @to = recipients
13
13
  @from = extract_address(params[:from], :email)
14
14
  @subject = params[:subject]
15
15
 
16
16
  @body = extract_body
17
- @raw_body = params[:text] || params[:html]
17
+ @raw_text = params[:text]
18
+ @raw_html = params[:html]
19
+ @raw_body = @raw_text || @raw_html
18
20
 
19
21
  @headers = extract_headers
20
22
  @raw_headers = params[:headers]
@@ -35,6 +37,10 @@ module Griddler
35
37
  Griddler.configuration
36
38
  end
37
39
 
40
+ def recipients
41
+ params[:to].map { |recipient| extract_address(recipient, config.to) }
42
+ end
43
+
38
44
  def extract_address(address, type)
39
45
  parsed = EmailParser.parse_address(address)
40
46
 
@@ -1,3 +1,3 @@
1
1
  module Griddler
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: griddler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Caleb Thompson
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-03-26 00:00:00.000000000 Z
14
+ date: 2013-04-21 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -96,6 +96,7 @@ files:
96
96
  - config/initializers/griddler.rb
97
97
  - config/routes.rb
98
98
  - lib/griddler/adapters/cloudmailin_adapter.rb
99
+ - lib/griddler/adapters/mandrill_adapter.rb
99
100
  - lib/griddler/adapters/postmark_adapter.rb
100
101
  - lib/griddler/adapters/sendgrid_adapter.rb
101
102
  - lib/griddler/configuration.rb
@@ -112,7 +113,10 @@ files:
112
113
  homepage: http://thoughtbot.com
113
114
  licenses: []
114
115
  metadata: {}
115
- post_install_message:
116
+ post_install_message: |
117
+ When upgrading from a Griddler version previous to 0.5.0, it is important that
118
+ you view https://github.com/thoughtbot/griddler/#upgrading-to-griddler-050 for
119
+ upgrade information.
116
120
  rdoc_options: []
117
121
  require_paths:
118
122
  - app