griddler 0.6.1 → 0.6.3
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 +26 -13
- data/lib/griddler.rb +1 -0
- data/lib/griddler/adapters/cloudmailin_adapter.rb +5 -0
- data/lib/griddler/adapters/mailgun_adapter.rb +57 -0
- data/lib/griddler/adapters/mandrill_adapter.rb +7 -1
- data/lib/griddler/adapters/postmark_adapter.rb +4 -3
- data/lib/griddler/adapters/sendgrid_adapter.rb +4 -3
- data/lib/griddler/configuration.rb +10 -1
- data/lib/griddler/email.rb +24 -25
- data/lib/griddler/email_parser.rb +4 -2
- data/lib/griddler/version.rb +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c93ac0eaccf2bf366151a3d202d31fb80c955e3a
|
4
|
+
data.tar.gz: 7966242ad3ac5d8566b8ed991b3b1118f266d88d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42e335e21700230465f2f60b9148cb0bd7188c5b99c86421d8bb06d3e34f8c4658a0b871c1248d5620a1edf4b1cb59e200bc961b0df5571c0698eda403894fc6
|
7
|
+
data.tar.gz: 40fdce0ad4cdd2e3644b40a253bf427e1b724c70831c36ae02ddd07b4efc07b835fda1e48537d7cca073f2d5d08a105d7a4c23144e870fb5e33ad10f5ce32af0
|
data/README.md
CHANGED
@@ -11,6 +11,7 @@ Griddler is a Rails engine (full plugin) that provides an endpoint for the
|
|
11
11
|
[Cloudmailin parse api](http://cloudmailin.com),
|
12
12
|
[Postmark parse api](http://developer.postmarkapp.com/developer-inbound-parse.html) or
|
13
13
|
[Mandrill parse api](http://help.mandrill.com/entries/21699367-Inbound-Email-Processing-Overview)
|
14
|
+
[Mailgun routes](http://documentation.mailgun.com/user_manual.html#receiving-messages-via-http-through-a-forward-action)
|
14
15
|
that hands off a built email object to a class implemented by you.
|
15
16
|
|
16
17
|
Tutorials
|
@@ -30,9 +31,18 @@ Add griddler to your application's Gemfile and run `bundle install`:
|
|
30
31
|
```ruby
|
31
32
|
gem 'griddler'
|
32
33
|
```
|
34
|
+
A route is needed for the endpoint which receives `POST` messages. Currently,
|
35
|
+
the route is automatically appended to the route table like so:
|
33
36
|
|
34
|
-
|
35
|
-
|
37
|
+
```ruby
|
38
|
+
email_processor POST /email_processor(.:format) griddler/emails#create
|
39
|
+
```
|
40
|
+
|
41
|
+
**NOTE: This behavior is deprecated and will be removed by version 0.7.0 in favor
|
42
|
+
of manually adding the route.**
|
43
|
+
|
44
|
+
To manually add the route, in `config/routes.rb` you may either use the provided
|
45
|
+
routing method `mount_griddler` or set the route explicitly. Examples:
|
36
46
|
|
37
47
|
```ruby
|
38
48
|
# mount using default path
|
@@ -45,11 +55,6 @@ mount_griddler('/email/incoming')
|
|
45
55
|
post '/email_processor' => 'griddler/emails#create'
|
46
56
|
```
|
47
57
|
|
48
|
-
**NOTE:** Currently the default route is added to the bottom of your route table.
|
49
|
-
By version 0.7.0 it will be removed and you will be required to add the route
|
50
|
-
with one of the three above methods.
|
51
|
-
|
52
|
-
|
53
58
|
Defaults
|
54
59
|
--------
|
55
60
|
|
@@ -71,6 +76,7 @@ that responds to:
|
|
71
76
|
|
72
77
|
* `.to`
|
73
78
|
* `.from`
|
79
|
+
* `.cc`
|
74
80
|
* `.subject`
|
75
81
|
* `.body`
|
76
82
|
* `.raw_text`
|
@@ -108,6 +114,9 @@ information of each recipient:
|
|
108
114
|
`.from` will default to the `email` value of a hash like `.to`, and can be
|
109
115
|
configured to return the full hash.
|
110
116
|
|
117
|
+
`.cc` behaves and can be configured like `.to`. If the adapter does not
|
118
|
+
pass along a `cc` key then the headers will be parsed.
|
119
|
+
|
111
120
|
`.attachments` will contain an array of attachments as multipart/form-data files
|
112
121
|
which can be passed off to attachment libraries like Carrierwave or Paperclip.
|
113
122
|
|
@@ -118,26 +127,28 @@ Configuration Options
|
|
118
127
|
---------------------
|
119
128
|
|
120
129
|
An initializer can be created to control some of the options in Griddler. Defaults
|
121
|
-
are shown below with sample overrides following. In `config/
|
130
|
+
are shown below with sample overrides following. In `config/initializers/griddler.rb`:
|
122
131
|
|
123
132
|
```ruby
|
124
133
|
Griddler.configure do |config|
|
125
134
|
config.processor_class = EmailProcessor # MyEmailProcessor
|
135
|
+
config.processor_method = :process # :custom_method
|
126
136
|
config.to = :hash # :full, :email, :token
|
137
|
+
config.cc = :email # :full, :hash, :token
|
127
138
|
config.from = :email # :full, :token, :hash
|
128
139
|
# :raw => 'AppName <s13.6b2d13dc6a1d33db7644@mail.myapp.com>'
|
129
140
|
# :email => 's13.6b2d13dc6a1d33db7644@mail.myapp.com'
|
130
141
|
# :token => 's13.6b2d13dc6a1d33db7644'
|
131
|
-
# :hash => { raw: [...], email: [...], token: [...], host: [...],
|
132
|
-
name: [...] }
|
142
|
+
# :hash => { raw: [...], email: [...], token: [...], host: [...], name: [...] }
|
133
143
|
config.reply_delimiter = '-- REPLY ABOVE THIS LINE --'
|
134
|
-
config.email_service = :sendgrid # :cloudmailin, :postmark, :mandrill
|
144
|
+
config.email_service = :sendgrid # :cloudmailin, :postmark, :mandrill, :mailgun
|
135
145
|
end
|
136
146
|
```
|
137
147
|
|
138
148
|
* `config.processor_class` is the class Griddler will use to handle your incoming emails.
|
149
|
+
* `config.processor_method` is the method Griddler will call on the processor class when handling your incoming emails.
|
139
150
|
* `config.reply_delimiter` is the string searched for that will split your body.
|
140
|
-
* `config.to` and `config.from` are the format of the returned value for that
|
151
|
+
* `config.to`, `config.cc` and `config.from` are the format of the returned value for that
|
141
152
|
address in the email object. `:hash` will return all options within a -- (surprise!) -- hash.
|
142
153
|
* `config.email_service` tells Griddler which email service you are using. The
|
143
154
|
supported email service options are `:sendgrid` (the default), `:cloudmailin`
|
@@ -241,7 +252,7 @@ application that can handle the HEAD request:
|
|
241
252
|
|
242
253
|
```ruby
|
243
254
|
# routes.rb
|
244
|
-
get
|
255
|
+
get "/email_processor", to: proc { [200, {}, ["OK"]] }, as: "mandrill_head_test_request"
|
245
256
|
```
|
246
257
|
|
247
258
|
Once you have correctly configured Mandrill, you can go ahead and delete this code.
|
@@ -257,6 +268,8 @@ More Information
|
|
257
268
|
* [Postmark Docs](http://developer.postmarkapp.com/)
|
258
269
|
* [Mandrill](http://mandrill.com)
|
259
270
|
* [Mandrill Docs](http://help.mandrill.com/forums/21092258-Inbound-Email-Processing)
|
271
|
+
* [Mailgun](http://mailgun.com)
|
272
|
+
* [Mailgun Docs](http://documentation.mailgun.com/user_manual.html#receiving-forwarding-and-storing-messages)
|
260
273
|
|
261
274
|
Credits
|
262
275
|
-------
|
data/lib/griddler.rb
CHANGED
@@ -10,6 +10,7 @@ require 'griddler/adapters/sendgrid_adapter'
|
|
10
10
|
require 'griddler/adapters/cloudmailin_adapter'
|
11
11
|
require 'griddler/adapters/postmark_adapter'
|
12
12
|
require 'griddler/adapters/mandrill_adapter'
|
13
|
+
require 'griddler/adapters/mailgun_adapter'
|
13
14
|
|
14
15
|
module Griddler
|
15
16
|
end
|
@@ -13,6 +13,7 @@ module Griddler
|
|
13
13
|
def normalize_params
|
14
14
|
{
|
15
15
|
to: params[:envelope][:to].split(','),
|
16
|
+
cc: ccs,
|
16
17
|
from: params[:envelope][:from],
|
17
18
|
subject: params[:headers][:Subject],
|
18
19
|
text: params[:plain],
|
@@ -24,6 +25,10 @@ module Griddler
|
|
24
25
|
|
25
26
|
attr_reader :params
|
26
27
|
|
28
|
+
def ccs
|
29
|
+
params[:headers][:Cc].to_s.split(',').map(&:strip)
|
30
|
+
end
|
31
|
+
|
27
32
|
end
|
28
33
|
end
|
29
34
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Griddler
|
2
|
+
module Adapters
|
3
|
+
class MailgunAdapter
|
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
|
+
params.merge(
|
15
|
+
to: recipients,
|
16
|
+
cc: ccs,
|
17
|
+
text: params['body-plain'],
|
18
|
+
html: params['body-html'],
|
19
|
+
headers: params['message-headers'],
|
20
|
+
attachments: attachment_files
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :params
|
27
|
+
|
28
|
+
def recipients
|
29
|
+
params[:recipient].split(',')
|
30
|
+
end
|
31
|
+
|
32
|
+
def ccs
|
33
|
+
cc = if params[:Cc].present?
|
34
|
+
params[:Cc]
|
35
|
+
else
|
36
|
+
extract_header_cc
|
37
|
+
end
|
38
|
+
cc.split(',').map(&:strip)
|
39
|
+
end
|
40
|
+
|
41
|
+
def extract_header_cc
|
42
|
+
header = params['message-headers'].select{|h|
|
43
|
+
h.first == 'Cc'
|
44
|
+
}.first
|
45
|
+
header.to_a.last
|
46
|
+
end
|
47
|
+
|
48
|
+
def attachment_files
|
49
|
+
attachment_count = params['attachment-count'].to_i
|
50
|
+
|
51
|
+
attachment_count.times.map do |index|
|
52
|
+
params.delete("attachment-#{index+1}")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -14,7 +14,8 @@ module Griddler
|
|
14
14
|
events.map do |event|
|
15
15
|
{
|
16
16
|
to: recipients(event),
|
17
|
-
|
17
|
+
cc: ccs(event),
|
18
|
+
from: full_email([ event[:from_email], event[:from_name] ]),
|
18
19
|
subject: event[:subject],
|
19
20
|
text: event[:text],
|
20
21
|
html: event[:html],
|
@@ -38,6 +39,11 @@ module Griddler
|
|
38
39
|
event[:to].map { |recipient| full_email(recipient) }
|
39
40
|
end
|
40
41
|
|
42
|
+
def ccs(event)
|
43
|
+
found = event[:headers].select { |header| header.first == 'Cc' }.first
|
44
|
+
Array(found).last.to_s.split(',').map(&:strip)
|
45
|
+
end
|
46
|
+
|
41
47
|
def full_email(contact_info)
|
42
48
|
email = contact_info[0]
|
43
49
|
if contact_info[1]
|
@@ -12,7 +12,8 @@ module Griddler
|
|
12
12
|
|
13
13
|
def normalize_params
|
14
14
|
{
|
15
|
-
to: extract_recipients,
|
15
|
+
to: extract_recipients(:ToFull),
|
16
|
+
cc: extract_recipients(:CcFull),
|
16
17
|
from: full_email(params[:FromFull]),
|
17
18
|
subject: params[:Subject],
|
18
19
|
text: params[:TextBody],
|
@@ -25,8 +26,8 @@ module Griddler
|
|
25
26
|
|
26
27
|
attr_reader :params
|
27
28
|
|
28
|
-
def extract_recipients
|
29
|
-
params[
|
29
|
+
def extract_recipients(key)
|
30
|
+
params[key].to_a.map { |recipient| full_email(recipient) }
|
30
31
|
end
|
31
32
|
|
32
33
|
def full_email(contact_info)
|
@@ -12,7 +12,8 @@ module Griddler
|
|
12
12
|
|
13
13
|
def normalize_params
|
14
14
|
params.merge(
|
15
|
-
to: recipients,
|
15
|
+
to: recipients(:to),
|
16
|
+
cc: recipients(:cc),
|
16
17
|
attachments: attachment_files,
|
17
18
|
)
|
18
19
|
end
|
@@ -21,8 +22,8 @@ module Griddler
|
|
21
22
|
|
22
23
|
attr_reader :params
|
23
24
|
|
24
|
-
def recipients
|
25
|
-
params[
|
25
|
+
def recipients(key)
|
26
|
+
( params[key] || '' ).split(',')
|
26
27
|
end
|
27
28
|
|
28
29
|
def attachment_files
|
@@ -16,7 +16,7 @@ module Griddler
|
|
16
16
|
end
|
17
17
|
|
18
18
|
class Configuration
|
19
|
-
attr_accessor :processor_class, :reply_delimiter, :from
|
19
|
+
attr_accessor :processor_class, :processor_method, :reply_delimiter, :cc, :from
|
20
20
|
|
21
21
|
def to
|
22
22
|
@to ||= :hash
|
@@ -33,6 +33,10 @@ module Griddler
|
|
33
33
|
@to = type
|
34
34
|
end
|
35
35
|
|
36
|
+
def cc
|
37
|
+
@cc ||= :email
|
38
|
+
end
|
39
|
+
|
36
40
|
def from
|
37
41
|
@from ||= :email
|
38
42
|
end
|
@@ -41,6 +45,10 @@ module Griddler
|
|
41
45
|
@processor_class ||= EmailProcessor
|
42
46
|
end
|
43
47
|
|
48
|
+
def processor_method
|
49
|
+
@processor_method ||= :process
|
50
|
+
end
|
51
|
+
|
44
52
|
def reply_delimiter
|
45
53
|
@reply_delimiter ||= 'Reply ABOVE THIS LINE'
|
46
54
|
end
|
@@ -65,6 +73,7 @@ module Griddler
|
|
65
73
|
cloudmailin: Griddler::Adapters::CloudmailinAdapter,
|
66
74
|
postmark: Griddler::Adapters::PostmarkAdapter,
|
67
75
|
mandrill: Griddler::Adapters::MandrillAdapter,
|
76
|
+
mailgun: Griddler::Adapters::MailgunAdapter
|
68
77
|
}
|
69
78
|
end
|
70
79
|
end
|
data/lib/griddler/email.rb
CHANGED
@@ -3,13 +3,13 @@ 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, :raw_text, :raw_html,
|
6
|
+
attr_reader :to, :from, :cc, :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 = recipients
|
12
|
+
@to = recipients(:to)
|
13
13
|
@from = extract_address(params[:from], config.from)
|
14
14
|
@subject = params[:subject]
|
15
15
|
|
@@ -19,14 +19,18 @@ module Griddler
|
|
19
19
|
@raw_body = @raw_text || @raw_html
|
20
20
|
|
21
21
|
@headers = extract_headers
|
22
|
+
|
23
|
+
@cc = recipients(:cc)
|
24
|
+
|
22
25
|
@raw_headers = params[:headers]
|
23
26
|
|
24
27
|
@attachments = params[:attachments]
|
25
28
|
end
|
26
29
|
|
27
30
|
def process
|
28
|
-
processor_class
|
29
|
-
|
31
|
+
processor_class = config.processor_class
|
32
|
+
processor_method = config.processor_method
|
33
|
+
processor_class.public_send(processor_method, self)
|
30
34
|
end
|
31
35
|
|
32
36
|
private
|
@@ -34,11 +38,11 @@ module Griddler
|
|
34
38
|
attr_reader :params
|
35
39
|
|
36
40
|
def config
|
37
|
-
Griddler.configuration
|
41
|
+
@config ||= Griddler.configuration
|
38
42
|
end
|
39
43
|
|
40
|
-
def recipients
|
41
|
-
params[
|
44
|
+
def recipients(type=:to)
|
45
|
+
params[type].to_a.map { |recipient| extract_address(recipient, config.send(type)) }
|
42
46
|
end
|
43
47
|
|
44
48
|
def extract_address(address, type)
|
@@ -59,6 +63,10 @@ module Griddler
|
|
59
63
|
EmailParser.extract_headers(params[:headers])
|
60
64
|
end
|
61
65
|
|
66
|
+
def extract_cc_from_headers(headers)
|
67
|
+
EmailParser.extract_cc(headers)
|
68
|
+
end
|
69
|
+
|
62
70
|
def text_or_sanitized_html
|
63
71
|
if params.key? :text
|
64
72
|
clean_text(params[:text])
|
@@ -68,33 +76,24 @@ module Griddler
|
|
68
76
|
end
|
69
77
|
|
70
78
|
def clean_text(text)
|
71
|
-
clean_invalid_utf8_bytes(text
|
79
|
+
clean_invalid_utf8_bytes(text)
|
72
80
|
end
|
73
81
|
|
74
82
|
def clean_html(html)
|
75
|
-
cleaned_html = clean_invalid_utf8_bytes(html
|
83
|
+
cleaned_html = clean_invalid_utf8_bytes(html)
|
76
84
|
cleaned_html = strip_tags(cleaned_html)
|
77
85
|
cleaned_html = HTMLEntities.new.decode(cleaned_html)
|
78
86
|
cleaned_html
|
79
87
|
end
|
80
88
|
|
81
|
-
def clean_invalid_utf8_bytes(text
|
82
|
-
text.
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
undef: :replace,
|
87
|
-
replace: ''
|
88
|
-
)
|
89
|
-
end
|
90
|
-
|
91
|
-
def src_encoding(email_part)
|
92
|
-
if params[:charsets]
|
93
|
-
charsets = ActiveSupport::JSON.decode(params[:charsets])
|
94
|
-
charsets[email_part]
|
95
|
-
else
|
96
|
-
'binary'
|
89
|
+
def clean_invalid_utf8_bytes(text)
|
90
|
+
if !text.valid_encoding?
|
91
|
+
text = text
|
92
|
+
.force_encoding('ISO-8859-1')
|
93
|
+
.encode('UTF-8')
|
97
94
|
end
|
95
|
+
|
96
|
+
text
|
98
97
|
end
|
99
98
|
end
|
100
99
|
end
|
@@ -74,10 +74,12 @@ module Griddler::EmailParser
|
|
74
74
|
def self.regex_split_points
|
75
75
|
[
|
76
76
|
reply_delimeter_regex,
|
77
|
-
/^\s*[-]+\s*Original Message\s*[-]+\s
|
77
|
+
/^\s*[-]+\s*Original Message\s*[-]+\s*$/i,
|
78
78
|
/^\s*--\s*$/,
|
79
|
+
/^\s*\>?\s*On.*\r?\n?\s*.*\s*wrote:$/,
|
79
80
|
/On.*wrote:/,
|
80
|
-
|
81
|
+
/From:.*$/i,
|
82
|
+
/^\s*\d{4}\/\d{1,2}\/\d{1,2}\s.*\s<.*>?$/i
|
81
83
|
]
|
82
84
|
end
|
83
85
|
|
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.6.
|
4
|
+
version: 0.6.3
|
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:
|
14
|
+
date: 2014-01-15 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: rails
|
@@ -92,10 +92,15 @@ executables: []
|
|
92
92
|
extensions: []
|
93
93
|
extra_rdoc_files: []
|
94
94
|
files:
|
95
|
+
- LICENSE
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
95
98
|
- app/controllers/griddler/emails_controller.rb
|
96
99
|
- config/initializers/griddler.rb
|
97
100
|
- config/routes.rb
|
101
|
+
- lib/griddler.rb
|
98
102
|
- lib/griddler/adapters/cloudmailin_adapter.rb
|
103
|
+
- lib/griddler/adapters/mailgun_adapter.rb
|
99
104
|
- lib/griddler/adapters/mandrill_adapter.rb
|
100
105
|
- lib/griddler/adapters/postmark_adapter.rb
|
101
106
|
- lib/griddler/adapters/sendgrid_adapter.rb
|
@@ -106,11 +111,7 @@ files:
|
|
106
111
|
- lib/griddler/errors.rb
|
107
112
|
- lib/griddler/route_extensions.rb
|
108
113
|
- lib/griddler/version.rb
|
109
|
-
- lib/griddler.rb
|
110
114
|
- lib/tasks/griddler_tasks.rake
|
111
|
-
- LICENSE
|
112
|
-
- Rakefile
|
113
|
-
- README.md
|
114
115
|
homepage: http://thoughtbot.com
|
115
116
|
licenses: []
|
116
117
|
metadata: {}
|
@@ -134,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
135
|
version: '0'
|
135
136
|
requirements: []
|
136
137
|
rubyforge_project:
|
137
|
-
rubygems_version: 2.
|
138
|
+
rubygems_version: 2.2.1
|
138
139
|
signing_key:
|
139
140
|
specification_version: 4
|
140
141
|
summary: SendGrid Parse API client Rails Engine
|