From 4dbc62dabd9decbeed74f30f36062355e10def6b Mon Sep 17 00:00:00 2001 From: Waynn Lue Date: Mon, 13 Jan 2014 11:56:00 -0800 Subject: e-mail => email, and subject/verb agreement --- actionmailer/README.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionmailer') diff --git a/actionmailer/README.rdoc b/actionmailer/README.rdoc index c3dcd3c3e4..e425282fa8 100644 --- a/actionmailer/README.rdoc +++ b/actionmailer/README.rdoc @@ -74,7 +74,7 @@ Or you can just chain the methods together like: == Setting defaults -It is possible to set default values that will be used in every method in your Action Mailer class. To implement this functionality, you just call the public class method default which you get for free from ActionMailer::Base. This method accepts a Hash as the parameter. You can use any of the headers e-mail messages has, like :from as the key. You can also pass in a string as the key, like "Content-Type", but Action Mailer does this out of the box for you, so you won't need to worry about that. Finally, it is also possible to pass in a Proc that will get evaluated when it is needed. +It is possible to set default values that will be used in every method in your Action Mailer class. To implement this functionality, you just call the public class method default which you get for free from ActionMailer::Base. This method accepts a Hash as the parameter. You can use any of the headers email messages have, like :from as the key. You can also pass in a string as the key, like "Content-Type", but Action Mailer does this out of the box for you, so you won't need to worry about that. Finally, it is also possible to pass in a Proc that will get evaluated when it is needed. Note that every value you set with this method will get overwritten if you use the same key in your mailer method. -- cgit v1.2.3 From 080fc9cad39a98b6973cd7a7106f1bcb10d3ad02 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Mon, 20 Jan 2014 15:04:36 +0100 Subject: docs should say `email` not `Email`. [ci skip] --- actionmailer/lib/action_mailer/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index a30e3e65da..41db62cc58 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -51,7 +51,7 @@ module ActionMailer # * mail - Allows you to specify email to be sent. # # The hash passed to the mail method allows you to specify any header that a Mail::Message - # will accept (any valid Email header including optional fields). + # will accept (any valid email header including optional fields). # # The mail method, if not passed a block, will inspect your views and send all the views with # the same name as the method, so the above action would send the +welcome.text.erb+ view -- cgit v1.2.3 From 35fd81672e02497c31f0b3cab965f4a38090229a Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sun, 26 Jan 2014 11:38:30 +0000 Subject: Add the ability to intercept emails before previewing To support the ability for tools like CSS style inliners to operate on emails being previewed this commit adds a hook in a similar fashion to the existing delivery interceptor hook, e.g: class CSSInlineStyler def self.previewing_email(message) # inline CSS styles end end ActionMailer::Base.register_preview_interceptor CSSInlineStyler Fixes #13622. --- actionmailer/CHANGELOG.md | 15 +++++++++++ actionmailer/lib/action_mailer/base.rb | 15 +++++++++++ actionmailer/lib/action_mailer/preview.rb | 39 +++++++++++++++++++++++++-- actionmailer/test/base_test.rb | 45 ++++++++++++++++++++++++++++--- 4 files changed, 109 insertions(+), 5 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index 1867a392eb..ede8cfccbf 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,18 @@ +* Add the ability to intercept emails before previewing in a similar fashion + to how emails can be intercepted before delivery, e.g: + + class CSSInlineStyler + def self.previewing_email(message) + # inline CSS styles + end + end + + ActionMailer::Base.register_preview_interceptor CSSInlineStyler + + Fixes #13622. + + *Andrew White* + * Add mailer previews feature based on 37 Signals mail_view gem *Andrew White* diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 41db62cc58..5af0217973 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -330,6 +330,21 @@ module ActionMailer # An overview of all previews is accessible at http://localhost:3000/rails/mailers # on a running development server instance. # + # Previews can also be intercepted in a similar manner as deliveries can be by registering + # a preview interceptor that has a previewing_email method: + # + # class CssInlineStyler + # def self.previewing_email(message) + # # inline CSS styles + # end + # end + # + # config.action_mailer.register_preview_interceptor :css_inline_styler + # + # Note that interceptors need to be registered both with register_interceptor + # and register_preview_interceptor if they should operate on both sending and + # previewing emails. + # # = Configuration options # # These options are specified on the class level, like diff --git a/actionmailer/lib/action_mailer/preview.rb b/actionmailer/lib/action_mailer/preview.rb index ecceaf8c70..0efd702e4d 100644 --- a/actionmailer/lib/action_mailer/preview.rb +++ b/actionmailer/lib/action_mailer/preview.rb @@ -10,6 +10,31 @@ module ActionMailer # config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews" # class_attribute :preview_path, instance_writer: false + + # :nodoc: + mattr_accessor :preview_interceptors, instance_writer: false + self.preview_interceptors = [] + + # Register one or more Interceptors which will be called before mail is previewed. + def register_preview_interceptors(*interceptors) + interceptors.flatten.compact.each { |interceptor| register_preview_interceptor(interceptor) } + end + + # Register am Interceptor which will be called before mail is previewed. + # Either a class or a string can be passed in as the Interceptor. If a + # string is passed in it will be constantized. + def register_preview_interceptor(interceptor) + preview_interceptor = case interceptor + when String, Symbol + interceptor.to_s.camelize.constantize + else + interceptor + end + + unless preview_interceptors.include?(preview_interceptor) + preview_interceptors << preview_interceptor + end + end end end @@ -23,10 +48,14 @@ module ActionMailer descendants end - # Returns the mail object for the given email name + # Returns the mail object for the given email name. The registered preview + # interceptors will be informed so that they can transform the message + # as they would if the mail was actually being delivered. def call(email) preview = self.new - preview.public_send(email) + message = preview.public_send(email) + inform_preview_interceptors(message) + message end # Returns all of the available email previews @@ -68,6 +97,12 @@ module ActionMailer def preview_path? #:nodoc: Base.preview_path? end + + def inform_preview_interceptors(message) #:nodoc: + Base.preview_interceptors.each do |interceptor| + interceptor.previewing_email(message) + end + end end end end diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index c1759d9b92..454e1afe97 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -539,12 +539,18 @@ class BaseTest < ActiveSupport::TestCase end class MyInterceptor - def self.delivering_email(mail) - end + def self.delivering_email(mail); end + def self.previewing_email(mail); end end class MySecondInterceptor - def self.delivering_email(mail) + def self.delivering_email(mail); end + def self.previewing_email(mail); end + end + + class BaseMailerPreview < ActionMailer::Preview + def welcome + BaseMailer.welcome end end @@ -570,6 +576,39 @@ class BaseTest < ActiveSupport::TestCase mail.deliver end + test "you can register a preview interceptor to the mail object that gets passed the mail object before previewing" do + ActionMailer::Base.register_preview_interceptor(MyInterceptor) + mail = BaseMailer.welcome + BaseMailerPreview.stubs(:welcome).returns(mail) + MyInterceptor.expects(:previewing_email).with(mail) + BaseMailerPreview.call(:welcome) + end + + test "you can register a preview interceptor using its stringified name to the mail object that gets passed the mail object before previewing" do + ActionMailer::Base.register_preview_interceptor("BaseTest::MyInterceptor") + mail = BaseMailer.welcome + BaseMailerPreview.stubs(:welcome).returns(mail) + MyInterceptor.expects(:previewing_email).with(mail) + BaseMailerPreview.call(:welcome) + end + + test "you can register an interceptor using its symbolized underscored name to the mail object that gets passed the mail object before previewing" do + ActionMailer::Base.register_preview_interceptor(:"base_test/my_interceptor") + mail = BaseMailer.welcome + BaseMailerPreview.stubs(:welcome).returns(mail) + MyInterceptor.expects(:previewing_email).with(mail) + BaseMailerPreview.call(:welcome) + end + + test "you can register multiple preview interceptors to the mail object that both get passed the mail object before previewing" do + ActionMailer::Base.register_preview_interceptors("BaseTest::MyInterceptor", MySecondInterceptor) + mail = BaseMailer.welcome + BaseMailerPreview.stubs(:welcome).returns(mail) + MyInterceptor.expects(:previewing_email).with(mail) + MySecondInterceptor.expects(:previewing_email).with(mail) + BaseMailerPreview.call(:welcome) + end + test "being able to put proc's into the defaults hash and they get evaluated on mail sending" do mail1 = ProcMailer.welcome['X-Proc-Method'] yesterday = 1.day.ago -- cgit v1.2.3 From 7d86352f83079458dd04df2ee5e1b38179c3aac3 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sun, 26 Jan 2014 11:50:36 +0000 Subject: Don't use a class_attribute for ActionMailer::Base.preview_path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since preview_path is read from ActionMailer::Base when previewing, subclasses can’t change it so don’t there's no need for the extra overhead imposed by using it. --- actionmailer/lib/action_mailer/preview.rb | 8 ++------ actionmailer/lib/action_mailer/railtie.rb | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/preview.rb b/actionmailer/lib/action_mailer/preview.rb index 0efd702e4d..fde0e86f5b 100644 --- a/actionmailer/lib/action_mailer/preview.rb +++ b/actionmailer/lib/action_mailer/preview.rb @@ -9,7 +9,7 @@ module ActionMailer # # config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews" # - class_attribute :preview_path, instance_writer: false + mattr_accessor :preview_path, instance_writer: false # :nodoc: mattr_accessor :preview_interceptors, instance_writer: false @@ -85,7 +85,7 @@ module ActionMailer protected def load_previews #:nodoc: - if preview_path? + if preview_path Dir["#{preview_path}/**/*_preview.rb"].each{ |file| require_dependency file } end end @@ -94,10 +94,6 @@ module ActionMailer Base.preview_path end - def preview_path? #:nodoc: - Base.preview_path? - end - def inform_preview_interceptors(message) #:nodoc: Base.preview_interceptors.each do |interceptor| interceptor.previewing_email(message) diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index c893ddfef5..8d1e40297b 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -46,7 +46,7 @@ module ActionMailer end config.after_initialize do - if ActionMailer::Base.preview_path? + if ActionMailer::Base.preview_path ActiveSupport::Dependencies.autoload_paths << ActionMailer::Base.preview_path end end -- cgit v1.2.3 From 4df9cc29c15634de8de5912d2b40766f04e58c03 Mon Sep 17 00:00:00 2001 From: Andrew White Date: Sun, 26 Jan 2014 12:03:32 +0000 Subject: Support underscored symbols in Action Mailer config We allow the use of underscored symbols to represent classes throughout other parts of Rails so it seems incongruous that it's not supported in `register_interceptor` and `register_observer`. --- actionmailer/CHANGELOG.md | 5 +++++ actionmailer/lib/action_mailer/base.rb | 23 ++++++++++++++++++----- actionmailer/test/base_test.rb | 14 ++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index ede8cfccbf..c264c710f6 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -1,3 +1,8 @@ +* Support the use of underscored symbols when registering interceptors and + observers like we do elsewhere within Rails. + + *Andrew White* + * Add the ability to intercept emails before previewing in a similar fashion to how emails can be intercepted before delivery, e.g: diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 5af0217973..76814d336b 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -444,18 +444,31 @@ module ActionMailer end # Register an Observer which will be notified when mail is delivered. - # Either a class or a string can be passed in as the Observer. If a string is passed in - # it will be constantized. + # Either a class, string or symbol can be passed in as the Observer. + # If a string or symbol is passed in it will be camelized and constantized. def register_observer(observer) - delivery_observer = (observer.is_a?(String) ? observer.constantize : observer) + delivery_observer = case observer + when String, Symbol + observer.to_s.camelize.constantize + else + observer + end + Mail.register_observer(delivery_observer) end # Register an Interceptor which will be called before mail is sent. - # Either a class or a string can be passed in as the Interceptor. If a string is passed in + # Either a class, string or symbol can be passed in as the Interceptor. + # If a string or symbol is passed in it will be camelized and constantized. # it will be constantized. def register_interceptor(interceptor) - delivery_interceptor = (interceptor.is_a?(String) ? interceptor.constantize : interceptor) + delivery_interceptor = case interceptor + when String, Symbol + interceptor.to_s.camelize.constantize + else + interceptor + end + Mail.register_interceptor(delivery_interceptor) end diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index 454e1afe97..02707d0b5f 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -530,6 +530,13 @@ class BaseTest < ActiveSupport::TestCase mail.deliver end + test "you can register an observer using its symbolized underscored name to the mail object that gets informed on email delivery" do + ActionMailer::Base.register_observer(:"base_test/my_observer") + mail = BaseMailer.welcome + MyObserver.expects(:delivered_email).with(mail) + mail.deliver + end + test "you can register multiple observers to the mail object that both get informed on email delivery" do ActionMailer::Base.register_observers("BaseTest::MyObserver", MySecondObserver) mail = BaseMailer.welcome @@ -568,6 +575,13 @@ class BaseTest < ActiveSupport::TestCase mail.deliver end + test "you can register an interceptor using its symbolized underscored name to the mail object that gets passed the mail object before delivery" do + ActionMailer::Base.register_interceptor(:"base_test/my_interceptor") + mail = BaseMailer.welcome + MyInterceptor.expects(:delivering_email).with(mail) + mail.deliver + end + test "you can register multiple interceptors to the mail object that both get passed the mail object before delivery" do ActionMailer::Base.register_interceptors("BaseTest::MyInterceptor", MySecondInterceptor) mail = BaseMailer.welcome -- cgit v1.2.3 From 718d3b0bc53bb5da4e5fc32d1a27f2119e6c747c Mon Sep 17 00:00:00 2001 From: Robin Dupret Date: Sun, 26 Jan 2014 13:11:26 +0100 Subject: Remove an extra comment [ci skip] --- actionmailer/lib/action_mailer/base.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 76814d336b..388f694590 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -460,7 +460,6 @@ module ActionMailer # Register an Interceptor which will be called before mail is sent. # Either a class, string or symbol can be passed in as the Interceptor. # If a string or symbol is passed in it will be camelized and constantized. - # it will be constantized. def register_interceptor(interceptor) delivery_interceptor = case interceptor when String, Symbol -- cgit v1.2.3 From 02f9f3314244513fce0a94acef08318d67d6707f Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Thu, 30 Jan 2014 11:12:46 +0100 Subject: tidy CHANGELOGs [ci skip] --- actionmailer/CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md index c264c710f6..5a61746700 100644 --- a/actionmailer/CHANGELOG.md +++ b/actionmailer/CHANGELOG.md @@ -4,7 +4,11 @@ *Andrew White* * Add the ability to intercept emails before previewing in a similar fashion - to how emails can be intercepted before delivery, e.g: + to how emails can be intercepted before delivery. + + Fixes #13622. + + Example: class CSSInlineStyler def self.previewing_email(message) @@ -14,11 +18,9 @@ ActionMailer::Base.register_preview_interceptor CSSInlineStyler - Fixes #13622. - *Andrew White* -* Add mailer previews feature based on 37 Signals mail_view gem +* Add mailer previews feature based on 37 Signals mail_view gem. *Andrew White* -- cgit v1.2.3 From 5af7cab02ddd95e6813738e9de69b64fe560dbcd Mon Sep 17 00:00:00 2001 From: Dmitry Polushkin Date: Sun, 9 Feb 2014 18:41:41 +0000 Subject: add actionmailer test coverage for undefined delivery method --- actionmailer/lib/action_mailer/base.rb | 2 +- actionmailer/test/delivery_methods_test.rb | 29 ++++++++++++++++++++--------- 2 files changed, 21 insertions(+), 10 deletions(-) (limited to 'actionmailer') diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 388f694590..eb8cca9ee4 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -764,7 +764,7 @@ module ActionMailer m.charset = charset = headers[:charset] # Set configure delivery behavior - wrap_delivery_behavior!(headers.delete(:delivery_method),headers.delete(:delivery_method_options)) + wrap_delivery_behavior!(headers.delete(:delivery_method), headers.delete(:delivery_method_options)) # Assign all headers except parts_order, content_type and body assignable = headers.except(:parts_order, :content_type, :body, :template_name, :template_path) diff --git a/actionmailer/test/delivery_methods_test.rb b/actionmailer/test/delivery_methods_test.rb index 20412c7bb2..609903620b 100644 --- a/actionmailer/test/delivery_methods_test.rb +++ b/actionmailer/test/delivery_methods_test.rb @@ -38,8 +38,10 @@ class DefaultsDeliveryMethodsTest < ActiveSupport::TestCase end test "default sendmail settings" do - settings = {location: '/usr/sbin/sendmail', - arguments: '-i -t'} + settings = { + location: '/usr/sbin/sendmail', + arguments: '-i -t' + } assert_equal settings, ActionMailer::Base.sendmail_settings end end @@ -138,13 +140,15 @@ class MailDeliveryTest < ActiveSupport::TestCase end test "default delivery options can be overridden per mail instance" do - settings = { address: "localhost", - port: 25, - domain: 'localhost.localdomain', - user_name: nil, - password: nil, - authentication: nil, - enable_starttls_auto: true } + settings = { + address: "localhost", + port: 25, + domain: 'localhost.localdomain', + user_name: nil, + password: nil, + authentication: nil, + enable_starttls_auto: true + } assert_equal settings, ActionMailer::Base.smtp_settings overridden_options = {user_name: "overridden", password: "somethingobtuse"} mail_instance = DeliveryMailer.welcome(delivery_method_options: overridden_options) @@ -164,6 +168,13 @@ class MailDeliveryTest < ActiveSupport::TestCase end end + test "undefined delivery methods raises errors" do + DeliveryMailer.delivery_method = nil + assert_raise RuntimeError do + DeliveryMailer.welcome.deliver + end + end + test "does not perform deliveries if requested" do DeliveryMailer.perform_deliveries = false DeliveryMailer.deliveries.clear -- cgit v1.2.3