griddler 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fb74f34f6940e9e3287bfb7a543d4eed144ca554
4
+ data.tar.gz: 38c69abc85aed6e97d8d7e75d47456b476964b27
5
+ SHA512:
6
+ metadata.gz: 2cd9c1d15de8639995f8c02f085da8c88846d3226a136756c022cdfb9b9125a0bb1da7d9b4b2aea10274f9d58ee6792d8675ced712f75f9470f6791b1931d40b
7
+ data.tar.gz: 7d6bce5cd7c9bff557cc6611a7c5129091d104d4e90e1bd031d26d9f7e8f8cb79e28eb12ab162e4c52e4fcf0e015eb5dea3a3c9974daf75d61aeff6d8c8c0b2d
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 Caleb Thompson, Joel Oliveira and thoughtbot, inc.
1
+ Copyright (c) 2013 Caleb Thompson, Joel Oliveira and thoughtbot, inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,13 +1,26 @@
1
-
2
1
  Griddler
3
2
  ========
4
3
 
4
+ [![Build Status](https://travis-ci.org/thoughtbot/griddler.png?branch=master)](https://travis-ci.org/thoughtbot/griddler)
5
+ [![Code Climate](https://codeclimate.com/github/thoughtbot/griddler.png)](https://codeclimate.com/github/thoughtbot/griddler)
6
+
5
7
  ### Receive emails in your Rails app
6
8
 
7
9
  Griddler is a Rails engine (full plugin) that provides an endpoint for the
8
- [Sendgrid parse api](http://sendgrid.com/docs/API%20Reference/Webhooks/parse.html)
10
+ [SendGrid parse api](http://sendgrid.com/docs/API%20Reference/Webhooks/parse.html),
11
+ [Cloudmailin parse api](http://cloudmailin.com) or
12
+ [Postmark parse api](http://developer.postmarkapp.com/developer-inbound-parse.html)
9
13
  that hands off a built email object to a class implemented by you.
10
14
 
15
+ Tutorials
16
+ ---------
17
+
18
+ * SendGrid has done a
19
+ [great tutorial](http://blog.sendgrid.com/receiving-email-in-your-rails-app-with-griddler/)
20
+ on integrating Griddler with your application.
21
+ * And of course, view our own blog post on the subject over at
22
+ [Giant Robots](http://robots.thoughtbot.com/post/42286882447/handle-incoming-email-with-griddler).
23
+
11
24
  Installation
12
25
  ------------
13
26
 
@@ -19,11 +32,11 @@ gem 'griddler'
19
32
 
20
33
  Griddler comes with a default endpoint that will be displayed at the bottom
21
34
  of the output of `rake routes`. If there is a previously defined route that
22
- matches `/email_processor`–or you would like to rename the matched pathyou
35
+ matches `/email_processor` -- or you would like to rename the matched path -- you
23
36
  may add the route to the desired position in routes.rb with the following:
24
37
 
25
38
  ```ruby
26
- match '/email_processor' => 'griddler/emails#create', via: :post
39
+ post '/email_processor' => 'griddler/emails#create'
27
40
  ```
28
41
 
29
42
  Defaults
@@ -50,10 +63,14 @@ that responds to:
50
63
  * `.subject`
51
64
  * `.body`
52
65
  * `.raw_body`
66
+ * `.attachments`
67
+ * `.headers`
68
+ * `.raw_headers`
53
69
 
54
70
  Each of those has some sensible defaults.
55
71
 
56
- `.from`, `.raw_body` and `.subject` will contain the obvious values found in the email, the raw values from those fields.
72
+ `.from`, `.raw_body`, `.raw_headers`, and `.subject` will contain the obvious
73
+ values found in the email, the raw values from those fields.
57
74
 
58
75
  `.body` will contain the full contents of the email body **unless** there is a
59
76
  line in the email containing the string `-- Reply ABOVE THIS LINE --`. In that
@@ -63,6 +80,12 @@ case `.body` will contain everything before that line.
63
80
  that this is the most often used portion of the email address and consider it to
64
81
  be the token we'll key off of for interaction with our application.
65
82
 
83
+ `.attachments` will contain an array of attachments as multipart/form-data files
84
+ which can be passed off to attachment libraries like Carrierwave or Paperclip.
85
+
86
+ `.headers` will contain a hash of header names and values as parsed by the Mail
87
+ gem. Headers will only be parsed if the adapter supports a headers option.
88
+
66
89
  Configuration Options
67
90
  ---------------------
68
91
 
@@ -78,13 +101,17 @@ Griddler.configure do |config|
78
101
  # :token => 's13.6b2d13dc6a1d33db7644'
79
102
  # :hash => { raw: '', email: '', token: '', host: '' }
80
103
  config.reply_delimiter = '-- REPLY ABOVE THIS LINE --'
104
+ config.email_service = :sendgrid
81
105
  end
82
106
  ```
83
107
 
84
- * `config.processor_class` change the class Griddler will use to handle your incoming emails.
85
- * `config.reply_delimiter` change the string searched for that will split your body.
86
- * `config.to` change the format of the returned value for the `:to` key in
108
+ * `config.processor_class` is the class Griddler will use to handle your incoming emails.
109
+ * `config.reply_delimiter` is the string searched for that will split your body.
110
+ * `config.to` is the format of the returned value for the `:to` key in
87
111
  the email object. `:hash` will return all options within a -- (surprise!) -- hash.
112
+ * `config.email_service` tells Griddler which email service you are using. The supported
113
+ email service options are :sendgrid (the default), :cloudmailin (expects
114
+ multipart format) and :postmark
88
115
 
89
116
  Testing In Your App
90
117
  -------------------
@@ -113,18 +140,39 @@ factory :email, class: OpenStruct do
113
140
  end
114
141
  ```
115
142
 
116
- Bear in mind, if you plan on using the :with_attachment trait, that this
117
- example assumes your factories are in spec/factories.rb and you have
118
- an image file in spec/fixtures/
143
+ Bear in mind, if you plan on using the `:with_attachment` trait, that this
144
+ example assumes your factories are in `spec/factories.rb` and you have
145
+ an image file in `spec/fixtures/`.
119
146
 
120
147
  To use it in your test(s) just build with `email = build(:email)`
121
- or `email = build(:email, :with_attachment)`
148
+ or `email = build(:email, :with_attachment)`.
149
+
150
+ Adapters
151
+ --------
152
+
153
+ `Griddler::Email` expects certain parameters to be in place for proper parsing
154
+ to occur. When writing an adapter, ensure that the `normalized_params` method
155
+ of your adapter returns a hash with these keys:
156
+
157
+ * `:to` The recipient field
158
+ * `:from` The sender field
159
+ * `:subject` Email subject
160
+ * `:text` The text body of the email
161
+ * `:html` The html body of the email, nil or empty string if not present
162
+ * `:attachments` (can be an empty array) Array of attachments to the email
163
+ * `:headers` (optional) The raw headers of the email
164
+ * `:charsets` (optional) A JSON string containing the character sets of the
165
+ fields extracted from the message
122
166
 
123
167
  More Information
124
168
  ----------------
125
169
 
126
- * [Sendgrid](http://www.sendgrid.com)
127
- * [Sendgrid Parse API](www.sendgrid.com/docs/API Reference/Webhooks/parse.html)
170
+ * [SendGrid](http://www.sendgrid.com)
171
+ * [SendGrid Parse API](http://www.sendgrid.com/docs/API Reference/Webhooks/parse.html)
172
+ * [Cloudmailin](http://cloudmailin.com)
173
+ * [Cloudmailin Docs](http://docs.cloudmailin.com/)
174
+ * [Postmark](http://postmarkapp.com)
175
+ * [Postmark Docs](http://developer.postmarkapp.com/)
128
176
 
129
177
  Credits
130
178
  -------
@@ -141,6 +189,6 @@ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
141
189
  License
142
190
  -------
143
191
 
144
- Griddler is Copyright © 2012 Caleb Thompson, Joel Oliveira and thoughtbot. It is
192
+ Griddler is Copyright © 2013 Caleb Thompson, Joel Oliveira and thoughtbot. It is
145
193
  free software, and may be redistributed under the terms specified in the LICENSE
146
194
  file.
@@ -1,6 +1,12 @@
1
1
  class Griddler::EmailsController < ActionController::Base
2
2
  def create
3
- Griddler::Email.new(params)
3
+ Griddler::Email.new(normalized_params).process
4
4
  head :ok
5
5
  end
6
+
7
+ private
8
+
9
+ def normalized_params
10
+ Griddler.configuration.email_service.normalize_params(params)
11
+ end
6
12
  end
@@ -1,3 +1,3 @@
1
1
  Rails.application.routes.draw do
2
- match '/email_processor' => 'griddler/emails#create', via: :post, as: :email_processor
2
+ post '/email_processor' => 'griddler/emails#create', as: :email_processor
3
3
  end
@@ -1,9 +1,13 @@
1
+ require 'rails/engine'
2
+ require 'action_view'
1
3
  require 'griddler/errors'
2
4
  require 'griddler/engine'
3
5
  require 'griddler/email'
4
- require 'griddler/email_format'
5
6
  require 'griddler/email_parser'
6
7
  require 'griddler/configuration'
8
+ require 'griddler/adapters/sendgrid_adapter'
9
+ require 'griddler/adapters/cloudmailin_adapter'
10
+ require 'griddler/adapters/postmark_adapter'
7
11
 
8
12
  module Griddler
9
13
  end
@@ -0,0 +1,29 @@
1
+ module Griddler
2
+ module Adapters
3
+ class CloudmailinAdapter
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
+ {
15
+ to: params[:envelope][:to],
16
+ from: params[:envelope][:from],
17
+ subject: params[:headers][:Subject],
18
+ text: params[:plain],
19
+ attachments: params.fetch(:attachments) { [] },
20
+ }
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :params
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,49 @@
1
+ module Griddler
2
+ module Adapters
3
+ class PostmarkAdapter
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
+ {
15
+ to: params[:ToFull][:Email],
16
+ from: params[:FromFull][:Email],
17
+ subject: params[:Subject],
18
+ text: params[:TextBody],
19
+ html: params[:HtmlBody],
20
+ attachments: attachment_files,
21
+ }
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :params
27
+
28
+ def attachment_files
29
+ attachments = Array(params[:Attachments])
30
+
31
+ attachments.map do |attachment|
32
+ ActionDispatch::Http::UploadedFile.new({
33
+ filename: attachment[:Name],
34
+ type: attachment[:ContentType],
35
+ tempfile: create_tempfile(attachment)
36
+ })
37
+ end
38
+ end
39
+
40
+ def create_tempfile(attachment)
41
+ filename = attachment[:Name]
42
+ tempfile = Tempfile.new(filename, Dir::tmpdir, encoding: 'ascii-8bit')
43
+ tempfile.write(Base64.decode64(attachment[:Content]))
44
+ tempfile.rewind
45
+ tempfile
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,32 @@
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[:attachments] = attachment_files
15
+ params
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :params
21
+
22
+ def attachment_files
23
+ params.delete('attachment-info')
24
+ attachment_count = params[:attachments].to_i
25
+
26
+ attachment_count.times.map do |index|
27
+ params.delete("attachment#{index + 1}".to_sym)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,20 +1,18 @@
1
1
  module Griddler
2
- class << self
3
- attr_accessor :configuration
4
- end
2
+ @@configuration = nil
5
3
 
6
4
  def self.configure
7
- self.configuration = Configuration.new
5
+ @@configuration = Configuration.new
8
6
 
9
7
  if block_given?
10
8
  yield configuration
11
9
  end
12
10
 
13
- self.configuration
11
+ configuration
14
12
  end
15
13
 
16
14
  def self.configuration
17
- @configuration || self.configure
15
+ @@configuration || configure
18
16
  end
19
17
 
20
18
  class Configuration
@@ -31,5 +29,22 @@ module Griddler
31
29
  def reply_delimiter
32
30
  @reply_delimiter ||= 'Reply ABOVE THIS LINE'
33
31
  end
32
+
33
+ def email_service
34
+ @email_service_adapter ||= adapter_class[:sendgrid]
35
+ end
36
+
37
+ def email_service=(new_email_service)
38
+ @email_service_adapter = adapter_class.fetch(new_email_service) { raise Griddler::Errors::EmailServiceAdapterNotFound }
39
+ end
40
+
41
+ private
42
+
43
+ def adapter_class
44
+ {
45
+ sendgrid: Griddler::Adapters::SendgridAdapter,
46
+ cloudmailin: Griddler::Adapters::CloudmailinAdapter,
47
+ }
48
+ end
34
49
  end
35
50
  end
@@ -1,96 +1,96 @@
1
1
  require 'htmlentities'
2
2
 
3
- class Griddler::Email
4
- include ActionView::Helpers::SanitizeHelper
5
- attr_accessor :to, :from, :body, :raw_body, :subject, :attachments
6
-
7
- def initialize(params)
8
- @params = params
9
- @to = extract_address(params[:to], config.to)
10
- @from = extract_address(params[:from], :email)
11
- @subject = params[:subject]
12
- @body = extract_body
13
- @raw_body = params[:text] || params[:html]
14
- @attachments = extract_attachments
15
-
16
- processor_class = config.processor_class
17
- processor_class.process(self)
18
- end
3
+ module Griddler
4
+ class Email
5
+ include ActionView::Helpers::SanitizeHelper
6
+ attr_reader :to, :from, :subject, :body, :raw_body,
7
+ :headers, :raw_headers, :attachments
19
8
 
20
- private
9
+ def initialize(params)
10
+ @params = params
21
11
 
22
- attr_reader :params
12
+ @to = extract_address(params[:to], config.to)
13
+ @from = extract_address(params[:from], :email)
14
+ @subject = params[:subject]
23
15
 
24
- def config
25
- Griddler.configuration
26
- end
16
+ @body = extract_body
17
+ @raw_body = params[:text] || params[:html]
27
18
 
28
- def extract_address(address, type)
29
- parsed = EmailParser.parse_address(address)
19
+ @headers = extract_headers
20
+ @raw_headers = params[:headers]
30
21
 
31
- if type == :hash
32
- parsed
33
- else
34
- parsed[type]
22
+ @attachments = params[:attachments]
35
23
  end
36
- end
37
24
 
38
- def extract_attachments
39
- attachment_count = params[:attachments].to_i
40
- attachment_files = []
25
+ def process
26
+ processor_class = config.processor_class
27
+ processor_class.process(self)
28
+ end
41
29
 
42
- attachment_count.times do |index|
43
- attachment_files << params["attachment#{index + 1}".to_sym]
30
+ private
31
+
32
+ attr_reader :params
33
+
34
+ def config
35
+ Griddler.configuration
44
36
  end
45
37
 
46
- attachment_files
47
- end
38
+ def extract_address(address, type)
39
+ parsed = EmailParser.parse_address(address)
48
40
 
49
- def extract_body
50
- body_text = text_or_sanitized_html
51
- charsets = params[:charsets]
41
+ if type == :hash
42
+ parsed
43
+ else
44
+ parsed[type]
45
+ end
46
+ end
52
47
 
53
- if charsets.present?
54
- charsets = ActiveSupport::JSON.decode(charsets)
55
- body_text = body_text.encode(
56
- 'UTF-8',
57
- invalid: :replace,
58
- undef: :replace,
59
- replace: ''
60
- ).force_encoding('UTF-8')
48
+ def extract_body
49
+ EmailParser.extract_reply_body(text_or_sanitized_html)
61
50
  end
62
51
 
63
- EmailParser.extract_reply_body(body_text)
64
- end
52
+ def extract_headers
53
+ EmailParser.extract_headers(params[:headers])
54
+ end
65
55
 
66
- def text_or_sanitized_html
67
- if params.key? :text
68
- clean_text(params[:text])
69
- elsif params.key? :html
70
- clean_html(params[:html])
71
- else
72
- raise Griddler::Errors::EmailBodyNotFound
56
+ def text_or_sanitized_html
57
+ if params.key? :text
58
+ clean_text(params[:text])
59
+ elsif params.key? :html
60
+ clean_html(params[:html])
61
+ else
62
+ raise Errors::EmailBodyNotFound
63
+ end
73
64
  end
74
- end
75
65
 
76
- def clean_text(text)
77
- clean_invalid_utf8_bytes(text)
78
- end
66
+ def clean_text(text)
67
+ clean_invalid_utf8_bytes(text, 'text')
68
+ end
79
69
 
80
- def clean_html(html)
81
- cleaned_html = clean_invalid_utf8_bytes(html)
82
- cleaned_html = strip_tags(cleaned_html)
83
- cleaned_html = HTMLEntities.new.decode(cleaned_html)
84
- cleaned_html
85
- end
70
+ def clean_html(html)
71
+ cleaned_html = clean_invalid_utf8_bytes(html, 'html')
72
+ cleaned_html = strip_tags(cleaned_html)
73
+ cleaned_html = HTMLEntities.new.decode(cleaned_html)
74
+ cleaned_html
75
+ end
86
76
 
87
- def clean_invalid_utf8_bytes(text)
88
- text.encode(
89
- 'UTF-8',
90
- 'binary',
91
- invalid: :replace,
92
- undef: :replace,
93
- replace: ''
94
- )
77
+ def clean_invalid_utf8_bytes(text, email_part)
78
+ text.encode(
79
+ 'UTF-8',
80
+ src_encoding(email_part),
81
+ invalid: :replace,
82
+ undef: :replace,
83
+ replace: ''
84
+ )
85
+ end
86
+
87
+ def src_encoding(email_part)
88
+ if params[:charsets]
89
+ charsets = ActiveSupport::JSON.decode(params[:charsets])
90
+ charsets[email_part]
91
+ else
92
+ 'binary'
93
+ end
94
+ end
95
95
  end
96
96
  end
@@ -8,7 +8,9 @@
8
8
  # email: 'somebody@example.com',
9
9
  # full: 'Some Body <somebody@example.com>',
10
10
  # }
11
- module EmailParser
11
+ require 'mail'
12
+
13
+ module Griddler::EmailParser
12
14
  def self.parse_address(full_address)
13
15
  email_address = extract_email_address(full_address)
14
16
  token, host = split_address(email_address)
@@ -21,7 +23,9 @@ module EmailParser
21
23
  end
22
24
 
23
25
  def self.extract_reply_body(body)
24
- if body
26
+ if body.blank?
27
+ ""
28
+ else
25
29
  delimeter = Griddler.configuration.reply_delimiter
26
30
  body.split(delimeter).first.
27
31
  split(/^\s*[-]+\s*Original Message\s*[-]+\s*$/).first.
@@ -37,6 +41,15 @@ module EmailParser
37
41
  end
38
42
  end
39
43
 
44
+ def self.extract_headers(raw_headers)
45
+ header_fields = Mail::Header.new(raw_headers).fields
46
+
47
+ header_fields.inject({}) do |header_hash, header_field|
48
+ header_hash[header_field.name.to_s] = header_field.value.to_s
49
+ header_hash
50
+ end
51
+ end
52
+
40
53
  private
41
54
 
42
55
  def self.extract_email_address(full_address)
@@ -5,5 +5,8 @@ module Griddler
5
5
  module Errors
6
6
  class EmailBodyNotFound < Griddler::Error
7
7
  end
8
+
9
+ class EmailServiceAdapterNotFound < Griddler::Error
10
+ end
8
11
  end
9
12
  end
@@ -1,3 +1,3 @@
1
1
  module Griddler
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,86 +1,93 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: griddler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
5
- prerelease:
4
+ version: 0.4.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Caleb Thompson
9
8
  - Joel Oliveira
10
9
  - thoughtbot
10
+ - Swift
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-02-04 00:00:00.000000000 Z
14
+ date: 2013-03-18 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
18
18
  requirement: !ruby/object:Gem::Requirement
19
- none: false
20
19
  requirements:
21
- - - ! '>='
20
+ - - '>='
22
21
  - !ruby/object:Gem::Version
23
22
  version: 3.2.0
24
23
  type: :runtime
25
24
  prerelease: false
26
25
  version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
26
  requirements:
29
- - - ! '>='
27
+ - - '>='
30
28
  - !ruby/object:Gem::Version
31
29
  version: 3.2.0
32
30
  - !ruby/object:Gem::Dependency
33
31
  name: htmlentities
34
32
  requirement: !ruby/object:Gem::Requirement
35
- none: false
36
33
  requirements:
37
- - - ! '>='
34
+ - - '>='
38
35
  - !ruby/object:Gem::Version
39
36
  version: '0'
40
37
  type: :runtime
41
38
  prerelease: false
42
39
  version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
40
  requirements:
45
- - - ! '>='
41
+ - - '>='
46
42
  - !ruby/object:Gem::Version
47
43
  version: '0'
48
44
  - !ruby/object:Gem::Dependency
49
45
  name: rspec-rails
50
46
  requirement: !ruby/object:Gem::Requirement
51
- none: false
52
47
  requirements:
53
- - - ! '>='
48
+ - - '>='
54
49
  - !ruby/object:Gem::Version
55
50
  version: '0'
56
51
  type: :development
57
52
  prerelease: false
58
53
  version_requirements: !ruby/object:Gem::Requirement
59
- none: false
60
54
  requirements:
61
- - - ! '>='
55
+ - - '>='
62
56
  - !ruby/object:Gem::Version
63
57
  version: '0'
64
58
  - !ruby/object:Gem::Dependency
65
59
  name: sqlite3
66
60
  requirement: !ruby/object:Gem::Requirement
67
- none: false
68
61
  requirements:
69
- - - ! '>='
62
+ - - '>='
70
63
  - !ruby/object:Gem::Version
71
64
  version: '0'
72
65
  type: :development
73
66
  prerelease: false
74
67
  version_requirements: !ruby/object:Gem::Requirement
75
- none: false
76
68
  requirements:
77
- - - ! '>='
69
+ - - '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ - !ruby/object:Gem::Dependency
73
+ name: jquery-rails
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
78
84
  - !ruby/object:Gem::Version
79
85
  version: '0'
80
86
  description:
81
87
  email:
82
88
  - cjaysson@gmail.com
83
89
  - joel@thoughtbot.com
90
+ - theycallmeswift@gmail.com
84
91
  executables: []
85
92
  extensions: []
86
93
  extra_rdoc_files: []
@@ -88,9 +95,11 @@ files:
88
95
  - app/controllers/griddler/emails_controller.rb
89
96
  - config/initializers/griddler.rb
90
97
  - config/routes.rb
98
+ - lib/griddler/adapters/cloudmailin_adapter.rb
99
+ - lib/griddler/adapters/postmark_adapter.rb
100
+ - lib/griddler/adapters/sendgrid_adapter.rb
91
101
  - lib/griddler/configuration.rb
92
102
  - lib/griddler/email.rb
93
- - lib/griddler/email_format.rb
94
103
  - lib/griddler/email_parser.rb
95
104
  - lib/griddler/engine.rb
96
105
  - lib/griddler/errors.rb
@@ -102,33 +111,26 @@ files:
102
111
  - README.md
103
112
  homepage: http://thoughtbot.com
104
113
  licenses: []
114
+ metadata: {}
105
115
  post_install_message:
106
116
  rdoc_options: []
107
117
  require_paths:
108
118
  - app
109
119
  - lib
110
120
  required_ruby_version: !ruby/object:Gem::Requirement
111
- none: false
112
121
  requirements:
113
- - - ! '>='
122
+ - - '>='
114
123
  - !ruby/object:Gem::Version
115
- version: '0'
116
- segments:
117
- - 0
118
- hash: 4165747324942510967
124
+ version: 1.9.2
119
125
  required_rubygems_version: !ruby/object:Gem::Requirement
120
- none: false
121
126
  requirements:
122
- - - ! '>='
127
+ - - '>='
123
128
  - !ruby/object:Gem::Version
124
129
  version: '0'
125
- segments:
126
- - 0
127
- hash: 4165747324942510967
128
130
  requirements: []
129
131
  rubyforge_project:
130
- rubygems_version: 1.8.24
132
+ rubygems_version: 2.0.0
131
133
  signing_key:
132
- specification_version: 3
134
+ specification_version: 4
133
135
  summary: SendGrid Parse API client Rails Engine
134
136
  test_files: []
@@ -1,6 +0,0 @@
1
- module Griddler::EmailFormat
2
- LocalPartSpecialChars = Regexp.escape('!#$%&\'*-/=?+-^_`{|}~')
3
- LocalPartUnquoted = '(([[:alnum:]' + LocalPartSpecialChars + ']+[\.\+]+))*[[:alnum:]' + LocalPartSpecialChars + '+]+'
4
- LocalPartQuoted = '\"(([[:alnum:]' + LocalPartSpecialChars + '\.\+]*|(\\\\[\u0001-\uFFFF]))*)\"'
5
- Regex = Regexp.new('((' + LocalPartUnquoted + ')|(' + LocalPartQuoted + ')+)@(((\w+\-+)|(\w+\.))*\w{1,63}\.[a-z]{2,6})', Regexp::EXTENDED | Regexp::IGNORECASE)
6
- end