diff options
Diffstat (limited to 'actionmailer/lib')
-rw-r--r-- | actionmailer/lib/action_mailer.rb | 2 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/base.rb | 169 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/gem_version.rb | 2 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/log_subscriber.rb | 6 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/railtie.rb | 23 | ||||
-rw-r--r-- | actionmailer/lib/action_mailer/test_case.rb | 17 | ||||
-rw-r--r-- | actionmailer/lib/rails/generators/mailer/mailer_generator.rb | 3 | ||||
-rw-r--r-- | actionmailer/lib/rails/generators/mailer/templates/application_mailer.rb | 4 |
8 files changed, 129 insertions, 97 deletions
diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb index 312dd1997c..55c017e338 100644 --- a/actionmailer/lib/action_mailer.rb +++ b/actionmailer/lib/action_mailer.rb @@ -1,5 +1,5 @@ #-- -# Copyright (c) 2004-2015 David Heinemeier Hansson +# Copyright (c) 2004-2016 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index cbd7cec70f..559cd06d91 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -430,6 +430,7 @@ module ActionMailer include AbstractController::Translation include AbstractController::AssetPaths include AbstractController::Callbacks + include AbstractController::Caching include ActionView::Layouts @@ -464,30 +465,26 @@ module ActionMailer # 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 = case observer - when String, Symbol - observer.to_s.camelize.constantize - else - observer - end - - Mail.register_observer(delivery_observer) + Mail.register_observer(observer_class_for(observer)) end # 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. def register_interceptor(interceptor) - delivery_interceptor = case interceptor - when String, Symbol - interceptor.to_s.camelize.constantize - else - interceptor - end - - Mail.register_interceptor(delivery_interceptor) + Mail.register_interceptor(observer_class_for(interceptor)) end + def observer_class_for(value) # :nodoc: + case value + when String, Symbol + value.to_s.camelize.constantize + else + value + end + end + private :observer_class_for + # Returns the name of current mailer. This method is also being used as a path for a view lookup. # If this is an anonymous mailer, this method will return +anonymous+ instead. def mailer_name @@ -545,10 +542,6 @@ module ActionMailer end end - def respond_to?(method, include_private = false) #:nodoc: - super || action_methods.include?(method.to_s) - end - protected def set_payload_for_mail(payload, mail) #:nodoc: @@ -570,6 +563,12 @@ module ActionMailer super end end + + private + + def respond_to_missing?(method, include_all = false) #:nodoc: + action_methods.include?(method.to_s) + end end attr_internal :message @@ -660,21 +659,21 @@ module ActionMailer # # mail.attachments['filename.jpg'] = File.read('/path/to/filename.jpg') # - # If you do this, then Mail will take the file name and work out the mime type - # set the Content-Type, Content-Disposition, Content-Transfer-Encoding and - # base64 encode the contents of the attachment all for you. + # If you do this, then Mail will take the file name and work out the mime type. + # It will also set the Content-Type, Content-Disposition, Content-Transfer-Encoding + # and encode the contents of the attachment in Base64. # # You can also specify overrides if you want by passing a hash instead of a string: # - # mail.attachments['filename.jpg'] = {mime_type: 'application/x-gzip', + # mail.attachments['filename.jpg'] = {mime_type: 'application/gzip', # content: File.read('/path/to/filename.jpg')} # - # If you want to use a different encoding than Base64, you can pass an encoding in, - # but then it is up to you to pass in the content pre-encoded, and don't expect - # Mail to know how to decode this data: + # If you want to use encoding other than Base64 then you will need to pass encoding + # type along with the pre-encoded content as Mail doesn't know how to decode the + # data: # # file_content = SpecialEncode(File.read('/path/to/filename.jpg')) - # mail.attachments['filename.jpg'] = {mime_type: 'application/x-gzip', + # mail.attachments['filename.jpg'] = {mime_type: 'application/gzip', # encoding: 'SpecialEncoding', # content: file_content } # @@ -796,52 +795,40 @@ module ActionMailer # end # def mail(headers = {}, &block) - return @_message if @_mail_was_called && headers.blank? && !block - - m = @_message + return message if @_mail_was_called && headers.blank? && !block # At the beginning, do not consider class default for content_type content_type = headers[:content_type] - # Call all the procs (if any) - default_values = {} - self.class.default.each do |k,v| - default_values[k] = v.is_a?(Proc) ? instance_eval(&v) : v - end - - # Handle defaults - headers = headers.reverse_merge(default_values) - headers[:subject] ||= default_i18n_subject + headers = apply_defaults(headers) # Apply charset at the beginning so all fields are properly quoted - m.charset = charset = headers[:charset] + message.charset = charset = headers[:charset] # Set configure delivery behavior - wrap_delivery_behavior!(headers.delete(:delivery_method), headers.delete(:delivery_method_options)) + wrap_delivery_behavior!(headers[:delivery_method], headers[:delivery_method_options]) - # Assign all headers except parts_order, content_type, body, template_name, and template_path - assignable = headers.except(:parts_order, :content_type, :body, :template_name, :template_path) - assignable.each { |k, v| m[k] = v } + assign_headers_to_message(message, headers) # Render the templates and blocks responses = collect_responses(headers, &block) @_mail_was_called = true - create_parts_from_responses(m, responses) + create_parts_from_responses(message, responses) # Setup content type, reapply charset and handle parts order - m.content_type = set_content_type(m, content_type, headers[:content_type]) - m.charset = charset + message.content_type = set_content_type(message, content_type, headers[:content_type]) + message.charset = charset - if m.multipart? - m.body.set_sort_order(headers[:parts_order]) - m.body.sort_parts! + if message.multipart? + message.body.set_sort_order(headers[:parts_order]) + message.body.sort_parts! end - m + message end - protected + protected # Used by #mail to set the content type of the message. # @@ -879,36 +866,61 @@ module ActionMailer I18n.t(:subject, interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize)) end - def collect_responses(headers) #:nodoc: - responses = [] + # Emails do not support relative path links. + def self.supports_path? + false + end + + private + def apply_defaults(headers) + default_values = self.class.default.map do |key, value| + [ + key, + value.is_a?(Proc) ? instance_eval(&value) : value + ] + end.to_h + + headers_with_defaults = headers.reverse_merge(default_values) + headers_with_defaults[:subject] ||= default_i18n_subject + headers_with_defaults + end + + def assign_headers_to_message(message, headers) + assignable = headers.except(:parts_order, :content_type, :body, :template_name, + :template_path, :delivery_method, :delivery_method_options) + assignable.each { |k, v| message[k] = v } + end + + def collect_responses(headers) if block_given? collector = ActionMailer::Collector.new(lookup_context) { render(action_name) } yield(collector) - responses = collector.responses + collector.responses elsif headers[:body] - responses << { + [{ body: headers.delete(:body), content_type: self.class.default[:content_type] || "text/plain" - } + }] else - templates_path = headers.delete(:template_path) || self.class.mailer_name - templates_name = headers.delete(:template_name) || action_name + collect_responses_from_templates(headers) + end + end - each_template(Array(templates_path), templates_name) do |template| - self.formats = template.formats + def collect_responses_from_templates(headers) + templates_path = headers[:template_path] || self.class.mailer_name + templates_name = headers[:template_name] || action_name - responses << { - body: render(template: template), - content_type: template.type.to_s - } - end + each_template(Array(templates_path), templates_name).map do |template| + self.formats = template.formats + { + body: render(template: template), + content_type: template.type.to_s + } end - - responses end - def each_template(paths, name, &block) #:nodoc: + def each_template(paths, name, &block) templates = lookup_context.find_all(name, paths) if templates.empty? raise ActionView::MissingTemplate.new(paths, name, paths, false, 'mailer') @@ -917,7 +929,7 @@ module ActionMailer end end - def create_parts_from_responses(m, responses) #:nodoc: + def create_parts_from_responses(m, responses) if responses.size == 1 && !m.has_attachments? responses[0].each { |k,v| m[k] = v } elsif responses.size > 1 && m.has_attachments? @@ -930,15 +942,22 @@ module ActionMailer end end - def insert_part(container, response, charset) #:nodoc: + def insert_part(container, response, charset) response[:charset] ||= charset part = Mail::Part.new(response) container.add_part(part) end - # Emails do not support relative path links. - def self.supports_path? - false + # This and #instrument_name is for caching instrument + def instrument_payload(key) + { + mailer: mailer_name, + key: key + } + end + + def instrument_name + "action_mailer" end ActiveSupport.run_load_hooks(:action_mailer, self) diff --git a/actionmailer/lib/action_mailer/gem_version.rb b/actionmailer/lib/action_mailer/gem_version.rb index b35d2ed965..cbe5fc3e64 100644 --- a/actionmailer/lib/action_mailer/gem_version.rb +++ b/actionmailer/lib/action_mailer/gem_version.rb @@ -8,7 +8,7 @@ module ActionMailer MAJOR = 5 MINOR = 0 TINY = 0 - PRE = "alpha" + PRE = "beta3" STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") end diff --git a/actionmailer/lib/action_mailer/log_subscriber.rb b/actionmailer/lib/action_mailer/log_subscriber.rb index 7e9d916b66..2867bf90fb 100644 --- a/actionmailer/lib/action_mailer/log_subscriber.rb +++ b/actionmailer/lib/action_mailer/log_subscriber.rb @@ -8,7 +8,7 @@ module ActionMailer def deliver(event) info do recipients = Array(event.payload[:to]).join(', ') - "\nSent mail to #{recipients} (#{event.duration.round(1)}ms)" + "Sent mail to #{recipients} (#{event.duration.round(1)}ms)" end debug { event.payload[:mail] } @@ -16,7 +16,7 @@ module ActionMailer # An email was received. def receive(event) - info { "\nReceived mail (#{event.duration.round(1)}ms)" } + info { "Received mail (#{event.duration.round(1)}ms)" } debug { event.payload[:mail] } end @@ -25,7 +25,7 @@ module ActionMailer debug do mailer = event.payload[:mailer] action = event.payload[:action] - "\n#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms" + "#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms" end end diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index fa707021c7..215d0199af 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -25,6 +25,7 @@ module ActionMailer options.javascripts_dir ||= paths["public/javascripts"].first options.stylesheets_dir ||= paths["public/stylesheets"].first options.show_previews = Rails.env.development? if options.show_previews.nil? + options.cache_store ||= Rails.cache if options.show_previews options.preview_path ||= defined?(Rails.root) ? "#{Rails.root}/test/mailers/previews" : nil @@ -45,12 +46,7 @@ module ActionMailer options.each { |k,v| send("#{k}=", v) } - if options.show_previews - app.routes.prepend do - get '/rails/mailers' => "rails/mailers#index" - get '/rails/mailers/*path' => "rails/mailers#preview" - end - end + ActionDispatch::IntegrationTest.send :include, ActionMailer::TestCase::ClearTestDeliveries end end @@ -60,9 +56,18 @@ module ActionMailer end end - config.after_initialize do - if ActionMailer::Base.preview_path - ActiveSupport::Dependencies.autoload_paths << ActionMailer::Base.preview_path + config.after_initialize do |app| + options = app.config.action_mailer + + if options.show_previews + app.routes.prepend do + get '/rails/mailers' => "rails/mailers#index", internal: true + get '/rails/mailers/*path' => "rails/mailers#preview", internal: true + end + + if options.preview_path + ActiveSupport::Dependencies.autoload_paths << options.preview_path + end end end end diff --git a/actionmailer/lib/action_mailer/test_case.rb b/actionmailer/lib/action_mailer/test_case.rb index 0aa15e31ba..d83719e57d 100644 --- a/actionmailer/lib/action_mailer/test_case.rb +++ b/actionmailer/lib/action_mailer/test_case.rb @@ -11,6 +11,21 @@ module ActionMailer end class TestCase < ActiveSupport::TestCase + module ClearTestDeliveries + extend ActiveSupport::Concern + + included do + teardown :clear_test_deliviers + end + + private + def clear_test_deliviers + if ActionMailer::Base.delivery_method == :test + ActionMailer::Base.deliveries.clear + end + end + end + module Behavior extend ActiveSupport::Concern @@ -66,7 +81,6 @@ module ActionMailer def restore_test_deliveries # :nodoc: restore_delivery_method ActionMailer::Base.perform_deliveries = @old_perform_deliveries - ActionMailer::Base.deliveries.clear end def set_delivery_method(method) # :nodoc: @@ -100,5 +114,6 @@ module ActionMailer end include Behavior + include ClearTestDeliveries end end diff --git a/actionmailer/lib/rails/generators/mailer/mailer_generator.rb b/actionmailer/lib/rails/generators/mailer/mailer_generator.rb index 3ec7d3d896..5a5c9d32bb 100644 --- a/actionmailer/lib/rails/generators/mailer/mailer_generator.rb +++ b/actionmailer/lib/rails/generators/mailer/mailer_generator.rb @@ -9,9 +9,6 @@ module Rails def create_mailer_file template "mailer.rb", File.join('app/mailers', class_path, "#{file_name}_mailer.rb") - if self.behavior == :invoke - template "application_mailer.rb", 'app/mailers/application_mailer.rb' - end end hook_for :template_engine, :test_framework diff --git a/actionmailer/lib/rails/generators/mailer/templates/application_mailer.rb b/actionmailer/lib/rails/generators/mailer/templates/application_mailer.rb deleted file mode 100644 index d25d8892dd..0000000000 --- a/actionmailer/lib/rails/generators/mailer/templates/application_mailer.rb +++ /dev/null @@ -1,4 +0,0 @@ -class ApplicationMailer < ActionMailer::Base - default from: "from@example.com" - layout 'mailer' -end |