griddler 0.6.1 → 0.6.3

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: 01c15f81e30fcd63ca2c9cb4bc9e2e8678264c5f
4
- data.tar.gz: 37a8b24a5ce5b94ef4e7f7d907298abfb3517cd2
3
+ metadata.gz: c93ac0eaccf2bf366151a3d202d31fb80c955e3a
4
+ data.tar.gz: 7966242ad3ac5d8566b8ed991b3b1118f266d88d
5
5
  SHA512:
6
- metadata.gz: 44c21089a2ede6e88242b9e6b24fc38bda03bc0a0dbcbf92e74e0a4a792d000cc374bcbb1da8e99bc922e934dbf8fa4506c164034293ebb482c62c80c1a8ece0
7
- data.tar.gz: 82704ef5699bc9c2b5c8fa1f274a21f37bb63993f6da44d74f273414d4464c2fea834464afe1f77919c1bd9a88abeb46ea7adeeb4676feaa8aa19562cf2d8a15
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
- In `config/routes.rb` you may either use the provided method `mount_griddler`
35
- or set the route manually. Examples:
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/initializer/griddler.rb`:
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 '/email_processor', :to => proc { [200, {}, ["OK"]] }
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
- from: event[:from_email],
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[:ToFull].map { |recipient| full_email(recipient) }
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[:to].split(',')
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
@@ -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 = config.processor_class
29
- processor_class.process(self)
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[:to].map { |recipient| extract_address(recipient, config.to) }
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, '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, '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, email_part)
82
- text.encode(
83
- 'UTF-8',
84
- src_encoding(email_part),
85
- invalid: :replace,
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
- /^\s*On.*\r?\n?\s*.*\s*wrote:$/
81
+ /From:.*$/i,
82
+ /^\s*\d{4}\/\d{1,2}\/\d{1,2}\s.*\s<.*>?$/i
81
83
  ]
82
84
  end
83
85
 
@@ -1,3 +1,3 @@
1
1
  module Griddler
2
- VERSION = "0.6.1"
2
+ VERSION = "0.6.3"
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.6.1
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: 2013-09-04 00:00:00.000000000 Z
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.0.5
138
+ rubygems_version: 2.2.1
138
139
  signing_key:
139
140
  specification_version: 4
140
141
  summary: SendGrid Parse API client Rails Engine