mandrill-mailer-rails 0.0.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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/Appraisals +19 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +115 -0
  6. data/LICENSE +21 -0
  7. data/README.md +35 -0
  8. data/Rakefile +4 -0
  9. data/gemfiles/rails_30.gemfile +7 -0
  10. data/gemfiles/rails_30.gemfile.lock +122 -0
  11. data/gemfiles/rails_31.gemfile +7 -0
  12. data/gemfiles/rails_31.gemfile.lock +122 -0
  13. data/gemfiles/rails_32.gemfile +7 -0
  14. data/gemfiles/rails_32.gemfile.lock +122 -0
  15. data/gemfiles/rails_40.gemfile +7 -0
  16. data/gemfiles/rails_40.gemfile.lock +116 -0
  17. data/gemfiles/rails_41.gemfile +7 -0
  18. data/gemfiles/rails_41.gemfile.lock +116 -0
  19. data/lib/mandrill-mailer-rails.rb +2 -0
  20. data/lib/mandrill_action_mailer.rb +10 -0
  21. data/lib/mandrill_action_mailer/delivery_handler.rb +54 -0
  22. data/lib/mandrill_action_mailer/railtie.rb +12 -0
  23. data/mandrill-mailer-rails.gemspec +22 -0
  24. data/spec/integration/deliver_handler_spec.rb +166 -0
  25. data/spec/rails_app/.gitignore +3 -0
  26. data/spec/rails_app/Rakefile +6 -0
  27. data/spec/rails_app/app/mailers/notifier.rb +35 -0
  28. data/spec/rails_app/app/views/notifier/multipart.html.erb +1 -0
  29. data/spec/rails_app/app/views/notifier/multipart.text.erb +1 -0
  30. data/spec/rails_app/app/views/notifier/test.text.erb +1 -0
  31. data/spec/rails_app/bin/bundle +3 -0
  32. data/spec/rails_app/bin/rails +4 -0
  33. data/spec/rails_app/bin/rake +4 -0
  34. data/spec/rails_app/config.ru +4 -0
  35. data/spec/rails_app/config/application.rb +61 -0
  36. data/spec/rails_app/config/boot.rb +5 -0
  37. data/spec/rails_app/config/environment.rb +5 -0
  38. data/spec/rails_app/config/environments/test.rb +39 -0
  39. data/spec/rails_app/config/initializers/assets.rb +8 -0
  40. data/spec/rails_app/config/initializers/cookies_serializer.rb +3 -0
  41. data/spec/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
  42. data/spec/rails_app/config/initializers/session_store.rb +3 -0
  43. data/spec/rails_app/config/initializers/wrap_parameters.rb +9 -0
  44. data/spec/rails_app/config/routes.rb +56 -0
  45. data/spec/rails_app/config/secrets.yml +14 -0
  46. data/spec/spec_helper.rb +30 -0
  47. metadata +195 -0
