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 +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
|