griddler 0.6.4 → 1.0.0.pre.alpha.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a2cacfe5e74d1231a76e4502ed28c88399fd769
4
- data.tar.gz: 3213db391f6032cfa65f6d0fa2e0323b45016001
3
+ metadata.gz: e799f0b0004bfe2b6628c40f370f2f16eab17223
4
+ data.tar.gz: b82b19547ba1ed0280e2e16460c54d4c22ed6cd0
5
5
  SHA512:
6
- metadata.gz: c9cf20906c65491d019e30b68dfd669c5f16f80eca4cbb922410c91f63b338e723e52f1a7912e56a2f6dfc10b041806eb64fe2ce7bc6adfdea3a1038ac88c304
7
- data.tar.gz: b047cccc5d6ea2fdfce31da626671fe11de304ec5d338850afacdf1640da27f51d60c31bee2b72d54d9c64db6147c17a9ad4d5d54e93d193e32d5925d1f6e6b7
6
+ metadata.gz: 240c7e9eda058081f8ee93e55f564f4c2a2683506c40d929cfc8fba43fbcbd7787fd91eef94871c272062ba9ae683a144e50cbcc442ddb2f3d22555c6762d35d
7
+ data.tar.gz: b5c5a4c2ad91fdaf9816178409cb12daca799ba9dd6be5e7311adf758bc879dfd14cf62e8fa0c7742a79e6c18a00c76b6581ae8ad929daa33af8fa46bc3839e7
data/README.md CHANGED
@@ -6,133 +6,58 @@ Griddler
6
6
 
7
7
  ### Receive emails in your Rails app
8
8
 
