aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJamis Buck <jamis@37signals.com>2005-07-01 20:43:40 +0000
committerJamis Buck <jamis@37signals.com>2005-07-01 20:43:40 +0000
commit5c981528f20d53ad441b61c70350cc53fe3e8b6f (patch)
tree2a3ae0e88c00115116746d81cf1882bb7b6d3b78
parentebd7bf7945d8fc6881a7b576fe22eaaa2ca3efd8 (diff)
downloadrails-5c981528f20d53ad441b61c70350cc53fe3e8b6f.tar.gz
rails-5c981528f20d53ad441b61c70350cc53fe3e8b6f.tar.bz2
rails-5c981528f20d53ad441b61c70350cc53fe3e8b6f.zip
Better multipart support with implicit multipart/alternative and sorting of subparts [John Long]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1586 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
-rw-r--r--actionmailer/CHANGELOG2
-rw-r--r--actionmailer/lib/action_mailer/base.rb49
-rw-r--r--actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.rhtml1
-rwxr-xr-xactionmailer/test/mail_service_test.rb18
4 files changed, 65 insertions, 5 deletions
diff --git a/actionmailer/CHANGELOG b/actionmailer/CHANGELOG
index 4338d4d3f6..c21a89e87c 100644
--- a/actionmailer/CHANGELOG
+++ b/actionmailer/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Better multipart support with implicit multipart/alternative and sorting of subparts [John Long]
+
* Allow for nested parts in multipart mails #1570 [Flurin Egger]
* Normalize line endings in outgoing mail bodies to "\n" #1536 [John Long]
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 9a432faa32..21f4086008 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -106,7 +106,14 @@ module ActionMailer #:nodoc:
# 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
- # pick a different charset from inside a method with <tt>@charset</tt>.
+ # pick a different charset from inside a method with <tt>@charset</tt>.
+ # * <tt>default_content_type</tt> - The default content type used for main part of the message. Defaults to "text/plain". You
+ # can also pick a different content type from inside a method with <tt>@content_type</tt>.
+ # * <tt>default_implicit_parts_order</tt> - When a message is built implicitly (i.e. multiple parts are assemble from templates
+ # which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to
+ # ["text/html", "text/enriched", "text/plain"]. 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
+ # <tt>@implicit_parts_order</tt>.
class Base
include ActionMailer::AdvAttrAccessor
include ActionMailer::PartContainer
@@ -144,8 +151,12 @@ module ActionMailer #:nodoc:
@@default_content_type = "text/plain"
cattr_accessor :default_content_type
+ @@default_implicit_parts_order = [ "text/html", "text/enriched", "text/plain" ]
+ cattr_accessor :default_implicit_parts_order
+
adv_attr_accessor :recipients, :subject, :body, :from, :sent_on, :headers,
- :bcc, :cc, :charset, :content_type, :template
+ :bcc, :cc, :charset, :content_type, :implicit_parts_order,
+ :template
attr_reader :mail
@@ -163,6 +174,7 @@ module ActionMailer #:nodoc:
@bcc = @cc = @from = @recipients = @sent_on = @subject = nil
@charset = @@default_charset.dup
@content_type = @@default_content_type.dup
+ @implicit_parts_order = @@default_implicit_parts_order.dup
@template = method_name
@parts = []
@headers = {}
@@ -184,6 +196,10 @@ module ActionMailer #:nodoc:
:disposition => "inline", :charset => charset,
:body => render_message(File.basename(path).split(".")[0..-2].join('.'), @body))
end
+ unless @parts.empty?
+ @content_type = "multipart/alternative"
+ @parts = sort_parts(@parts, @implicit_parts_order)
+ end
end
# Then, if there were such templates, we check to see if we ought to
@@ -235,6 +251,35 @@ module ActionMailer #:nodoc:
ActionView::Base.new(template_path, assigns, self)
end
+ def sort_parts(parts, order = [])
+ order = order.collect { |s| s.downcase }
+
+ parts = parts.sort do |a, b|
+ a_ct = a.content_type.downcase
+ b_ct = b.content_type.downcase
+
+ a_in = order.include? a_ct
+ b_in = order.include? b_ct
+
+ s = case
+ when a_in && b_in
+ order.index(a_ct) <=> order.index(b_ct)
+ when a_in
+ -1
+ when b_in
+ 1
+ else
+ a_ct <=> b_ct
+ end
+
+ # reverse the ordering because parts that come last are displayed
+ # first in mail clients
+ (s * -1)
+ end
+
+ parts
+ end
+
def create_mail
m = TMail::Mail.new
diff --git a/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.rhtml b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.rhtml
new file mode 100644
index 0000000000..c14348c770
--- /dev/null
+++ b/actionmailer/test/fixtures/test_mailer/implicitly_multipart_example.text.yaml.rhtml
@@ -0,0 +1 @@
+yaml to: <%= @recipient %> \ No newline at end of file
diff --git a/actionmailer/test/mail_service_test.rb b/actionmailer/test/mail_service_test.rb
index 01b71801b8..85fe3ad69b 100755
--- a/actionmailer/test/mail_service_test.rb
+++ b/actionmailer/test/mail_service_test.rb
@@ -111,12 +111,13 @@ class TestMailer < ActionMailer::Base
:body => "123456789"
end
- def implicitly_multipart_example(recipient)
+ def implicitly_multipart_example(recipient, order = nil)
@recipients = recipient
@subject = "multipart example"
@from = "test@example.com"
@sent_on = Time.local 2004, 12, 12
@body = { "recipient" => recipient }
+ @implicit_parts_order = order unless order.nil?
end
def html_mail(recipient)
@@ -551,11 +552,22 @@ EOF
def test_implicitly_multipart_messages
mail = TestMailer.create_implicitly_multipart_example(@recipient)
- assert_equal 2, mail.parts.length
- assert_equal "text/html", mail.parts[0].content_type
+ assert_equal 3, mail.parts.length
+ assert_equal "multipart/alternative", mail.content_type
+ assert_equal "text/yaml", mail.parts[0].content_type
assert_equal "utf-8", mail.parts[0].sub_header("content-type", "charset")
assert_equal "text/plain", mail.parts[1].content_type
assert_equal "utf-8", mail.parts[1].sub_header("content-type", "charset")
+ assert_equal "text/html", mail.parts[2].content_type
+ assert_equal "utf-8", mail.parts[2].sub_header("content-type", "charset")
+ end
+
+ def test_implicitly_multipart_messages_with_custom_order
+ mail = TestMailer.create_implicitly_multipart_example(@recipient, ["text/yaml", "text/plain"])
+ assert_equal 3, mail.parts.length
+ assert_equal "text/html", mail.parts[0].content_type
+ assert_equal "text/plain", mail.parts[1].content_type
+ assert_equal "text/yaml", mail.parts[2].content_type
end
def test_html_mail