Skip to content

Commit

Permalink
Parse content-type apart before using it so that sub-parts of the hea…
Browse files Browse the repository at this point in the history
…der can be set correctly (closes #2918)

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3959 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
jamis committed Mar 18, 2006
1 parent 9c9069a commit db0e8ff
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 11 deletions.
2 changes: 2 additions & 0 deletions actionmailer/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*

* Parse content-type apart before using it so that sub-parts of the header can be set correctly #2918 [Jamis Buck]

* Make custom headers work in subparts #4034 [elan@bluemandrill.com]

* Template paths with dot chars in them no longer mess up implicit template selection for multipart messages #3332 [Chad Fowler]
Expand Down
8 changes: 5 additions & 3 deletions actionmailer/lib/action_mailer/base.rb
Expand Up @@ -413,14 +413,16 @@ def create_mail
m.date = sent_on.to_time rescue sent_on if sent_on
headers.each { |k, v| m[k] = v }

real_content_type, ctype_attrs = parse_content_type

if @parts.empty?
m.set_content_type content_type, nil, { "charset" => charset }
m.set_content_type(real_content_type, nil, ctype_attrs)
m.body = Utils.normalize_new_lines(body)
else
if String === body
part = TMail::Mail.new
part.body = Utils.normalize_new_lines(body)
part.set_content_type content_type, nil, { "charset" => charset }
part.set_content_type(real_content_type, nil, ctype_attrs)
part.set_content_disposition "inline"
m.parts << part
end
Expand All @@ -430,7 +432,7 @@ def create_mail
m.parts << part
end

m.set_content_type(content_type, nil, { "charset" => charset }) if content_type =~ /multipart/
m.set_content_type(real_content_type, nil, ctype_attrs) if real_content_type =~ /multipart/
end

@mail = m
Expand Down
19 changes: 11 additions & 8 deletions actionmailer/lib/action_mailer/part.rb
Expand Up @@ -56,6 +56,8 @@ def initialize(params)
def to_mail(defaults)
part = TMail::Mail.new

real_content_type, ctype_attrs = parse_content_type(defaults)

if @parts.empty?
part.content_transfer_encoding = transfer_encoding || "quoted-printable"
case (transfer_encoding || "").downcase
Expand All @@ -71,20 +73,20 @@ def to_mail(defaults)
# Also don't set filename and name when there is none (like in
# non-attachment parts)
if content_disposition == "attachment"
part.set_content_type(content_type || defaults.content_type, nil,
squish("charset" => nil, "name" => filename))
ctype_attrs.delete "charset"
part.set_content_type(real_content_type, nil,
squish("name" => filename).merge(ctype_attrs))
part.set_content_disposition(content_disposition,
squish("filename" => filename))
squish("filename" => filename).merge(ctype_attrs))
else
part.set_content_type(content_type || defaults.content_type, nil,
"charset" => (charset || defaults.charset))
part.set_content_type(real_content_type, nil, ctype_attrs)
part.set_content_disposition(content_disposition)
end
else
if String === body
part = TMail::Mail.new
part.body = body
part.set_content_type content_type, nil, { "charset" => charset }
part.set_content_type(real_content_type, nil, ctype_attrs)
part.set_content_disposition "inline"
m.parts << part
end
Expand All @@ -94,15 +96,16 @@ def to_mail(defaults)
part.parts << prt
end

part.set_content_type(content_type, nil, { "charset" => charset }) if content_type =~ /multipart/
part.set_content_type(real_content_type, nil, ctype_attrs) if real_content_type =~ /multipart/
end

@headers.each { |k,v| part[k] = v }
headers.each { |k,v| part[k] = v }

part
end

private

def squish(values={})
values.delete_if { |k,v| v.nil? }
end
Expand Down
9 changes: 9 additions & 0 deletions actionmailer/lib/action_mailer/part_container.rb
Expand Up @@ -38,5 +38,14 @@ def attachment(params, &block)
part(params, &block)
end

private

def parse_content_type(defaults=nil)
return [defaults && defaults.content_type, {}] if content_type.blank?
ctype, *attrs = content_type.split(/;\s*/)
attrs = attrs.inject({}) { |h,s| k,v = s.split(/=/, 2); h[k] = v; h }
[ctype, {"charset" => charset || defaults && defaults.charset}.merge(attrs)]
end

end
end
14 changes: 14 additions & 0 deletions actionmailer/test/mail_service_test.rb
Expand Up @@ -246,6 +246,14 @@ def headers_with_nonalpha_chars(recipient)
body "testing"
end

def custom_content_type_attributes
recipients "no.one@nowhere.test"
subject "custom content types"
from "some.one@somewhere.test"
content_type "text/plain; format=flowed"
body "testing"
end

class <<self
attr_accessor :received_body
end
Expand Down Expand Up @@ -787,5 +795,11 @@ def test_multipart_with_template_path_with_dots
mail = FunkyPathMailer.create_multipart_with_template_path_with_dots(@recipient)
assert_equal 2, mail.parts.length
end

def test_custom_content_type_attributes
mail = TestMailer.create_custom_content_type_attributes
assert_match %r{format=flowed}, mail['content-type'].to_s
assert_match %r{charset=utf-8}, mail['content-type'].to_s
end
end

0 comments on commit db0e8ff

Please sign in to comment.