mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Explicit multipart messages respect :parts_order
As issue #7978, the order in which ActionMailer sends multipart messages could be unintentionally overwritten if a block is passed to the mail method. This changes the mail method such that :parts_order is always respected, regardless of whether a block is passed to mail.
This commit is contained in:
parent
3b99653587
commit
9cf33b55f3
4 changed files with 31 additions and 46 deletions
|
@ -1,5 +1,8 @@
|
|||
## Rails 4.0.0 (unreleased) ##
|
||||
|
||||
* Explicit multipart messages no longer set the order of the MIME parts.
|
||||
*Nate Berkopec*
|
||||
|
||||
* Do not render views when mail() isn't called.
|
||||
Fix #7761
|
||||
|
||||
|
|
|
@ -698,7 +698,7 @@ module ActionMailer
|
|||
assignable.each { |k, v| m[k] = v }
|
||||
|
||||
# Render the templates and blocks
|
||||
responses, explicit_order = collect_responses_and_parts_order(headers, &block)
|
||||
responses = collect_responses(headers, &block)
|
||||
create_parts_from_responses(m, responses)
|
||||
|
||||
# Setup content type, reapply charset and handle parts order
|
||||
|
@ -706,8 +706,7 @@ module ActionMailer
|
|||
m.charset = charset
|
||||
|
||||
if m.multipart?
|
||||
parts_order ||= explicit_order || headers[:parts_order]
|
||||
m.body.set_sort_order(parts_order)
|
||||
m.body.set_sort_order(headers[:parts_order])
|
||||
m.body.sort_parts!
|
||||
end
|
||||
|
||||
|
@ -742,14 +741,13 @@ module ActionMailer
|
|||
I18n.t(:subject, scope: [mailer_scope, action_name], default: action_name.humanize)
|
||||
end
|
||||
|
||||
def collect_responses_and_parts_order(headers) #:nodoc:
|
||||
responses, parts_order = [], nil
|
||||
def collect_responses(headers) #:nodoc:
|
||||
responses = []
|
||||
|
||||
if block_given?
|
||||
collector = ActionMailer::Collector.new(lookup_context) { render(action_name) }
|
||||
yield(collector)
|
||||
parts_order = collector.responses.map { |r| r[:content_type] }
|
||||
responses = collector.responses
|
||||
responses = collector.responses
|
||||
elsif headers[:body]
|
||||
responses << {
|
||||
body: headers.delete(:body),
|
||||
|
@ -769,7 +767,7 @@ module ActionMailer
|
|||
end
|
||||
end
|
||||
|
||||
[responses, parts_order]
|
||||
responses
|
||||
end
|
||||
|
||||
def each_template(paths, name, &block) #:nodoc:
|
||||
|
|
|
@ -322,19 +322,6 @@ class BaseTest < ActiveSupport::TestCase
|
|||
assert_not_nil(mail.content_type_parameters[:boundary])
|
||||
end
|
||||
|
||||
test "explicit multipart does not sort order" do
|
||||
order = ["text/html", "text/plain"]
|
||||
with_default BaseMailer, parts_order: order do
|
||||
email = BaseMailer.explicit_multipart
|
||||
assert_equal("text/plain", email.parts[0].mime_type)
|
||||
assert_equal("text/html", email.parts[1].mime_type)
|
||||
|
||||
email = BaseMailer.explicit_multipart(parts_order: order.reverse)
|
||||
assert_equal("text/plain", email.parts[0].mime_type)
|
||||
assert_equal("text/html", email.parts[1].mime_type)
|
||||
end
|
||||
end
|
||||
|
||||
test "explicit multipart with attachments creates nested parts" do
|
||||
email = BaseMailer.explicit_multipart(attachments: true)
|
||||
assert_equal("application/pdf", email.parts[0].mime_type)
|
||||
|
@ -349,10 +336,10 @@ class BaseTest < ActiveSupport::TestCase
|
|||
email = BaseMailer.explicit_multipart_templates
|
||||
assert_equal(2, email.parts.size)
|
||||
assert_equal("multipart/alternative", email.mime_type)
|
||||
assert_equal("text/html", email.parts[0].mime_type)
|
||||
assert_equal("HTML Explicit Multipart Templates", email.parts[0].body.encoded)
|
||||
assert_equal("text/plain", email.parts[1].mime_type)
|
||||
assert_equal("TEXT Explicit Multipart Templates", email.parts[1].body.encoded)
|
||||
assert_equal("text/plain", email.parts[0].mime_type)
|
||||
assert_equal("TEXT Explicit Multipart Templates", email.parts[0].body.encoded)
|
||||
assert_equal("text/html", email.parts[1].mime_type)
|
||||
assert_equal("HTML Explicit Multipart Templates", email.parts[1].body.encoded)
|
||||
end
|
||||
|
||||
test "explicit multipart with format.any" do
|
||||
|
@ -387,10 +374,23 @@ class BaseTest < ActiveSupport::TestCase
|
|||
email = BaseMailer.explicit_multipart_with_one_template
|
||||
assert_equal(2, email.parts.size)
|
||||
assert_equal("multipart/alternative", email.mime_type)
|
||||
assert_equal("text/html", email.parts[0].mime_type)
|
||||
assert_equal("[:html]", email.parts[0].body.encoded)
|
||||
assert_equal("text/plain", email.parts[1].mime_type)
|
||||
assert_equal("[:text]", email.parts[1].body.encoded)
|
||||
assert_equal("text/plain", email.parts[0].mime_type)
|
||||
assert_equal("[:text]", email.parts[0].body.encoded)
|
||||
assert_equal("text/html", email.parts[1].mime_type)
|
||||
assert_equal("[:html]", email.parts[1].body.encoded)
|
||||
end
|
||||
|
||||
test "explicit multipart with sort order" do
|
||||
order = ["text/html", "text/plain"]
|
||||
with_default BaseMailer, parts_order: order do
|
||||
email = BaseMailer.explicit_multipart
|
||||
assert_equal("text/html", email.parts[0].mime_type)
|
||||
assert_equal("text/plain", email.parts[1].mime_type)
|
||||
|
||||
email = BaseMailer.explicit_multipart(parts_order: order.reverse)
|
||||
assert_equal("text/plain", email.parts[0].mime_type)
|
||||
assert_equal("text/html", email.parts[1].mime_type)
|
||||
end
|
||||
end
|
||||
|
||||
# Class level API with method missing
|
||||
|
|
|
@ -377,23 +377,7 @@ If you use this setting, you should pass the `only_path: false` option when usin
|
|||
|
||||
Action Mailer will automatically send multipart emails if you have different templates for the same action. So, for our UserMailer example, if you have `welcome_email.text.erb` and `welcome_email.html.erb` in `app/views/user_mailer`, Action Mailer will automatically send a multipart email with the HTML and text versions setup as different parts.
|
||||
|
||||
The order of the parts getting inserted is determined by the `:parts_order` inside of the `ActionMailer::Base.default` method. If you want to explicitly alter the order, you can either change the `:parts_order` or explicitly render the parts in a different order:
|
||||
|
||||
```ruby
|
||||
class UserMailer < ActionMailer::Base
|
||||
def welcome_email(user)
|
||||
@user = user
|
||||
@url = user_url(@user)
|
||||
mail(to: user.email,
|
||||
subject: 'Welcome to My Awesome Site') do |format|
|
||||
format.html
|
||||
format.text
|
||||
end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Will put the HTML part first, and the plain text part second.
|
||||
The order of the parts getting inserted is determined by the `:parts_order` inside of the `ActionMailer::Base.default` method.
|
||||
|
||||
### Sending Emails with Attachments
|
||||
|
||||
|
|
Loading…
Reference in a new issue