griddler 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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