diff options
Diffstat (limited to 'actionmailer/lib/action_mailer/base.rb')
-rw-r--r-- | actionmailer/lib/action_mailer/base.rb | 103 |
1 files changed, 83 insertions, 20 deletions
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 1800ff5839..a96cbd7871 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -1,8 +1,10 @@ require 'mail' +require 'action_mailer/queued_message' require 'action_mailer/collector' -require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string/inflections' require 'active_support/core_ext/hash/except' +require 'active_support/core_ext/module/anonymous' +require 'active_support/queueing' require 'action_mailer/log_subscriber' module ActionMailer #:nodoc: @@ -14,15 +16,15 @@ module ActionMailer #:nodoc: # # $ rails generate mailer Notifier # - # The generated model inherits from <tt>ActionMailer::Base</tt>. Emails are defined by creating methods - # within the model which are then used to set variables to be used in the mail template, to - # change options on the mail, or to add attachments. + # The generated model inherits from <tt>ActionMailer::Base</tt>. A mailer model defines methods + # used to generate an email message. In these methods, you can setup variables to be used in + # the mailer views, options on the mail itself such as the <tt>:from</tt> address, and attachments. # # Examples: # # class Notifier < ActionMailer::Base # default :from => 'no-reply@example.com', - # :return_path => 'system@example.com' + # :return_path => 'system@example.com' # # def welcome(recipient) # @account = recipient @@ -183,6 +185,16 @@ module ActionMailer #:nodoc: # and the second being a <tt>application/pdf</tt> with a Base64 encoded copy of the file.pdf book # with the filename +free_book.pdf+. # + # If you need to send attachments with no content, you need to create an empty view for it, + # or add an empty body parameter like this: + # + # class ApplicationMailer < ActionMailer::Base + # def welcome(recipient) + # attachments['free_book.pdf'] = File.read('path/to/file.pdf') + # mail(:to => recipient, :subject => "New account information", :body => "") + # end + # end + # # = Inline Attachments # # You can also specify that a file should be displayed inline with other HTML. This is useful @@ -267,6 +279,38 @@ module ActionMailer #:nodoc: # set something in the defaults using a proc, and then set the same thing inside of your # mailer method, it will get over written by the mailer method. # + # It is also possible to set these default options that will be used in all mailers through + # the <tt>default_options=</tt> configuration in <tt>config/application.rb</tt>: + # + # config.action_mailer.default_options = { from: "no-reply@example.org" } + # + # = Callbacks + # + # You can specify callbacks using before_filter and after_filter for configuring your messages. + # This may be useful, for example, when you want to add default inline attachments for all + # messages sent out by a certain mailer class: + # + # class Notifier < ActionMailer::Base + # before_filter :add_inline_attachment! + # + # def welcome + # mail + # end + # + # private + # + # def add_inline_attachment! + # attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg') + # end + # end + # + # Callbacks in ActionMailer are implemented using AbstractController::Callbacks, so you + # can define and configure callbacks in the same manner that you would use callbacks in + # classes that inherit from ActionController::Base. + # + # Note that unless you have a specific reason to do so, you should prefer using before_filter + # rather than after_filter in your ActionMailer classes so that headers are parsed properly. + # # = Configuration options # # These options are specified on the class level, like @@ -310,7 +354,7 @@ module ActionMailer #:nodoc: # # * <tt>delivery_method</tt> - Defines a delivery method. Possible values are <tt>:smtp</tt> (default), # <tt>:sendmail</tt>, <tt>:test</tt>, and <tt>:file</tt>. Or you may provide a custom delivery method - # object eg. MyOwnDeliveryMethodClass.new. See the Mail gem documentation on the interface you need to + # object e.g. MyOwnDeliveryMethodClass. See the Mail gem documentation on the interface you need to # implement for a custom delivery agent. # # * <tt>perform_deliveries</tt> - Determines whether emails are actually sent from Action Mailer when you @@ -320,6 +364,9 @@ module ActionMailer #:nodoc: # * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with # <tt>delivery_method :test</tt>. Most useful for unit and functional testing. # + # * <tt>queue</> - The queue that will be used to deliver the mail. The queue should expect a job that + # responds to <tt>run</tt> + # class Base < AbstractController::Base include DeliveryMethods abstract! @@ -330,10 +377,11 @@ module ActionMailer #:nodoc: include AbstractController::Helpers include AbstractController::Translation include AbstractController::AssetPaths + include AbstractController::Callbacks self.protected_instance_variables = [:@_action_has_layout] - helper ActionMailer::MailHelper + helper ActionMailer::MailHelper private_class_method :new #:nodoc: @@ -345,6 +393,9 @@ module ActionMailer #:nodoc: :parts_order => [ "text/plain", "text/enriched", "text/html" ] }.freeze + class_attribute :queue + self.queue = ActiveSupport::SynchronousQueue.new + class << self # Register one or more Observers which will be notified when mail is delivered. def register_observers(*observers) @@ -373,7 +424,7 @@ module ActionMailer #:nodoc: end def mailer_name - @mailer_name ||= name.underscore + @mailer_name ||= anonymous? ? "anonymous" : name.underscore end attr_writer :mailer_name alias :controller_path :mailer_name @@ -382,6 +433,10 @@ module ActionMailer #:nodoc: self.default_params = default_params.merge(value).freeze if value default_params end + # Allows to set defaults through app configuration: + # + # config.action_mailer.default_options = { from: "no-reply@example.org" } + alias :default_options= :default # Receives a raw email, parses it into an email object, decodes it, # instantiates a new mailer, and passes the email object to the mailer @@ -431,9 +486,12 @@ module ActionMailer #:nodoc: payload[:mail] = mail.encoded end - def method_missing(method, *args) #:nodoc: - return super unless respond_to?(method) - new(method, *args).message + def method_missing(method_name, *args) + if action_methods.include?(method_name.to_s) + QueuedMessage.new(queue, self, method_name, *args) + else + super + end end end @@ -458,7 +516,7 @@ module ActionMailer #:nodoc: self.class.mailer_name end - # Allows you to pass random and unusual headers to the new +Mail::Message+ object + # Allows you to pass random and unusual headers to the new <tt>Mail::Message</tt> object # which will add them to itself. # # headers['X-Special-Domain-Specific-Header'] = "SecretValue" @@ -469,7 +527,7 @@ module ActionMailer #:nodoc: # headers 'X-Special-Domain-Specific-Header' => "SecretValue", # 'In-Reply-To' => incoming.message_id # - # The resulting Mail::Message will have the following in it's header: + # The resulting Mail::Message will have the following in its header: # # X-Special-Domain-Specific-Header: SecretValue def headers(args=nil) @@ -569,8 +627,10 @@ module ActionMailer #:nodoc: # end # end # - # Will look for all templates at "app/views/notifier" with name "welcome". However, those - # can be customized: + # Will look for all templates at "app/views/notifier" with name "welcome". + # If no welcome template exists, it will raise an ActionView::MissingTemplate error. + # + # However, those can be customized: # # mail(:template_path => 'notifications', :template_name => 'another') # @@ -621,7 +681,7 @@ module ActionMailer #:nodoc: m.charset = charset = headers[:charset] # Set configure delivery behavior - wrap_delivery_behavior!(headers.delete(:delivery_method)) + 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) @@ -668,7 +728,7 @@ module ActionMailer #:nodoc: # If it does not find a translation for the +subject+ under the specified scope it will default to a # humanized version of the <tt>action_name</tt>. def default_i18n_subject #:nodoc: - mailer_scope = self.class.mailer_name.gsub('/', '.') + mailer_scope = self.class.mailer_name.tr('/', '.') I18n.t(:subject, :scope => [mailer_scope, action_name], :default => action_name.humanize) end @@ -694,7 +754,7 @@ module ActionMailer #:nodoc: responses << { :body => render(:template => template), - :content_type => template.mime_type.to_s + :content_type => template.type.to_s } end end @@ -704,7 +764,11 @@ module ActionMailer #:nodoc: def each_template(paths, name, &block) #:nodoc: templates = lookup_context.find_all(name, Array(paths)) - templates.uniq { |t| t.formats }.each(&block) + if templates.empty? + raise ActionView::MissingTemplate.new([paths], name, [paths], false, 'mailer') + else + templates.uniq { |t| t.formats }.each(&block) + end end def create_parts_from_responses(m, responses) #:nodoc: @@ -729,4 +793,3 @@ module ActionMailer #:nodoc: ActiveSupport.run_load_hooks(:action_mailer, self) end end - |