sendgrid_events_pbxx 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +154 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +37 -0
  8. data/Rakefile +13 -0
  9. data/app/controllers/sendgrid_events/sendgrid_events_controller.rb +8 -0
  10. data/app/models/sendgrid_events/sendgrid_email_record.rb +26 -0
  11. data/lib/generators/sendgrid_events/install/templates/create_sendgrid_email_records.rb +16 -0
  12. data/lib/generators/sendgrid_events/install/templates/initializer.rb +8 -0
  13. data/lib/generators/sendgrid_events/install/templates/routes.rb +2 -0
  14. data/lib/generators/sendgrid_events/install_generator.rb +55 -0
  15. data/lib/sendgrid_events/action_mailer_override.rb +29 -0
  16. data/lib/sendgrid_events/configure.rb +27 -0
  17. data/lib/sendgrid_events/engine.rb +12 -0
  18. data/lib/sendgrid_events/handlers/base.rb +50 -0
  19. data/lib/sendgrid_events/handlers/bounced.rb +7 -0
  20. data/lib/sendgrid_events/handlers/clicked.rb +7 -0
  21. data/lib/sendgrid_events/handlers/deferred.rb +7 -0
  22. data/lib/sendgrid_events/handlers/delivered.rb +10 -0
  23. data/lib/sendgrid_events/handlers/dispatch.rb +34 -0
  24. data/lib/sendgrid_events/handlers/dropped.rb +7 -0
  25. data/lib/sendgrid_events/handlers/opened.rb +7 -0
  26. data/lib/sendgrid_events/handlers/processed.rb +7 -0
  27. data/lib/sendgrid_events/handlers/spam_reported.rb +7 -0
  28. data/lib/sendgrid_events/handlers/unsubscribed.rb +7 -0
  29. data/lib/sendgrid_events/handlers.rb +3 -0
  30. data/lib/sendgrid_events/middleware.rb +22 -0
  31. data/lib/sendgrid_events/receiver.rb +18 -0
  32. data/lib/sendgrid_events/version.rb +3 -0
  33. data/lib/sendgrid_events.rb +9 -0
  34. data/script/rails +8 -0
  35. data/sendgrid_events.gemspec +28 -0
  36. data/spec/sendgrid_events/action_mailer_override_spec.rb +42 -0
  37. data/spec/sendgrid_events/handlers/base_spec.rb +47 -0
  38. data/spec/sendgrid_events/handlers/bounced_spec.rb +31 -0
  39. data/spec/sendgrid_events/handlers/clicked_spec.rb +31 -0
  40. data/spec/sendgrid_events/handlers/deferred_spec.rb +31 -0
  41. data/spec/sendgrid_events/handlers/delivered_spec.rb +31 -0
  42. data/spec/sendgrid_events/handlers/dispatch_spec.rb +8 -0
  43. data/spec/sendgrid_events/handlers/dropped_spec.rb +31 -0
  44. data/spec/sendgrid_events/handlers/opened_spec.rb +31 -0
  45. data/spec/sendgrid_events/handlers/processed_spec.rb +31 -0
  46. data/spec/sendgrid_events/handlers/spam_reported_spec.rb +31 -0
  47. data/spec/sendgrid_events/handlers/unsubscribed_spec.rb +31 -0
  48. data/spec/sendgrid_events/receiver_spec.rb +24 -0
  49. data/spec/spec_helper.rb +42 -0
  50. metadata +276 -0
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ spec/dummy/db/*.sqlite3
5
+ spec/dummy/log/*.log
6
+ spec/dummy/tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'enumerated_field'
6
+ gem 'jeweler'
data/Gemfile.lock ADDED
@@ -0,0 +1,154 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sendgrid_events_pbxx (0.1.4)
5
+ enumerated_field
6
+ rails (~> 3.2)
7
+ sendgrid-rails (~> 2.0)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ actionmailer (3.2.13)
13
+ actionpack (= 3.2.13)
14
+ mail (~> 2.5.3)
15
+ actionpack (3.2.13)
16
+ activemodel (= 3.2.13)
17
+ activesupport (= 3.2.13)
18
+ builder (~> 3.0.0)
19
+ erubis (~> 2.7.0)
20
+ journey (~> 1.0.4)
21
+ rack (~> 1.4.5)
22
+ rack-cache (~> 1.2)
23
+ rack-test (~> 0.6.1)
24
+ sprockets (~> 2.2.1)
25
+ activemodel (3.2.13)
26
+ activesupport (= 3.2.13)
27
+ builder (~> 3.0.0)
28
+ activerecord (3.2.13)
29
+ activemodel (= 3.2.13)
30
+ activesupport (= 3.2.13)
31
+ arel (~> 3.0.2)
32
+ tzinfo (~> 0.3.29)
33
+ activeresource (3.2.13)
34
+ activemodel (= 3.2.13)
35
+ activesupport (= 3.2.13)
36
+ activesupport (3.2.13)
37
+ i18n (= 0.6.1)
38
+ multi_json (~> 1.0)
39
+ arel (3.0.2)
40
+ awesome_print (1.1.0)
41
+ builder (3.0.4)
42
+ capybara (2.0.3)
43
+ mime-types (>= 1.16)
44
+ nokogiri (>= 1.3.3)
45
+ rack (>= 1.0.0)
46
+ rack-test (>= 0.5.4)
47
+ selenium-webdriver (~> 2.0)
48
+ xpath (~> 1.0.0)
49
+ childprocess (0.3.9)
50
+ ffi (~> 1.0, >= 1.0.11)
51
+ diff-lcs (1.2.2)
52
+ enumerated_field (0.3.0)
53
+ activemodel
54
+ activesupport
55
+ erubis (2.7.0)
56
+ factory_girl (2.6.4)
57
+ activesupport (>= 2.3.9)
58
+ factory_girl_rails (1.7.0)
59
+ factory_girl (~> 2.6.0)
60
+ railties (>= 3.0.0)
61
+ ffi (1.6.0)
62
+ git (1.2.5)
63
+ hike (1.2.1)
64
+ i18n (0.6.1)
65
+ jeweler (1.8.4)
66
+ bundler (~> 1.0)
67
+ git (>= 1.2.5)
68
+ rake
69
+ rdoc
70
+ journey (1.0.4)
71
+ json (1.7.7)
72
+ mail (2.5.3)
73
+ i18n (>= 0.4.0)
74
+ mime-types (~> 1.16)
75
+ treetop (~> 1.4.8)
76
+ mime-types (1.22)
77
+ multi_json (1.7.2)
78
+ nokogiri (1.5.9)
79
+ polyglot (0.3.3)
80
+ rack (1.4.5)
81
+ rack-cache (1.2)
82
+ rack (>= 0.4)
83
+ rack-ssl (1.3.3)
84
+ rack
85
+ rack-test (0.6.2)
86
+ rack (>= 1.0)
87
+ rails (3.2.13)
88
+ actionmailer (= 3.2.13)
89
+ actionpack (= 3.2.13)
90
+ activerecord (= 3.2.13)
91
+ activeresource (= 3.2.13)
92
+ activesupport (= 3.2.13)
93
+ bundler (~> 1.0)
94
+ railties (= 3.2.13)
95
+ railties (3.2.13)
96
+ actionpack (= 3.2.13)
97
+ activesupport (= 3.2.13)
98
+ rack-ssl (~> 1.3.2)
99
+ rake (>= 0.8.7)
100
+ rdoc (~> 3.4)
101
+ thor (>= 0.14.6, < 2.0)
102
+ rake (10.0.4)
103
+ rdoc (3.12.2)
104
+ json (~> 1.4)
105
+ rspec-core (2.13.1)
106
+ rspec-expectations (2.13.0)
107
+ diff-lcs (>= 1.1.3, < 2.0)
108
+ rspec-mocks (2.13.0)
109
+ rspec-rails (2.13.0)
110
+ actionpack (>= 3.0)
111
+ activesupport (>= 3.0)
112
+ railties (>= 3.0)
113
+ rspec-core (~> 2.13.0)
114
+ rspec-expectations (~> 2.13.0)
115
+ rspec-mocks (~> 2.13.0)
116
+ rubyzip (0.9.9)
117
+ selenium-webdriver (2.31.0)
118
+ childprocess (>= 0.2.5)
119
+ multi_json (~> 1.0)
120
+ rubyzip
121
+ websocket (~> 1.0.4)
122
+ sendgrid-rails (2.0.3)
123
+ actionmailer (>= 3.0.0)
124
+ activesupport (>= 2.1.0)
125
+ sprockets (2.2.2)
126
+ hike (~> 1.2)
127
+ multi_json (~> 1.0)
128
+ rack (~> 1.0)
129
+ tilt (~> 1.1, != 1.3.0)
130
+ sqlite3 (1.3.7)
131
+ thor (0.18.1)
132
+ tilt (1.3.6)
133
+ treetop (1.4.12)
134
+ polyglot
135
+ polyglot (>= 0.3.1)
136
+ tzinfo (0.3.37)
137
+ websocket (1.0.7)
138
+ xpath (1.0.0)
139
+ nokogiri (~> 1.3)
140
+
141
+ PLATFORMS
142
+ ruby
143
+
144
+ DEPENDENCIES
145
+ awesome_print
146
+ capybara
147
+ enumerated_field
148
+ factory_girl_rails (~> 1.7)
149
+ jeweler
150
+ rails (~> 3.2)
151
+ rake
152
+ rspec-rails (~> 2)
153
+ sendgrid_events_pbxx!
154
+ sqlite3
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2012 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # SendgridEvents
2
+
3
+ [![TravisCI](https://secure.travis-ci.org/jphenow/sendgrid_events.png "TravisCI")](http://travis-ci.org/jphenow/sendgrid_events "Travis-CI SendgridEvents")
4
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/jphenow/sendgrid_events)
5
+ [Ruby Gems](https://rubygems.org/gems/sendgrid_events)
6
+
7
+ SendgridEvents is a gem designed to give your application [Sendgrid postbacks](http://docs.sendgrid.com/documentation/api/event-api/).
8
+ With these postbacks you are more able to track the status of your emails programatically.
9
+
10
+ This gem creates a `SendgridEmailRecord` table for this tracking and you can attach handlers to specific
11
+ events.
12
+
13
+ # Installation
14
+
15
+ add
16
+
17
+ ```ruby
18
+ gem 'sendgrid_events'
19
+ ```
20
+
21
+ to your Gemfile and run
22
+
23
+ ```
24
+ bundle install
25
+ ```
26
+
27
+ After that you'll want to run:
28
+
29
+ ```
30
+ rails g sendgrid_events:install
31
+ rake db:migrate
32
+ ```
33
+
34
+ Finally, you'll want to edit your `config/initializers/sendgrid_events.rb`. Currently
35
+ you just have the option to include or disclude certain event handlers.
36
+
37
+ This project rocks and uses MIT-LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ namespace :spec do
8
+ RSpec::Core::RakeTask.new(:docs) do |t|
9
+ t.rspec_opts = ["--format doc"]
10
+ end
11
+ end
12
+
13
+ task :default => :spec
@@ -0,0 +1,8 @@
1
+ module SendgridEvents
2
+ class SendgridEventsController < ActionController::Base
3
+ def create
4
+ Receiver.receive params
5
+ render :nothing => true
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+ module SendgridEvents
2
+ class SendgridEmailRecord < ActiveRecord::Base
3
+ #belongs_to :sender, :polymorphic => true # What models can we use here?
4
+ # Message
5
+ include ::EnumeratedField
6
+ enum_field :status, [
7
+ %w[bounced bounced],
8
+ %w[clicked clicked],
9
+ %w[deferred deferred],
10
+ %w[delivered delivered],
11
+ %w[dropped dropped],
12
+ %w[opened opened],
13
+ %w[processed processed],
14
+ %w[processing processing],
15
+ %w[spamreported spamreported],
16
+ %w[unsubscribed unsubscribed],
17
+ ]
18
+
19
+ def self.create_from_headers!(headers, additional_attributes)
20
+ create!(:to => headers[:to],
21
+ :from => headers[:from],
22
+ :subject => headers[:subject],
23
+ :status => 'processing')
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ class CreateSendGridEmailRecords < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :sendgrid_email_records do |t|
4
+ t.string :status
5
+ t.string :to
6
+ t.string :from
7
+ t.string :subject
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+
13
+ def self.down
14
+ drop_table :sendgrid_email_records
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ SendgridEvents::Configure.config do
2
+ handle %w[processed deferred delivered open click bounce dropped spamreport unsubscribe]
3
+ receive true
4
+ foreign_key 'sengrid_events_id'
5
+ mount_at "/sendgrid_events/receiver"
6
+ end
7
+
8
+ # ActionMailer::Base.send :include, SendgridEvents::ActionMailerOverride
@@ -0,0 +1,2 @@
1
+
2
+ match SendgridEvents::Configure.mount_at => "sendgrid_events/sendgrid_events#receiver", :via => :post
@@ -0,0 +1,55 @@
1
+ require 'rails/generators'
2
+ module SendgridEvents
3
+ module Generators
4
+ class InstallGenerator < Rails::Generators::Base
5
+ include Rails::Generators::Migration
6
+ source_root File.expand_path "../install/templates", __FILE__
7
+
8
+ def self.next_migration_number(path)
9
+ unless @prev_migration_nr
10
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
11
+ else
12
+ @prev_migration_nr += 1
13
+ end
14
+ @prev_migration_nr.to_s
15
+ end
16
+
17
+ def install
18
+ migrations
19
+ initializer
20
+ routes
21
+ middleware
22
+ end
23
+
24
+ private
25
+
26
+ def migrations
27
+ puts "Copying Sengrid Events migrations..."
28
+ begin
29
+ migration_template "create_sendgrid_email_records.rb", "db/migrate/create_sendgrid_email_records.rb"
30
+ rescue
31
+ puts "Already have that migration"
32
+ end
33
+ end
34
+
35
+ def initializer
36
+ puts "Copying initializer..."
37
+ copy_file "initializer.rb", "config/initializers/sendgrid_events.rb"
38
+ end
39
+
40
+ def routes
41
+ puts "Copying routes..."
42
+ insert_into_file Rails.root.join('config', 'routes.rb'),
43
+ File.open(File.join(File.expand_path("../install/templates", __FILE__), 'routes.rb')).read,
44
+ :after => /Application\.routes\.draw do$/
45
+ end
46
+
47
+ def middleware
48
+ puts "Copying config..."
49
+ insert_into_file Rails.root.join('config', 'application.rb'), :after => /class Application.*$/ do
50
+ "\n config.middleware.insert_before ActiveRecord::ParamsParser, SendgridEvents::Middleware"
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ module SendgridEvents
2
+ module ActionMailerOverride
3
+ extend ActiveSupport::Concern
4
+ included do
5
+ alias_method_chain :uniq_args, :merge_args
6
+ alias_method_chain :mail, :record_email
7
+ end
8
+
9
+ attr_accessor :sendgrid_email_record_attributes
10
+ def sendgrid_email_record_attributes(attrs = nil)
11
+ @sendgrid_email_record_attributes ||= {}
12
+ return @sendgrid_email_record_attributes if attrs.nil?
13
+ self.sendgrid_email_record_attributes = attrs
14
+ end
15
+
16
+ def uniq_args_with_merge_args(args)
17
+ set_args = send_grid_header.data[:unique_args] ||= {}
18
+ uniq_args_without_merge_args set_args.merge(args)
19
+ end
20
+
21
+ def mail_with_record_email(headers={}, &block)
22
+ id = SendgridEmailRecord.create_from_headers!(headers, sendgrid_email_record_attributes).id
23
+ uniq_args :sendgrid_events_id => id
24
+ mail_without_record_email headers, &block
25
+ end
26
+ end
27
+ end
28
+
29
+ ActionMailer::Base.send :include, SendgridEvents::ActionMailerOverride
@@ -0,0 +1,27 @@
1
+ module SendgridEvents
2
+ class Configure
3
+ def self.mount_at(val = nil)
4
+ @mount_at ||= val
5
+ end
6
+
7
+ def self.config(&block)
8
+ class_eval &block
9
+ end
10
+
11
+ def self.handle(list)
12
+ Handlers::Dispatch.selected_handlers = list
13
+ end
14
+
15
+ def self.receive(boolean)
16
+ @receive = boolean
17
+ end
18
+
19
+ def self.receive?
20
+ @receive.nil? ? true : @receive
21
+ end
22
+
23
+ def self.foreign_key(name = nil)
24
+ @foreign_key ||= name
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ module ::SendgridEvents
2
+ class Engine < Rails::Engine
3
+ config.mount_at = '/sendgrid_events/' #TODO Config file
4
+ class << self
5
+ attr_accessor :root
6
+ end
7
+
8
+ def self.root
9
+ @root ||= Pathname.new(File.expand_path('../../', __FILE__))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,50 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Base
4
+ def self.registered_handlers
5
+ Dispatch.registered_handlers
6
+ end
7
+
8
+ def self.selected_handlers
9
+ Dispatch.selected_handlers
10
+ end
11
+
12
+ def self.acceptable_handlers
13
+ Dispatch.acceptable_handlers
14
+ end
15
+
16
+ def self.choose_and_handle(event)
17
+ if registered_handlers[event[:event]] and selected_handlers[event[:event]]
18
+ registered_handlers[event[:event]].handle(event)
19
+ end
20
+ end
21
+
22
+ def self.register_as_handler_for(handlee)
23
+ if acceptable_handlers[handlee]
24
+ handlee = handlee.to_s
25
+ registered_handlers[handlee] = self.name.constantize
26
+ self.name.constantize.send :define_singleton_method, :handlee do
27
+ self.name.demodulize.downcase
28
+ end
29
+ else
30
+ raise ArgumentError, "#{handlee.to_s.titleize} is not in the Dispatch's list of acceptable handlers"
31
+ end
32
+ end
33
+
34
+ def self.handler(&block)
35
+ block_given? ? @handler = block : @handler
36
+ end
37
+
38
+ def self.handle(event)
39
+ found_event = find_and_update_event(event)
40
+ handler.call(found_event) unless found_event.nil? or handler.nil?
41
+ end
42
+
43
+ def self.find_and_update_event(event)
44
+ SendgridEmailRecord.find_by_id(event[:sendgrid_events_id]).tap do |record|
45
+ record.update_attributes(:status => handlee) unless record.nil?
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,7 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Bounced < Base
4
+ register_as_handler_for :bounce
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Clicked < Base
4
+ register_as_handler_for :click
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Deferred < Base
4
+ register_as_handler_for :deferred
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Delivered < Base
4
+ # Delivered
5
+ # event | email | response | category
6
+ # delivered | Message recipient | Full reponse from MTA | The category you assigned
7
+ register_as_handler_for :delivered
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,34 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Dispatch
4
+ class << self
5
+ attr_accessor :registered_handlers, :selected_handlers
6
+ end
7
+
8
+ def self.registered_handlers
9
+ @registered_handlers ||= {}.with_indifferent_access
10
+ end
11
+
12
+ def self.acceptable_handlers
13
+ @acceptable_handlers ||= begin
14
+ array = %w[processed
15
+ deferred
16
+ delivered
17
+ open
18
+ click
19
+ bounce
20
+ dropped
21
+ spamreport
22
+ unsubscribe
23
+ ]
24
+ Hash[array.zip([true] * array.size)].with_indifferent_access
25
+ end
26
+ end
27
+
28
+ def self.selected_handlers=(handler_list)
29
+ raise ArgumentError, "Found an unaccetable handler" unless handler_list.all? { |x| acceptable_handlers[x.to_sym] }
30
+ @selected_handlers = Hash[handler_list.zip([true] * handler_list.size)].with_indifferent_access
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Dropped < Base
4
+ register_as_handler_for :dropped
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Opened < Base
4
+ register_as_handler_for :open
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Processed < Base
4
+ register_as_handler_for :processed
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class SpamReported < Base
4
+ register_as_handler_for :spamreport
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module SendgridEvents
2
+ module Handlers
3
+ class Unsubscribed < Base
4
+ register_as_handler_for :unsubscribe
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ require 'sendgrid_events/handlers/dispatch'
2
+ require 'sendgrid_events/handlers/base'
3
+ Dir.glob(File.expand_path('../handlers/**/*.rb', __FILE__)).each { |file| require file }
@@ -0,0 +1,22 @@
1
+ module SendgridEvents
2
+ class Middleware
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def call(env)
8
+ scrub(env) if env and env["REQUEST_URI"] and env["REQUEST_URI"].include? Configure.mount_at
9
+ @app.call(env)
10
+ end
11
+
12
+ private
13
+ def scrub(env)
14
+ rack_input = env["rack.input"].read
15
+ rack_input ="[#{rack_input.split("\r\n").join(",")}]"
16
+ env["rack.input"] = StringIO.new(rack_input)
17
+ rescue
18
+ ensure
19
+ env["rack.input"].rewind
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ module SendgridEvents
2
+ class Receiver
3
+ def self.receive(params)
4
+ if Configure.receive? and params['_json'] and params['_json'].is_a? Array
5
+
6
+ SendgridEmailRecord.transaction do
7
+ params['_json'].each do |event|
8
+ if event.is_a? Hash and event.has_key? Configure.foreign_key
9
+ event = event.with_indifferent_access
10
+ Handlers::Base.choose_and_handle(event)
11
+ end
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module SendgridEvents
2
+ VERSION = "0.1.4"
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'active_support/core_ext/string'
2
+ require 'sendgrid-rails'
3
+ require 'sendgrid_events/version'
4
+ require 'sendgrid_events/engine'
5
+ require 'sendgrid_events/handlers'
6
+ require 'sendgrid_events/receiver'
7
+ require 'sendgrid_events/action_mailer_override'
8
+ require 'sendgrid_events/configure'
9
+ require 'sendgrid_events/middleware'