9
- Griddler is a Rails engine (full plugin) that provides an endpoint for the
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) or
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)
15
- that hands off a built email object to a class implemented by you.
9
+ Griddler is a Rails engine that provides an endpoint for the
10
+ [SendGrid](http://sendgrid.com/docs/API%20Reference/Webhooks/parse.html),
11
+ [Cloudmailin](http://cloudmailin.com),
12
+ [Postmark](http://developer.postmarkapp.com/developer-inbound-parse.html),
13
+ [Mandrill](http://help.mandrill.com/entries/21699367-Inbound-Email-Processing-Overview), or
14
+ [Mailgun](http://documentation.mailgun.com/user\_manual.html#receiving-messages-via-http-through-a-forward-action)
15
+ parse APIs that hands off a built email object to a class implemented by you.
16
16
 
17
17
  Tutorials
18
18
  ---------
19
19
 
20
- * SendGrid has done a
20
+ * SendGrid wrote a
21
21
  [great tutorial](http://blog.sendgrid.com/receiving-email-in-your-rails-app-with-griddler/)
22
22
  on integrating Griddler with your application.
23
- * And of course, view our own blog post on the subject over at
24
- [Giant Robots](http://robots.thoughtbot.com/post/42286882447/handle-incoming-email-with-griddler).
23
+ * We have our own blog post on the subject over at
24
+ [Giant Robots](http://robots.thoughtbot.com/handle-incoming-email-with-griddler).
25
25
 
26
26
  Installation
27
27
  ------------
28
28
 
29
- Add griddler to your application's Gemfile and run `bundle install`:
29
+ 1. Add `griddler` and an [adapter] gem to your application's Gemfile
30
+ and run `bundle install`.
30
31
 
31
- ```ruby
32
- gem 'griddler'
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:
36
-
37
- ```ruby
38
- email_processor POST /email_processor(.:format) griddler/emails#create
39
- ```
32
+ [adapter]: #adapters
40
33
 
41
- **NOTE: This behavior is deprecated and will be removed by version 0.7.0 in favor
42
- of manually adding the route.**
34
+ 2. A route is needed for the endpoint which receives `POST` messages. To add the
35
+ route, in `config/routes.rb` you may either use the provided routing method
36
+ `mount_griddler` or set the route explicitly. Examples:
43
37
 
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:
38
+ ```ruby
39
+ # config/routes.rb
46
40
 
47
- ```ruby
48
- # mount using default path
49
- mount_griddler
41
+ # mount using default path: /email_processor
42
+ mount_griddler
50
43
 
51
- # mount using a custom path
52
- mount_griddler('/email/incoming')
44
+ # mount using a custom path
45
+ mount_griddler('/email/incoming')
53
46
 
54
- # the "get off my lawn", DIY approach:
55
- post '/email_processor' => 'griddler/emails#create'
56
- ```
47
+ # the DIY approach:
48
+ post '/email_processor' => 'griddler/emails#create'
49
+ ```
57
50
 
58
- Defaults
59
- --------
51
+ ### Configuration Options
60
52
 
61
- By default Griddler will look for a class to be created in your application
62
- called EmailProcessor with a class method implemented, named process, taking
63
- in one argument (presumably `email`). For example, in `./lib/email_processor.rb`:
64
-
65
- ```ruby
66
- class EmailProcessor
67
- def self.process(email)
68
- # all of your application-specific code here - creating models,
69
- # processing reports, etc
70
- end
71
- end
72
- ```
73
-
74
- The contents of the `email` object passed into your process method is an object
75
- that responds to:
76
-
77
- * `.to`
78
- * `.from`
79
- * `.cc`
80
- * `.subject`
81
- * `.body`
82
- * `.raw_text`
83
- * `.raw_html`
84
- * `.raw_body`
85
- * `.attachments`
86
- * `.headers`
87
- * `.raw_headers`
88
-
89
- Each of those has some sensible defaults.
90
-
91
- `.raw_body`, `.raw_headers`, and `.subject` will contain the obvious
92
- values found in the email, the raw values from those fields.
93
-
94
- `.body` will contain the full contents of the email body **unless** there is a
95
- line in the email containing the string `-- Reply ABOVE THIS LINE --`. In that
96
- case `.body` will contain everything before that line.
97
-
98
- `.to` will contain an array of hashes. Each hash will have the following
99
- information of each recipient:
100
-
101
- * `token`: All the text before the email's "@". We've found that this is the
102
- most often used portion of the email address and consider it to be the token
103
- we'll key off of for interaction with our application.
104
-
105
- * `host`: All the text after the email's "@". This is important to filter
106
- the recipients sent to the application vs emails to other domains. More
107
- info below on the Upgrading to 0.5.0 section.
108
-
109
- * `email`: The email address of the recipient.
110
-
111
- * `full`: The whole recipient field. E.g, `Some User <hello@example.com>`
112
- * `name`: The name of the recipient. E.g, `Some User`
113
-
114
- `.from` will default to the `email` value of a hash like `.to`, and can be
115
- configured to return the full hash.
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
-
120
- `.attachments` will contain an array of attachments as multipart/form-data files
121
- which can be passed off to attachment libraries like Carrierwave or Paperclip.
122
-
123
- `.headers` will contain a hash of header names and values as parsed by the Mail
124
- gem. Headers will only be parsed if the adapter supports a headers option.
125
-
126
- Configuration Options
127
- ---------------------
128
-
129
- An initializer can be created to control some of the options in Griddler. Defaults
130
- are shown below with sample overrides following. In `config/initializers/griddler.rb`:
53
+ An initializer can be created to control some of the options in Griddler.
54
+ Defaults are shown below with sample overrides following. In
55
+ `config/initializers/griddler.rb`:
131
56
 
132
57
  ```ruby
133
58
  Griddler.configure do |config|
134
- config.processor_class = EmailProcessor # MyEmailProcessor
135
- config.processor_method = :process # :custom_method
59
+ config.processor_class = EmailProcessor # CommentViaEmail
60
+ config.processor_method = :process # :create_comment (A method on CommentViaEmail)
136
61
  config.to = :hash # :full, :email, :token
137
62
  config.cc = :email # :full, :hash, :token
138
63
  config.from = :email # :full, :token, :hash
@@ -145,21 +70,63 @@ Griddler.configure do |config|
145
70
  end
146
71
  ```
147
72
 
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.
150
- * `config.reply_delimiter` is the string searched for that will split your body.
151
- * `config.to`, `config.cc` and `config.from` are the format of the returned value for that
152
- address in the email object. `:hash` will return all options within a -- (surprise!) -- hash.
153
- * `config.email_service` tells Griddler which email service you are using. The
154
- supported email service options are `:sendgrid` (the default), `:cloudmailin`
155
- (expects multipart format), `:postmark` and `:mandrill`.
73
+ | Option | Meaning
74
+ | ------ | -------
75
+ | `processor_class` | The class Griddler will use to handle your incoming emails.
76
+ | `processor_method` | The method Griddler will call on the processor class when handling your incoming emails.
77
+ | `reply_delimiter` | The string searched for that will split your body.
78
+ | `email_service` | Tells Griddler which email service you are using. The supported email service options are `:sendgrid` (the default), `:cloudmailin` (expects multipart format), `:postmark` and `:mandrill`. You will also need to have an appropriate [adapter] gem included in your Gemfile.
79
+ | `to`, `config.cc` and `config.from` | The format of the returned value for that address in the email object. `:hash` will return all options within a -- (surprise!) -- hash.
80
+
81
+ By default Griddler will look for a class named `EmailProcessor` with a class
82
+ method named `process`, taking in one argument, a `Griddler::Email` instance
83
+ representing the incoming email. For example, in `./lib/email_processor.rb`:
84
+
85
+ ```ruby
86
+ class EmailProcessor
87
+ def self.process(email)
88
+ # all of your application-specific code here - creating models,
89
+ # processing reports, etc
90
+ end
91
+ end
92
+ ```
93
+
94
+ Griddler::Email attributes
95
+ --------------------------
96
+
97
+ | Attribute | Description
98
+ | -------------- | -----------
99
+ | `#to` | An array of hashes containing recipient address information. See [Email Addresses](#email-addresses) for more information.
100
+ | `#from` | A hash containing the sender address information.
101
+ | `#cc` | An array of hashes containing cc email address information.
102
+ | `#subject` | The subject of the email message.
103
+ | `#body` | The full contents of the email body **unless** there is a line in the email containing the string `-- Reply ABOVE THIS LINE --`. In that case `.body` will contain everything before that line.
104
+ | `#raw_text` | The raw text part of the body.
105
+ | `#raw_html` | The raw html part of the body.
106
+ | `#raw_body` | The raw body information provided by the email service.
107
+ | `#attachments` | An array of `File` objects containing any attachments.
108
+ | `#headers` | A hash of headers parsed by `Mail::Header`.
109
+ | `#raw_headers` | The raw headers included in the message.
110
+
111
+ ### Email Addresses
112
+
113
+ Gridder::Email provides email addresses as hashes. Each hash will have the following
114
+ information of each recipient:
115
+
116
+ | Key | Value
117
+ | --- | -----
118
+ | `:token` | All the text before the email's "@". We've found that this is the most often used portion of the email address and consider it to be the token we'll key off of for interaction with our application.
119
+ | `:host` | All the text after the email's "@". This is important to filter the recipients sent to the application vs emails to other domains. More info below on the Upgrading to 0.5.0 section.
120
+ | `:email` | The email address of the recipient.
121
+ | `:full` | The whole recipient field (e.g., `Some User <hello@example.com>`).
122
+ | `:name` | The name of the recipient (e.g., `Some User`).
156
123
 
157
124
  Testing In Your App
158
125
  -------------------
159
126
 
160
- You may want to create a factory for when testing the integration of Griddler into
161
- your application. If you're using factory\_girl this can be accomplished with the
162
- following sample factory.
127
+ You may want to create a factory for when testing the integration of Griddler
128
+ into your application. If you're using factory\_girl this can be accomplished
129
+ with the following sample factory:
163
130
 
164
131
  ```ruby
165
132
  factory :email, class: OpenStruct do
@@ -175,7 +142,7 @@ factory :email, class: OpenStruct do
175
142
  ActionDispatch::Http::UploadedFile.new({
176
143
  filename: 'img.png',
177
144
  type: 'image/png',
178
- tempfile: File.new("#{File.expand_path File.dirname(__FILE__)}/fixtures/img.png")
145
+ tempfile: File.new("#{File.expand_path(File.dirname(__FILE__))}/fixtures/img.png")
179
146
  })
180
147
  ]}
181
148
  end
@@ -186,76 +153,49 @@ Bear in mind, if you plan on using the `:with_attachment` trait, that this
186
153
  example assumes your factories are in `spec/factories.rb` and you have
187
154
  an image file in `spec/fixtures/`.
188
155
 
189
- To use it in your test(s) just build with `email = build(:email)`
156
+ To use it in your tests, build with `email = build(:email)`
190
157
  or `email = build(:email, :with_attachment)`.
191
158
 
192
159
  Adapters
193
160
  --------
194
161
 
195
- `Griddler::Email` expects certain parameters to be in place for proper parsing
196
- to occur. When writing an adapter, ensure that the `normalized_params` method
197
- of your adapter returns a hash with these keys:
198
-
199
- * `:to` The recipient field
200
- * `:from` The sender field
201
- * `:subject` Email subject
202
- * `:text` The text body of the email
203
- * `:html` The html body of the email, nil or empty string if not present
204
- * `:attachments` (can be an empty array) Array of attachments to the email
205
- * `:headers` (optional) The raw headers of the email
206
- * `:charsets` (optional) A JSON string containing the character sets of the
207
- fields extracted from the message
208
-
209
- Upgrading to Griddler 0.5.0
210
- ---------------------------
211
-
212
- Because of an issue with the way Griddler handled recipients in the `To` header,
213
- a breaking change was introduced in Griddler 0.5.0 that requires a minor change
214
- to `EmailProcessor` or `processor_class`.
215
-
216
- Previously, a single address was returned from `Griddler::Email#to`. Moving
217
- forward, this field will always be an array. Generally speaking, you will want
218
- to do something like this to handle the change:
162
+ Depending on the service you want to use Griddler with, you'll need to add an
163
+ adapter gem in addition to `griddler`.
219
164
 
220
- ```ruby
221
- # before
222
- def initialize(email)
223
- @to = email.to
224
- @from = email.from
225
- @body = email.body
226
- end
227
-
228
- # after
229
- def initialize(email)
230
- @to = pick_meaningful_recipient(email.to)
231
- @from = email.from
232
- @body = email.body
233
- end
165
+ | Service | Adapter
166
+ | ------- | -------
167
+ | sendgrid | [griddler-sendgrid]
168
+ | mandrill | [griddler-mandrill]
234
169
 
235
- private
170
+ [griddler-sendgrid]: https://github.com/thoughtbot/griddler-sendgrid
171
+ [griddler-mandrill]: https://github.com/wingrunr21/griddler-mandrill
236
172
 
237
- def pick_meaningful_recipient(recipients)
238
- recipients.find { |address| address =~ /@mydomain.com$/ }
239
- end
240
- ```
173
+ Writing an Adapter
174
+ ------------------
241
175
 
242
- Using Griddler with Mandrill
243
- ----------------------------
176
+ Griddler can theoretically work with any email => POST service. In order to work
177
+ correctly, adapters need to have their POST parameters restructured.
244
178
 
245
- When adding a webhook in their administration panel, Mandrill will issue a HEAD
246
- request to check if the webhook is valid (see
247
- [Adding Routes](http://help.mandrill.com/entries/21699367-Inbound-Email-Processing-Overview)).
248
- If the HEAD request fails, Mandrill will not allow you to add the webhook.
249
- Since Griddler is only configured to handle POST requests, you will not be able
250
- to add the webhook as-is. To solve this, add a temporary route to your
251
- application that can handle the HEAD request:
252
-
253
- ```ruby
254
- # routes.rb
255
- get "/email_processor", to: proc { [200, {}, ["OK"]] }, as: "mandrill_head_test_request"
256
- ```
257
-
258
- Once you have correctly configured Mandrill, you can go ahead and delete this code.
179
+ `Griddler::Email` expects certain parameters to be in place for proper parsing
180
+ to occur. When writing an adapter, ensure that the `normalized_params` method of
181
+ your adapter returns a hash with these keys:
182
+
183
+ | Parameter | Contents
184
+ | --------- | --------
185
+ | `:to` | The recipient field
186
+ | `:from` | The sender field
187
+ | `:subject` | Email subject
188
+ | `:text` | The text body of the email
189
+ | `:html` | The html body of the email, nil or empty string if not present
190
+ | `:attachments` | Array of attachments to the email. Can be an empty array.
191
+ | `:headers` | The raw headers of the email. **Optional**.
192
+ | `:charsets` | A JSON string containing the character sets of the fields extracted from the message. **Optional**.
193
+
194
+ All keys are required unless otherwise stated.
195
+
196
+ Adapters should be provided as gems. If you write an adapter, let us know and we
197
+ will add it to this README. See [griddler-sendgrid] for an example
198
+ implementation.
259
199
 
260
200
  More Information
261
201
  ----------------
@@ -269,7 +209,7 @@ More Information
269
209
  * [Mandrill](http://mandrill.com)
270
210
  * [Mandrill Docs](http://help.mandrill.com/forums/21092258-Inbound-Email-Processing)
271
211
  * [Mailgun](http://mailgun.com)
272
- * [Mailgun Docs](http://documentation.mailgun.com/user_manual.html#receiving-forwarding-and-storing-messages)
212
+ * [Mailgun Docs](http://documentation.mailgun.com/user\_manual.html#receiving-forwarding-and-storing-messages)
273
213
 
274
214
  Credits
275
215
  -------
@@ -279,13 +219,8 @@ Griddler was written by Caleb Thompson and Joel Oliveira.
279
219
  Large portions of the codebase were extracted from thoughtbot's
280
220
  [Trajectory](http://www.apptrajectory.com).
281
221
 
222
+ Thanks to our [contributors](https://github.com/thoughtbot/griddler/contributors)!
223
+
282
224
  ![thoughtbot](http://thoughtbot.com/images/tm/logo.png)
283
225
 
284
226
  The names and logos for thoughtbot are trademarks of thoughtbot, inc.
285
-
286
- License
287
- -------
288
-
289
- Griddler is Copyright © 2014 Caleb Thompson, Joel Oliveira and thoughtbot. It is
290
- free software, and may be redistributed under the terms specified in the LICENSE
291
- file.
data/Rakefile CHANGED
@@ -4,6 +4,7 @@ begin
4
4
  require 'bundler/gem_tasks'
5
5
  rescue LoadError
6
6
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ exit 1
7
8
  end
8
9
 
9
10
  Bundler::GemHelper.install_tasks
data/lib/griddler.rb CHANGED
@@ -6,11 +6,14 @@ require 'griddler/email'
6
6
  require 'griddler/email_parser'
7
7
  require 'griddler/configuration'
8
8
  require 'griddler/route_extensions'
9
- require 'griddler/adapters/sendgrid_adapter'
9
+ require 'griddler/adapter_registry'
10
10
  require 'griddler/adapters/cloudmailin_adapter'
11
11
  require 'griddler/adapters/postmark_adapter'
12
- require 'griddler/adapters/mandrill_adapter'
13
12
  require 'griddler/adapters/mailgun_adapter'
14
13
 
15
- module Griddler
16
- end
14
+ require 'griddler/sendgrid'
15
+ require 'griddler/mandrill'
16
+
17
+ Griddler.adapter_registry.register(:cloudmailin, Griddler::Adapters::CloudmailinAdapter)
18
+ Griddler.adapter_registry.register(:postmark, Griddler::Adapters::PostmarkAdapter)
19
+ Griddler.adapter_registry.register(:mailgun, Griddler::Adapters::MailgunAdapter)
@@ -0,0 +1,28 @@
1
+ module Griddler
2
+ class AdapterRegistry
3
+ DEFAULT_ADAPTER = :sendgrid
4
+
5
+ def initialize
6
+ @registry = {}
7
+ end
8
+
9
+ def register(adapter_name, adapter_class)
10
+ if adapter_name == DEFAULT_ADAPTER
11
+ @registry[:default] = adapter_class
12
+ end
13
+ @registry[adapter_name] = adapter_class
14
+ end
15
+
16
+ def [](adapter_name)
17
+ @registry[adapter_name]
18
+ end
19
+
20
+ def fetch(key, &block)
21
+ @registry.fetch(key, &block)
22
+ end
23
+ end
24
+
25
+ def self.adapter_registry
26
+ @adapter_registry ||= AdapterRegistry.new
27
+ end
28
+ end
@@ -12,7 +12,7 @@ module Griddler
12
12
 
13
13
  def normalize_params
14
14
  params.merge(
15
- to: recipients,
15
+ to: tos,
16
16
  cc: ccs,
17
17
  text: params['body-plain'],
18
18
  html: params['body-html'],
@@ -25,24 +25,32 @@ module Griddler
25
25
 
26
26
  attr_reader :params
27
27
 
28
- def recipients
29
- params[:recipient].split(',')
28
+ def tos
29
+ to = param_or_header(:To)
30
+ to = params[:recipient] unless to
31
+ to.split(',').map(&:strip)
30
32
  end
31
33
 
32
34
  def ccs
33
- cc = if params[:Cc].present?
34
- params[:Cc]
35
- else
36
- extract_header_cc
37
- end
35
+ cc = param_or_header(:Cc)
38
36
  cc.split(',').map(&:strip)
39
37
  end
40
38
 
41
- def extract_header_cc
42
- header = params['message-headers'].select{|h|
43
- h.first == 'Cc'
44
- }.first
45
- header.to_a.last
39
+ def extract_header(key)
40
+ return nil unless params['message-headers'].present?
41
+
42
+ headers = params['message-headers'].select do |h|
43
+ h.first.to_s == key.to_s
44
+ end
45
+ headers.flatten.last
46
+ end
47
+
48
+ def param_or_header(key)
49
+ if params[key].present?
50
+ params[key]
51
+ else
52
+ extract_header(key)
53
+ end
46
54
  end
47
55
 
48
56
  def attachment_files
@@ -42,7 +42,18 @@ module Griddler
42
42
  end
43
43
 
44
44
  def processor_class
45
- @processor_class ||= EmailProcessor
45
+ @processor_class ||=
46
+ begin
47
+ if Kernel.const_defined?(:EmailProcessor)
48
+ EmailProcessor
49
+ else
50
+ raise NameError.new(<<-ERROR.strip_heredoc, 'EmailProcessor')
51
+ To use Griddler, you must either define `EmailProcessor` or configure a
52
+ different processor. See https://github.com/thoughtbot/griddler#defaults for
53
+ more information.
54
+ ERROR
55
+ end
56
+ end
46
57
  end
47
58
 
48
59
  def processor_method
@@ -54,27 +65,11 @@ module Griddler
54
65
  end
55
66
 
56
67
  def email_service
57
- @email_service_adapter ||= adapter_class[:sendgrid]
68
+ @email_service_adapter ||= Griddler.adapter_registry[:sendgrid]
58
69
  end
59
70
 
60
71
  def email_service=(new_email_service)
61
- if new_email_service == :default
62
- new_email_service = :sendgrid
63
- end
64
-
65
- @email_service_adapter = adapter_class.fetch(new_email_service) { raise Griddler::Errors::EmailServiceAdapterNotFound }
66
- end
67
-
68
- private
69
-
70
- def adapter_class
71
- {
72
- sendgrid: Griddler::Adapters::SendgridAdapter,
73
- cloudmailin: Griddler::Adapters::CloudmailinAdapter,
74
- postmark: Griddler::Adapters::PostmarkAdapter,
75
- mandrill: Griddler::Adapters::MandrillAdapter,
76
- mailgun: Griddler::Adapters::MailgunAdapter
77
- }
72
+ @email_service_adapter = Griddler.adapter_registry.fetch(new_email_service) { raise Griddler::Errors::EmailServiceAdapterNotFound }
78
73
  end
79
74
  end
80
75
  end
@@ -0,0 +1,57 @@
1
+ require 'action_dispatch'
2
+
3
+ module Griddler::Testing
4
+ def upload_1
5
+ @upload_1 ||= UploadedImage.new('photo1.jpg').file
6
+ end
7
+
8
+ def upload_2
9
+ @upload_2 ||= UploadedImage.new('photo2.jpg').file
10
+ end
11
+
12
+ def normalize_params(params)
13
+ Griddler::Sendgrid::Adapter.normalize_params(params)
14
+ end
15
+
16
+ class UploadedImage
17
+ def initialize(name)
18
+ @name = name
19
+ end
20
+
21
+ def file
22
+ ActionDispatch::Http::UploadedFile.new({
23
+ filename: @name,
24
+ type: 'image/jpeg',
25
+ tempfile: fixture_file
26
+ })
27
+ end
28
+
29
+ private
30
+
31
+ def fixture_file
32
+ cwd = File.expand_path File.dirname(__FILE__)
33
+ File.new(File.join(cwd, '..', '..', 'spec', 'fixtures', @name))
34
+ end
35
+ end
36
+ end
37
+
38
+ shared_examples_for 'Griddler adapter' do |adapter, service_params|
39
+ it 'adapts params to expected values' do
40
+ Griddler.configuration.email_service = adapter
41
+
42
+ normalized_params = Griddler.configuration.email_service.normalize_params(service_params)
43
+
44
+ Array.wrap(normalized_params).each do |params|
45
+ email = Griddler::Email.new(params)
46
+
47
+ email.to.should eq([{
48
+ token: 'hi',
49
+ host: 'example.com',
50
+ full: 'Hello World <hi@example.com>',
51
+ email: 'hi@example.com',
52
+ name: 'Hello World',
53
+ }])
54
+ email.cc.should eq ['emily@example.com']
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,3 @@
1
1
  module Griddler
2
- VERSION = "0.6.4"
2
+ VERSION = "1.0.0-alpha.1"
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.4
4
+ version: 1.0.0.pre.alpha.1
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: 2014-03-13 00:00:00.000000000 Z
14
+ date: 2014-06-17 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -97,21 +97,19 @@ files:
97
97
  - Rakefile
98
98
  - app/controllers/griddler/emails_controller.rb
99
99
  - config/initializers/griddler.rb
100
- - config/routes.rb
101
100
  - lib/griddler.rb
101
+ - lib/griddler/adapter_registry.rb
102
102
  - lib/griddler/adapters/cloudmailin_adapter.rb
103
103
  - lib/griddler/adapters/mailgun_adapter.rb
104
- - lib/griddler/adapters/mandrill_adapter.rb
105
104
  - lib/griddler/adapters/postmark_adapter.rb
106
- - lib/griddler/adapters/sendgrid_adapter.rb
107
105
  - lib/griddler/configuration.rb
108
106
  - lib/griddler/email.rb
109
107
  - lib/griddler/email_parser.rb
110
108
  - lib/griddler/engine.rb
111
109
  - lib/griddler/errors.rb
112
110
  - lib/griddler/route_extensions.rb
111
+ - lib/griddler/testing.rb
113
112
  - lib/griddler/version.rb
114
- - lib/tasks/griddler_tasks.rake
115
113
  homepage: http://thoughtbot.com
116
114
  licenses: []
117
115
  metadata: {}
@@ -130,9 +128,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
128
  version: 1.9.2
131
129
  required_rubygems_version: !ruby/object:Gem::Requirement
132
130
  requirements:
133
- - - ">="
131
+ - - ">"
134
132
  - !ruby/object:Gem::Version
135
- version: '0'
133
+ version: 1.3.1
136
134
  requirements: []
137
135
  rubyforge_project:
138
136
  rubygems_version: 2.2.2
data/config/routes.rb DELETED
@@ -1,3 +0,0 @@
1
- Rails.application.routes.draw do
2
- post '/email_processor' => 'griddler/emails#create', as: :email_processor
3
- end
@@ -1,71 +0,0 @@
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(:to, event),
17
- cc: recipients(:cc, event),
18
- from: full_email([ event[:from_email], event[:from_name] ]),
19
- subject: event[:subject],
20
- text: event.fetch(:text, ''),
21
- html: event.fetch(:html, ''),
22
- raw_body: event[:raw_msg],
23
- attachments: attachment_files(event)
24
- }
25
- end
26
- end
27
-
28
- private
29
-
30
- attr_reader :params
31
-
32
- def events
33
- @events ||= ActiveSupport::JSON.decode(params[:mandrill_events]).map do |event|
34
- event['msg'].with_indifferent_access
35
- end
36
- end
37
-
38
- def recipients(field, event)
39
- Array.wrap(event[field]).map { |recipient| full_email(recipient) }
40
- end
41
-
42
- def full_email(contact_info)
43
- email = contact_info[0]
44
- if contact_info[1]
45
- "#{contact_info[1]} <#{email}>"
46
- else
47
- email
48
- end
49
- end
50
-
51
- def attachment_files(event)
52
- attachments = event[:attachments] || Array.new
53
- attachments.map do |key, attachment|
54
- ActionDispatch::Http::UploadedFile.new({
55
- filename: attachment[:name],
56
- type: attachment[:type],
57
- tempfile: create_tempfile(attachment)
58
- })
59
- end
60
- end
61
-
62
- def create_tempfile(attachment)
63
- filename = attachment[:name]
64
- tempfile = Tempfile.new(filename, Dir::tmpdir, encoding: 'ascii-8bit')
65
- tempfile.write(Base64.decode64(attachment[:content]))
66
- tempfile.rewind
67
- tempfile
68
- end
69
- end
70
- end
71
- end
@@ -1,39 +0,0 @@
1
- module Griddler
2
- module Adapters
3
- class SendgridAdapter
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(:to),
16
- cc: recipients(:cc),
17
- attachments: attachment_files,
18
- )
19
- end
20
-
21
- private
22
-
23
- attr_reader :params
24
-
25
- def recipients(key)
26
- ( params[key] || '' ).split(',')
27
- end
28
-
29
- def attachment_files
30
- params.delete('attachment-info')
31
- attachment_count = params[:attachments].to_i
32
-
33
- attachment_count.times.map do |index|
34
- params.delete("attachment#{index + 1}".to_sym)
35
- end
36
- end
37
- end
38
- end
39
- end
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :griddler do
3
- # # Task goes here
4
- # end