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 +4 -4
- data/README.md +63 -6
- data/Rakefile +1 -0
- data/app/controllers/griddler/emails_controller.rb +4 -2
- data/lib/griddler.rb +1 -0
- data/lib/griddler/adapters/cloudmailin_adapter.rb +1 -1
- data/lib/griddler/adapters/mandrill_adapter.rb +70 -0
- data/lib/griddler/adapters/postmark_adapter.rb +5 -1
- data/lib/griddler/adapters/sendgrid_adapter.rb +8 -2
- data/lib/griddler/configuration.rb +14 -2
- data/lib/griddler/email.rb +9 -3
- data/lib/griddler/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3573025fb9bfe09cc1746e637a3992d7349d58e5
|
4
|
+
data.tar.gz: 1c818804c1f63e95613531fc79afba41c5964213
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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)
|
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 # :
|
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 `:
|
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
|
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
|
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,12 +1,14 @@
|
|
1
1
|
class Griddler::EmailsController < ActionController::Base
|
2
2
|
def create
|
3
|
-
|
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
@@ -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:
|
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
|
15
|
-
|
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
|
19
|
+
attr_accessor :processor_class, :reply_delimiter
|
20
20
|
|
21
21
|
def to
|
22
|
-
@to ||= :
|
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
|
data/lib/griddler/email.rb
CHANGED
@@ -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 =
|
12
|
+
@to = recipients
|
13
13
|
@from = extract_address(params[:from], :email)
|
14
14
|
@subject = params[:subject]
|
15
15
|
|
16
16
|
@body = extract_body
|
17
|
-
@
|
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
|
|
data/lib/griddler/version.rb
CHANGED
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
|
+
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-
|
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
|