Make implicit and explicit templates pass through the same part creation process.

上级 5a19d248
require 'active_support/core_ext/class'
require "active_support/core_ext/module/delegation"
require 'active_support/core_ext/module/delegation'
require 'mail'
require 'action_mailer/tmail_compat'
......@@ -391,70 +391,63 @@ def set_payload_for_mail(payload, mail) #:nodoc:
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"
# method, for instance).
def initialize(method_name=nil, *args)
super()
@message = Mail.new
process(method_name, *args) if method_name
end
# Delivers a Mail object. By default, it delivers the cached mail
# object (from the <tt>create!</tt> method). If no cached mail object exists, and
# no alternate has been given as the parameter, this will fail.
def deliver!(mail = @message)
self.class.deliver(mail)
end
# TODO Add new delivery method goodness
def mail(headers = {})
# Guard flag to prevent both the old and the new API from firing
# Should be removed when old API is deprecated
@mail_was_called = true
m = @message
# Get default subject from I18n if none is set
headers[:subject] ||= default_subject
m, sort_parts = @message, true
# Give preference to headers and fallbacks to the ones set in mail
# Give preference to headers and fallback to the ones set in mail
content_type = headers[:content_type] || m.content_type
charset = headers[:charset] || m.charset || self.class.default_charset.dup
mime_version = headers[:mime_version] || m.mime_version || self.class.default_mime_version.dup
m.subject ||= quote_if_necessary(headers[:subject], charset) if headers[:subject]
m.to ||= quote_address_if_necessary(headers[:to], charset) if headers[:to]
m.from ||= quote_address_if_necessary(headers[:from], charset) if headers[:from]
m.cc ||= quote_address_if_necessary(headers[:cc], charset) if headers[:cc]
m.bcc ||= quote_address_if_necessary(headers[:bcc], charset) if headers[:bcc]
m.reply_to ||= quote_address_if_necessary(headers[:reply_to], charset) if headers[:reply_to]
m.date ||= headers[:date] if headers[:date]
headers[:subject] ||= default_subject
quote_fields(m, headers, charset)
if headers[:body]
templates = [ActionView::Template::Text.new(headers[:body], format_for_text)]
responses = if headers[:body]
[ { :body => headers[:body], :content_type => self.class.default_content_type.dup } ]
elsif block_given?
collector = ActionMailer::Collector.new(self, {:charset => charset}) do
render action_name
end
yield collector
collector.responses.each do |response|
part = Mail::Part.new(response)
m.add_part(part)
end
sort_parts = false
collector = ActionMailer::Collector.new(self) { render(action_name) }
yield(collector)
collector.responses
else
# TODO Ensure that we don't need to pass I18n.locale as detail
templates = self.class.template_root.find_all(action_name, {}, self.class.mailer_name)
end
if templates
if templates.size == 1 && !m.has_attachments?
content_type ||= templates[0].mime_type.to_s
m.body = render_to_body(:_template => templates[0])
elsif templates.size > 1 && m.has_attachments?
container = Mail::Part.new
container.content_type = "multipart/alternate"
templates.each { |t| insert_part(container, t, charset) }
m.add_part(container)
else
templates.each { |t| insert_part(m, t, charset) }
templates.map do |template|
{ :body => render_to_body(:_template => template),
:content_type => template.mime_type.to_s }
end
end
content_type ||= (m.has_attachments? ? "multipart/mixed" : "multipart/alternate")
content_type ||= create_parts_from_responses(m, responses, charset)
# Check if the content_type was not overwriten along the way and if so,
# fallback to default.
m.content_type = content_type || self.class.default_content_type.dup
m.content_type = content_type
m.charset = charset
m.mime_version = mime_version
if m.parts.present? && templates
if sort_parts && m.parts.present?
m.body.set_sort_order(headers[:parts_order] || self.class.default_implicit_parts_order.dup)
m.body.sort_parts!
end
......@@ -462,34 +455,43 @@ def mail(headers = {})
m
end
def default_subject
protected
def default_subject #:nodoc:
mailer_scope = self.class.mailer_name.gsub('/', '.')
I18n.t(:subject, :scope => [:actionmailer, mailer_scope, action_name], :default => action_name.humanize)
end
def insert_part(container, template, charset)
part = Mail::Part.new
part.content_type = template.mime_type.to_s
part.charset = charset
part.body = render_to_body(:_template => template)
container.add_part(part)
def quote_fields(m, headers, charset) #:nodoc:
m.subject ||= quote_if_necessary(headers[:subject], charset) if headers[:subject]
m.to ||= quote_address_if_necessary(headers[:to], charset) if headers[:to]
m.from ||= quote_address_if_necessary(headers[:from], charset) if headers[:from]
m.cc ||= quote_address_if_necessary(headers[:cc], charset) if headers[:cc]
m.bcc ||= quote_address_if_necessary(headers[:bcc], charset) if headers[:bcc]
m.reply_to ||= quote_address_if_necessary(headers[:reply_to], charset) if headers[:reply_to]
m.date ||= headers[:date] if headers[:date]
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"
# method, for instance).
def initialize(method_name=nil, *args)
super()
@message = Mail.new
process(method_name, *args) if method_name
def create_parts_from_responses(m, responses, charset) #:nodoc:
if responses.size == 1 && !m.has_attachments?
m.body = responses[0][:body]
return responses[0][:content_type]
elsif responses.size > 1 && m.has_attachments?
container = Mail::Part.new
container.content_type = "multipart/alternate"
responses.each { |r| insert_part(container, r, charset) }
m.add_part(container)
else
responses.each { |r| insert_part(m, r, charset) }
end
m.has_attachments? ? "multipart/mixed" : "multipart/alternate"
end
# Delivers a Mail object. By default, it delivers the cached mail
# object (from the <tt>create!</tt> method). If no cached mail object exists, and
# no alternate has been given as the parameter, this will fail.
def deliver!(mail = @message)
self.class.deliver(mail)
def insert_part(container, response, charset) #:nodoc:
response[:charset] ||= charset
part = Mail::Part.new(response)
container.add_part(part)
end
end
......
require 'abstract_controller/collector'
require 'active_support/core_ext/hash/reverse_merge'
require 'active_support/core_ext/array/extract_options'
module ActionMailer #:nodoc:
class Collector
include AbstractController::Collector
attr_accessor :responses
attr_reader :responses
def initialize(context, options, &block)
@default_options = options
@default_render = block
@default_formats = context.formats
def initialize(context, &block)
@context = context
@responses = []
@default_render = block
@default_formats = context.formats
end
# TODO Test me
def any(*args, &block)
options = args.extract_options!
raise "You have to supply at least one format" if args.empty?
args.each { |type| send(type, options, &block) }
end
alias :all :any
def custom(mime, options={}, &block)
options = @default_options.merge(:content_type => mime.to_s).merge(options)
options.reverse_merge!(:content_type => mime.to_s)
@context.formats = [mime.to_sym]
options[:body] = if block
block.call
......@@ -27,6 +33,5 @@ def custom(mime, options={}, &block)
@responses << options
@context.formats = @default_formats
end
end
end
\ No newline at end of file
......@@ -54,9 +54,9 @@ def welcome(hash = {})
mail(DEFAULT_HEADERS.merge(hash))
end
def attachment_with_content
def attachment_with_content(hash = {})
attachments['invoice.pdf'] = 'This is test File content'
mail(DEFAULT_HEADERS)
mail(DEFAULT_HEADERS.merge(hash))
end
def attachment_with_hash
......@@ -69,8 +69,9 @@ def implicit_multipart(hash = {})
attachments['invoice.pdf'] = 'This is test File content' if hash.delete(:attachments)
mail(DEFAULT_HEADERS.merge(hash))
end
def explicit_multipart(hash = {})
attachments['invoice.pdf'] = 'This is test File content' if hash.delete(:attachments)
mail(DEFAULT_HEADERS.merge(hash)) do |format|
format.text { render :text => "TEXT Explicit Multipart" }
format.html { render :text => "HTML Explicit Multipart" }
......@@ -116,6 +117,7 @@ def explicit_multipart(hash = {})
test "can pass in :body to the mail method hash" do
email = BaseMailer.deliver_welcome(:body => "Hello there")
assert_equal("text/plain", email.mime_type)
assert_equal("Hello there", email.body.encoded)
end
......@@ -154,12 +156,23 @@ def explicit_multipart(hash = {})
test "adds the rendered template as part" do
email = BaseMailer.deliver_attachment_with_content
assert_equal(2, email.parts.length)
assert_equal("multipart/mixed", email.mime_type)
assert_equal("text/html", email.parts[0].mime_type)
assert_equal("Attachment with content", email.parts[0].body.encoded)
assert_equal("application/pdf", email.parts[1].mime_type)
assert_equal("VGhpcyBpcyB0ZXN0IEZpbGUgY29udGVudA==\r\n", email.parts[1].body.encoded)
end
test "adds the given :body as part" do
email = BaseMailer.deliver_attachment_with_content(:body => "I'm the eggman")
assert_equal(2, email.parts.length)
assert_equal("multipart/mixed", email.mime_type)
assert_equal("text/plain", email.parts[0].mime_type)
assert_equal("I'm the eggman", email.parts[0].body.encoded)
assert_equal("application/pdf", email.parts[1].mime_type)
assert_equal("VGhpcyBpcyB0ZXN0IEZpbGUgY29udGVudA==\r\n", email.parts[1].body.encoded)
end
# Defaults values
test "uses default charset from class" do
swap BaseMailer, :default_charset => "US-ASCII" do
......@@ -268,15 +281,15 @@ def explicit_multipart(hash = {})
end
end
#test "explicit multipart with attachments creates nested parts" do
# email = BaseMailer.deliver_explicit_multipart(:attachments => true)
# assert_equal("application/pdf", email.parts[0].mime_type)
# assert_equal("multipart/alternate", email.parts[1].mime_type)
# assert_equal("text/plain", email.parts[1].parts[0].mime_type)
# assert_equal("TEXT Implicit Multipart", email.parts[1].parts[0].body.encoded)
# assert_equal("text/html", email.parts[1].parts[1].mime_type)
# assert_equal("HTML Implicit Multipart", email.parts[1].parts[1].body.encoded)
#end
test "explicit multipart with attachments creates nested parts" do
email = BaseMailer.deliver_explicit_multipart(:attachments => true)
assert_equal("application/pdf", email.parts[0].mime_type)
assert_equal("multipart/alternate", email.parts[1].mime_type)
assert_equal("text/plain", email.parts[1].parts[0].mime_type)
assert_equal("TEXT Explicit Multipart", email.parts[1].parts[0].body.encoded)
assert_equal("text/html", email.parts[1].parts[1].mime_type)
assert_equal("HTML Explicit Multipart", email.parts[1].parts[1].body.encoded)
end
protected
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册