@@ -0,0 +1,12 @@
1
+ require 'rails/railtie'
2
+ require 'mandrill_action_mailer/delivery_handler'
3
+
4
+ module MandrillActionMailer
5
+ class Railtie < Rails::Railtie
6
+ config.mandrill_action_mailer = MandrillActionMailer.config
7
+
8
+ initializer 'mandrill_action_mailer.add_delivery_method' do
9
+ ActionMailer::Base.add_delivery_method(:mandrill, MandrillActionMailer::DeliveryHandler)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'mandrill-mailer-rails'
3
+ s.version = '0.0.1'
4
+ s.authors = ['Tinfoil Security, Inc.']
5
+ s.email = ['engineers@tinfoilsecurity.com']
6
+ s.homepage = 'https://www.github.com/bsedat/mandrill-mailer-rails'
7
+ s.summary = %q{Handler for Rails to send emails through Mandrill}
8
+ s.description = %q{Provides an ActionMailer delivery handler sending emails through Mandrill}
9
+
10
+ s.files = `git ls-files`.split("\n")
11
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
12
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
13
+ s.require_paths = ['lib']
14
+
15
+ s.add_dependency('mandrill-api')
16
+ s.add_dependency('rails', '> 3.0')
17
+
18
+ s.add_development_dependency('rake')
19
+ s.add_development_dependency('rspec-rails')
20
+ s.add_development_dependency('rspec-mocks')
21
+ s.add_development_dependency('appraisal')
22
+ end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'MandrillActionMailer::DeliverHandler' do
4
+ let(:client) { double('Mandrill::API') }
5
+ let(:sender) { double('Mandrill::Messages') }
6
+
7
+ before do
8
+ allow(MandrillActionMailer).to receive(:client).and_return(client)
9
+ allow(client).to receive(:messages).and_return(sender)
10
+ end
11
+
12
+ context 'when an API key is missing' do
13
+ before do
14
+ allow(MandrillActionMailer).to receive(:client).and_call_original
15
+ end
16
+
17
+ it 'should raise an error' do
18
+ expect { Notifier.test.deliver! }.to raise_error
19
+ end
20
+ end
21
+
22
+ context 'when the delivery fails' do
23
+ it 'should raise an error' do
24
+ allow(sender).to receive(:send).and_raise(RuntimeError.new)
25
+
26
+ expect { Notifier.test.deliver! }.to raise_error
27
+ end
28
+ end
29
+
30
+ context 'when the delivery is best effort' do
31
+ it 'should not raise an error' do
32
+ allow(sender).to receive(:send)
33
+
34
+ expect { Notifier.test.deliver }.to_not raise_error
35
+ end
36
+ end
37
+
38
+ it 'should send the email through the Mandrill client' do
39
+ expect(sender).to receive(:send)
40
+
41
+ Notifier.test.deliver
42
+ end
43
+
44
+ it 'should set the subject' do
45
+ expect(sender).to receive(:send).with(
46
+ hash_including(
47
+ :subject => Notifier::SUBJECT
48
+ )
49
+ )
50
+
51
+ Notifier.test.deliver
52
+ end
53
+
54
+ it 'should set the from field' do
55
+ expect(sender).to receive(:send).with(
56
+ hash_including(
57
+ :from_email => Notifier::FROM
58
+ )
59
+ )
60
+
61
+ Notifier.test.deliver
62
+ end
63
+
64
+ it 'should not set the from_name field' do
65
+ expect(sender).to receive(:send).with(
66
+ hash_excluding(:from_name)
67
+ )
68
+
69
+ Notifier.test.deliver
70
+ end
71
+
72
+ context 'when the from_name is set' do
73
+ it 'should set the from_name field' do
74
+ expect(sender).to receive(:send).with(
75
+ hash_including(
76
+ :from_name => Notifier::FROM
77
+ )
78
+ )
79
+
80
+ Notifier.test_from_name.deliver
81
+ end
82
+ end
83
+
84
+ it 'should set the to field' do
85
+ expect(sender).to receive(:send).with(
86
+ hash_including(
87
+ :to => [
88
+ {
89
+ :email => Notifier::TO,
90
+ :name => Notifier::TO
91
+ }
92
+ ]
93
+ )
94
+ )
95
+
96
+ Notifier.test.deliver
97
+ end
98
+
99
+ it 'should not set the reply-to field' do
100
+ expect(sender).to receive(:send).with(
101
+ hash_excluding(
102
+ :headers => hash_including('Reply-To')
103
+ )
104
+ )
105
+
106
+ Notifier.test.deliver
107
+ end
108
+
109
+ context 'when the reply-to field is set' do
110
+ it 'should set the reply-to field' do
111
+ expect(sender).to receive(:send).with(
112
+ hash_including(
113
+ :headers => { 'Reply-To' => Notifier::REPLY_TO }
114
+ )
115
+ )
116
+
117
+ Notifier.test_reply_to.deliver
118
+ end
119
+ end
120
+
121
+ it 'should not set the bcc field' do
122
+ expect(sender).to receive(:send).with(
123
+ hash_excluding(:bcc)
124
+ )
125
+
126
+ Notifier.test.deliver
127
+ end
128
+
129
+ context 'when the bcc is set' do
130
+ it 'should set the bcc_address field' do
131
+ expect(sender).to receive(:send).with(
132
+ hash_including(
133
+ :bcc_address => Notifier::BCC
134
+ )
135
+ )
136
+
137
+ Notifier.test_bcc.deliver
138
+ end
139
+ end
140
+
141
+ it 'should render multipart messages' do
142
+ expect(sender).to receive(:send).with(
143
+ hash_including(
144
+ :html,
145
+ :text
146
+ )
147
+ )
148
+
149
+ Notifier.multipart.deliver
150
+ end
151
+
152
+ it 'should set many to recipients' do
153
+ expect(sender).to receive(:send).with(
154
+ hash_including(
155
+ :to => Notifier::MANY_TO.map do |email|
156
+ {
157
+ :email => email,
158
+ :name => email
159
+ }
160
+ end
161
+ )
162
+ )
163
+
164
+ Notifier.to_many.deliver
165
+ end
166
+ end
@@ -0,0 +1,3 @@
1
+ tmp
2
+ log
3
+
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,35 @@
1
+ class Notifier < ActionMailer::Base
2
+ TO = 'to@example.org'
3
+ MANY_TO = [TO, 'to2@example.org']
4
+ FROM = 'from@example.org'
5
+ SUBJECT = 'Test Subject'
6
+ REPLY_TO = 'reply@example.org'
7
+ BCC = 'bcc@example.org'
8
+
9
+ default to: TO, from: FROM, subject: SUBJECT
10
+
11
+ def test
12
+ mail
13
+ end
14
+
15
+ def test_reply_to
16
+ mail reply_to: REPLY_TO, template_name: 'test'
17
+ end
18
+
19
+ def test_bcc
20
+ mail bcc: BCC, template_name: 'test'
21
+ end
22
+
23
+ def test_from_name
24
+ mail from_name: FROM, template_name: 'test'
25
+ end
26
+
27
+ def to_many
28
+ mail to: MANY_TO, template_name: 'test'
29
+ end
30
+
31
+ def multipart
32
+ mail
33
+ end
34
+
35
+ end
@@ -0,0 +1 @@
1
+ <b>HTML</b>
@@ -0,0 +1 @@
1
+ Plaintext
@@ -0,0 +1 @@
1
+ Testing!
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
3
+ require_relative '../config/boot'
4
+ require 'rails/commands'
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../config/boot'
3
+ require 'rake'
4
+ Rake.application.run
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run Rails.application
@@ -0,0 +1,61 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "action_controller/railtie"
4
+ require "action_mailer/railtie"
5
+ # require "active_resource/railtie"
6
+ require "rails/test_unit/railtie"
7
+ require "sprockets/railtie"
8
+
9
+ Bundler.require(*Rails.groups)
10
+
11
+ module TestRailsApp
12
+ class Application < Rails::Application
13
+ # Settings in config/environments/* take precedence over those specified here.
14
+ # Application configuration should go into files in config/initializers
15
+ # -- all .rb files in that directory are automatically loaded.
16
+
17
+ # Custom directories with classes and modules you want to be autoloadable.
18
+ # config.autoload_paths += %W(#{config.root}/extras)
19
+
20
+ # Only load the plugins named here, in the order given (default is alphabetical).
21
+ # :all can be used as a placeholder for all plugins not explicitly named.
22
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
23
+
24
+ # Activate observers that should always be running.
25
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
26
+
27
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
28
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
29
+ # config.time_zone = 'Central Time (US & Canada)'
30
+
31
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
32
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
33
+ # config.i18n.default_locale = :de
34
+
35
+ # Configure the default encoding used in templates for Ruby 1.9.
36
+ config.encoding = "utf-8"
37
+
38
+ # Configure sensitive parameters which will be filtered from the log file.
39
+ config.filter_parameters += [:password]
40
+
41
+ # Enable escaping HTML in JSON.
42
+ config.active_support.escape_html_entities_in_json = true
43
+
44
+ # Use SQL instead of Active Record's schema dumper when creating the database.
45
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
46
+ # like if you have constraints or database-specific column types
47
+ # config.active_record.schema_format = :sql
48
+
49
+ # Enforce whitelist mode for mass assignment.
50
+ # This will create an empty whitelist of attributes available for mass-assignment for all models
51
+ # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
52
+ # parameters by using an attr_accessible or attr_protected declaration.
53
+ # config.active_record.whitelist_attributes = true
54
+
55
+ # Enable the asset pipeline
56
+ config.assets.enabled = true
57
+
58
+ # Version of your assets, change this if you want to expire all your assets
59
+ config.assets.version = '1.0'
60
+ end
61
+ end
@@ -0,0 +1,5 @@
1
+ # Set up gems listed in the Gemfile.
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
3
+
4
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
5
+ $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)
@@ -0,0 +1,5 @@
1
+ # Load the Rails application.
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the Rails application.
5
+ Rails.application.initialize!
@@ -0,0 +1,39 @@
1
+ TestRailsApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb.
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Do not eager load code on boot. This avoids loading your whole application
11
+ # just for the purpose of running a single test. If you are using a tool that
12
+ # preloads Rails for running tests, you may have to set it to true.
13
+ config.eager_load = false
14
+
15
+ # Configure static asset server for tests with Cache-Control for performance.
16
+ config.serve_static_assets = true
17
+ config.static_cache_control = 'public, max-age=3600'
18
+
19
+ # Show full error reports and disable caching.
20
+ config.consider_all_requests_local = true
21
+ config.action_controller.perform_caching = false
22
+
23
+ # Raise exceptions instead of rendering exception templates.
24
+ config.action_dispatch.show_exceptions = false
25
+
26
+ # Disable request forgery protection in test environment.
27
+ config.action_controller.allow_forgery_protection = false
28
+
29
+ # Tell Action Mailer not to deliver emails to the real world.
30
+ # The :test delivery method accumulates sent emails in the
31
+ # ActionMailer::Base.deliveries array.
32
+ config.action_mailer.delivery_method = :mandrill
33
+
34
+ # Print deprecation notices to the stderr.
35
+ config.active_support.deprecation = :stderr
36
+
37
+ # Raises error for missing translations
38
+ # config.action_view.raise_on_missing_translations = true
39
+ end
@@ -0,0 +1,8 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Version of your assets, change this if you want to expire all your assets.
4
+ Rails.application.config.assets.version = '1.0'
5
+
6
+ # Precompile additional assets.
7
+ # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
8
+ # Rails.application.config.assets.precompile += %w( search.js )
@@ -0,0 +1,3 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ Rails.application.config.action_dispatch.cookies_serializer = :json
@@ -0,0 +1,4 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # Configure sensitive parameters which will be filtered from the log file.
4
+ Rails.application.config.filter_parameters += [:password]
@@ -0,0 +1,3 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ Rails.application.config.session_store :cookie_store, key: '_dummy_session'
@@ -0,0 +1,9 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # This file contains settings for ActionController::ParamsWrapper which
4
+ # is enabled by default.
5
+
6
+ # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7
+ ActiveSupport.on_load(:action_controller) do
8
+ wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
9
+ end
@@ -0,0 +1,56 @@
1
+ Rails.application.routes.draw do
2
+ # The priority is based upon order of creation: first created -> highest priority.
3
+ # See how all your routes lay out with "rake routes".
4
+
5
+ # You can have the root of your site routed with "root"
6
+ # root 'welcome#index'
7
+
8
+ # Example of regular route:
9
+ # get 'products/:id' => 'catalog#view'
10
+
11
+ # Example of named route that can be invoked with purchase_url(id: product.id)
12
+ # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
13
+
14
+ # Example resource route (maps HTTP verbs to controller actions automatically):
15
+ # resources :products
16
+
17
+ # Example resource route with options:
18
+ # resources :products do
19
+ # member do
20
+ # get 'short'
21
+ # post 'toggle'
22
+ # end
23
+ #
24
+ # collection do
25
+ # get 'sold'
26
+ # end
27
+ # end
28
+
29
+ # Example resource route with sub-resources:
30
+ # resources :products do
31
+ # resources :comments, :sales
32
+ # resource :seller
33
+ # end
34
+
35
+ # Example resource route with more complex sub-resources:
36
+ # resources :products do
37
+ # resources :comments
38
+ # resources :sales do
39
+ # get 'recent', on: :collection
40
+ # end
41
+ # end
42
+
43
+ # Example resource route with concerns:
44
+ # concern :toggleable do
45
+ # post 'toggle'
46
+ # end
47
+ # resources :posts, concerns: :toggleable
48
+ # resources :photos, concerns: :toggleable
49
+
50
+ # Example resource route within a namespace:
51
+ # namespace :admin do
52
+ # # Directs /admin/products/* to Admin::ProductsController
53
+ # # (app/controllers/admin/products_controller.rb)
54
+ # resources :products
55
+ # end
56
+ end