vendor/rails/actionmailer/lib/action_mailer/base.rb in radiant-0.7.2 vs vendor/rails/actionmailer/lib/action_mailer/base.rb in radiant-0.8.0

- old
+ new

@@ -1,11 +1,5 @@ -require 'action_mailer/adv_attr_accessor' -require 'action_mailer/part' -require 'action_mailer/part_container' -require 'action_mailer/utils' -require 'tmail/net' - module ActionMailer #:nodoc: # Action Mailer allows you to send email from your application using a mailer model and views. # # # = Mailer Models @@ -21,10 +15,11 @@ # Examples: # # class Notifier < ActionMailer::Base # def signup_notification(recipient) # recipients recipient.email_address_with_name + # bcc ["bcc@example.com", "Order Watcher <watcher@example.com>"] # from "system@example.com" # subject "New account information" # body :account => recipient # end # end @@ -214,12 +209,14 @@ # * <tt>:address</tt> - Allows you to use a remote mail server. Just change it from its default "localhost" setting. # * <tt>:port</tt> - On the off chance that your mail server doesn't run on port 25, you can change it. # * <tt>:domain</tt> - If you need to specify a HELO domain, you can do it here. # * <tt>:user_name</tt> - If your mail server requires authentication, set the username in this setting. # * <tt>:password</tt> - If your mail server requires authentication, set the password in this setting. - # * <tt>:authentication</tt> - If your mail server requires authentication, you need to specify the authentication type here. + # * <tt>:authentication</tt> - If your mail server requires authentication, you need to specify the authentication type here. # This is a symbol and one of <tt>:plain</tt>, <tt>:login</tt>, <tt>:cram_md5</tt>. + # * <tt>:enable_starttls_auto</tt> - When set to true, detects if STARTTLS is enabled in your SMTP server and starts to use it. + # It works only on Ruby >= 1.8.7 and Ruby >= 1.9. Default is true. # # * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method. # * <tt>:location</tt> - The location of the sendmail executable. Defaults to <tt>/usr/sbin/sendmail</tt>. # * <tt>:arguments</tt> - The command line arguments. Defaults to <tt>-i -t</tt>. # @@ -231,40 +228,46 @@ # but this can be turned off to help functional testing. # # * <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>default_charset</tt> - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also + # * <tt>default_charset</tt> - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also # pick a different charset from inside a method with +charset+. + # # * <tt>default_content_type</tt> - The default content type used for the main part of the message. Defaults to "text/plain". You - # can also pick a different content type from inside a method with +content_type+. + # can also pick a different content type from inside a method with +content_type+. + # # * <tt>default_mime_version</tt> - The default mime version used for the message. Defaults to <tt>1.0</tt>. You # can also pick a different value from inside a method with +mime_version+. + # # * <tt>default_implicit_parts_order</tt> - When a message is built implicitly (i.e. multiple parts are assembled from templates # which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to # <tt>["text/html", "text/enriched", "text/plain"]</tt>. Items that appear first in the array have higher priority in the mail client # and appear last in the mime encoded message. You can also pick a different order from inside a method with # +implicit_parts_order+. class Base - include AdvAttrAccessor, PartContainer - include ActionController::UrlWriter if Object.const_defined?(:ActionController) + include AdvAttrAccessor, PartContainer, Quoting, Utils + if Object.const_defined?(:ActionController) + include ActionController::UrlWriter + include ActionController::Layout + end private_class_method :new #:nodoc: - class_inheritable_accessor :template_root + class_inheritable_accessor :view_paths + self.view_paths = [] + cattr_accessor :logger - cattr_accessor :template_extensions - @@template_extensions = ['erb', 'builder', 'rhtml', 'rxml'] - @@smtp_settings = { - :address => "localhost", - :port => 25, - :domain => 'localhost.localdomain', - :user_name => nil, - :password => nil, - :authentication => nil + :address => "localhost", + :port => 25, + :domain => 'localhost.localdomain', + :user_name => nil, + :password => nil, + :authentication => nil, + :enable_starttls_auto => true, } cattr_accessor :smtp_settings @@sendmail_settings = { :location => '/usr/sbin/sendmail', @@ -294,10 +297,13 @@ cattr_accessor :default_mime_version @@default_implicit_parts_order = [ "text/html", "text/enriched", "text/plain" ] cattr_accessor :default_implicit_parts_order + cattr_reader :protected_instance_variables + @@protected_instance_variables = %w(@body) + # Specify the BCC addresses for the message adv_attr_accessor :bcc # Define the body of the message. This is either a Hash (in which case it # specifies the variables to pass to the template when it is rendered), @@ -363,10 +369,11 @@ self.class.mailer_name = value end # The mail object instance referenced by this mailer. attr_reader :mail + attr_reader :template_name, :default_template_name, :action_name class << self attr_writer :mailer_name def mailer_name @@ -375,16 +382,24 @@ # for ActionView compatibility alias_method :controller_name, :mailer_name alias_method :controller_path, :mailer_name - def method_missing(method_symbol, *parameters)#:nodoc: - case method_symbol.id2name - when /^create_([_a-z]\w*)/ then new($1, *parameters).mail - when /^deliver_([_a-z]\w*)/ then new($1, *parameters).deliver! - when "new" then nil - else super + def respond_to?(method_symbol, include_private = false) #:nodoc: + matches_dynamic_method?(method_symbol) || super + end + + def method_missing(method_symbol, *parameters) #:nodoc: + if match = matches_dynamic_method?(method_symbol) + case match[1] + when 'create' then new(match[2], *parameters).mail + when 'deliver' then new(match[2], *parameters).deliver! + when 'new' then nil + else super + end + else + super end end # Receives a raw email, parses it into an email object, decodes it, # instantiates a new mailer, and passes the email object to the mailer @@ -412,25 +427,23 @@ # MyMailer.deliver(email) def deliver(mail) new.deliver!(mail) end - # Register a template extension so mailer templates written in a - # templating language other than rhtml or rxml are supported. - # To use this, include in your template-language plugin's init - # code or on a per-application basis, this can be invoked from - # <tt>config/environment.rb</tt>: - # - # ActionMailer::Base.register_template_extension('haml') - def register_template_extension(extension) - template_extensions << extension + def template_root + self.view_paths && self.view_paths.first end def template_root=(root) - write_inheritable_attribute(:template_root, root) - ActionView::TemplateFinder.process_view_paths(root) + self.view_paths = ActionView::Base.process_view_paths(root) end + + private + def matches_dynamic_method?(method_name) #:nodoc: + method_name = method_name.to_s + /^(create|deliver)_([_a-z]\w*)/.match(method_name) || /^(new)$/.match(method_name) + end end # Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer # will be initialized according to the named method. If not, the mailer will # remain uninitialized (useful when you only need to invoke the "receive" @@ -450,33 +463,35 @@ # First, we look to see if there are any likely templates that match, # which include the content-type in their file name (i.e., # "the_template_file.text.html.erb", etc.). Only do this if parts # have not already been specified manually. if @parts.empty? - templates = Dir.glob("#{template_path}/#{@template}.*") - templates.each do |path| - basename = File.basename(path) - template_regex = Regexp.new("^([^\\\.]+)\\\.([^\\\.]+\\\.[^\\\.]+)\\\.(" + template_extensions.join('|') + ")$") - next unless md = template_regex.match(basename) - template_name = basename - content_type = md.captures[1].gsub('.', '/') - @parts << Part.new(:content_type => content_type, - :disposition => "inline", :charset => charset, - :body => render_message(template_name, @body)) + Dir.glob("#{template_path}/#{@template}.*").each do |path| + template = template_root["#{mailer_name}/#{File.basename(path)}"] + + # Skip unless template has a multipart format + next unless template && template.multipart? + + @parts << Part.new( + :content_type => template.content_type, + :disposition => "inline", + :charset => charset, + :body => render_message(template, @body) + ) end unless @parts.empty? - @content_type = "multipart/alternative" + @content_type = "multipart/alternative" if @content_type !~ /^multipart/ @parts = sort_parts(@parts, @implicit_parts_order) end end # Then, if there were such templates, we check to see if we ought to # also render a "normal" template (without the content type). If a # normal template exists (or if there were no implicit parts) we render # it. template_exists = @parts.empty? - template_exists ||= Dir.glob("#{template_path}/#{@template}.*").any? { |i| File.basename(i).split(".").length == 2 } + template_exists ||= template_root["#{mailer_name}/#{@template}"] @body = render_message(@template, @body) if template_exists # Finally, if there are other message parts and a textual body exists, # we shift it onto the front of the parts and set the body to nil (so # that create_mail doesn't try to render it in addition to the parts). @@ -520,36 +535,72 @@ def initialize_defaults(method_name) @charset ||= @@default_charset.dup @content_type ||= @@default_content_type.dup @implicit_parts_order ||= @@default_implicit_parts_order.dup @template ||= method_name + @default_template_name = @action_name = @template @mailer_name ||= self.class.name.underscore @parts ||= [] @headers ||= {} @body ||= {} @mime_version = @@default_mime_version.dup if @@default_mime_version end def render_message(method_name, body) - render :file => method_name, :body => body, :use_full_path => true + if method_name.respond_to?(:content_type) + @current_template_content_type = method_name.content_type + end + render :file => method_name, :body => body + ensure + @current_template_content_type = nil end def render(opts) body = opts.delete(:body) - if opts[:file] && opts[:file] !~ /\// + if opts[:file] && (opts[:file] !~ /\// && !opts[:file].respond_to?(:render)) opts[:file] = "#{mailer_name}/#{opts[:file]}" end - opts[:use_full_path] = true - initialize_template_class(body).render(opts) + + begin + old_template, @template = @template, initialize_template_class(body) + layout = respond_to?(:pick_layout, true) ? pick_layout(opts) : false + @template.render(opts.merge(:layout => layout)) + ensure + @template = old_template + end end + def default_template_format + if @current_template_content_type + Mime::Type.lookup(@current_template_content_type).to_sym + else + :html + end + end + + def candidate_for_layout?(options) + !self.view_paths.find_template(default_template_name, default_template_format).exempt_from_layout? + rescue ActionView::MissingTemplate + return true + end + + def template_root + self.class.template_root + end + + def template_root=(root) + self.class.template_root = root + end + def template_path "#{template_root}/#{mailer_name}" end def initialize_template_class(assigns) - ActionView::Base.new([template_root], assigns, self) + template = ActionView::Base.new(self.class.view_paths, assigns, self) + template.template_format = default_template_format + template end def sort_parts(parts, order = []) order = order.collect { |s| s.downcase } @@ -594,15 +645,15 @@ real_content_type, ctype_attrs = parse_content_type if @parts.empty? m.set_content_type(real_content_type, nil, ctype_attrs) - m.body = Utils.normalize_new_lines(body) + m.body = normalize_new_lines(body) else if String === body part = TMail::Mail.new - part.body = Utils.normalize_new_lines(body) + part.body = normalize_new_lines(body) part.set_content_type(real_content_type, nil, ctype_attrs) part.set_content_disposition "inline" m.parts << part end @@ -621,14 +672,16 @@ end def perform_delivery_smtp(mail) destinations = mail.destinations mail.ready_to_send - sender = mail['return-path'] || mail.from + sender = (mail['return-path'] && mail['return-path'].spec) || mail.from - Net::SMTP.start(smtp_settings[:address], smtp_settings[:port], smtp_settings[:domain], - smtp_settings[:user_name], smtp_settings[:password], smtp_settings[:authentication]) do |smtp| + smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port]) + smtp.enable_starttls_auto if smtp_settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto) + smtp.start(smtp_settings[:domain], smtp_settings[:user_name], smtp_settings[:password], + smtp_settings[:authentication]) do |smtp| smtp.sendmail(mail.encoded, sender, destinations) end end def perform_delivery_sendmail(mail) @@ -641,7 +694,12 @@ end def perform_delivery_test(mail) deliveries << mail end + end + + Base.class_eval do + include Helpers + helper MailHelper end end