提交 5ddffc8c 编写于 作者: J Jamis Buck

Allow for nested parts in multipart mails #1570 [Flurin Egger]


git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1581 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 5651a691
*SVN*
* Allow for nested parts in multipart mails #1570 [Flurin Egger]
* Normalize line endings in outgoing mail bodies to "\n" #1536 [John Long]
* Allow template to be explicitly specified #1448 [tuxie@dekadance.se]
......
require 'action_mailer/adv_attr_accessor'
require 'action_mailer/part'
require 'action_mailer/part_container'
require 'tmail/net'
module ActionMailer #:nodoc:
......@@ -108,6 +109,7 @@ module ActionMailer #:nodoc:
# pick a different charset from inside a method with <tt>@charset</tt>.
class Base
include ActionMailer::AdvAttrAccessor
include ActionMailer::PartContainer
private_class_method :new #:nodoc:
......@@ -220,25 +222,6 @@ def deliver!
return @mail
end
# Add a part to a multipart message, with the given content-type. The
# part itself is yielded to the block, so that other properties (charset,
# body, headers, etc.) can be set on it.
def part(params)
params = {:content_type => params} if String === params
part = Part.new(params)
yield part if block_given?
@parts << part
end
# Add an attachment to a multipart message. This is simply a part with the
# content-disposition set to "attachment".
def attachment(params, &block)
params = { :content_type => params } if String === params
params = { :disposition => "attachment",
:transfer_encoding => "base64" }.merge(params)
part(params, &block)
end
private
def render_message(method_name, body)
initialize_template_class(body).render_file(method_name)
......
require 'action_mailer/adv_attr_accessor'
require 'action_mailer/part_container'
module ActionMailer
class Part #:nodoc:
include ActionMailer::AdvAttrAccessor
include ActionMailer::PartContainer
adv_attr_accessor :content_type, :content_disposition, :charset, :body
adv_attr_accessor :filename, :transfer_encoding, :headers
......@@ -16,27 +18,54 @@ def initialize(params)
@filename = params[:filename]
@transfer_encoding = params[:transfer_encoding] || "quoted-printable"
@headers = params[:headers] || {}
@parts = []
end
def to_mail(defaults)
part = TMail::Mail.new
part.set_content_type(content_type || defaults.content_type, nil,
"charset" => (content_disposition == "attachment" ?
nil : (charset || defaults.charset)),
"name" => filename)
part.set_content_disposition(content_disposition,
"filename" => filename)
part.content_transfer_encoding = transfer_encoding || "quoted-printable"
case (transfer_encoding || "").downcase
when "base64" then
part.body = TMail::Base64.folding_encode(body)
when "quoted-printable"
part.body = [body].pack("M*")
if @parts.empty?
part.content_transfer_encoding = transfer_encoding || "quoted-printable"
case (transfer_encoding || "").downcase
when "base64" then
part.body = TMail::Base64.folding_encode(body)
when "quoted-printable"
part.body = [body].pack("M*")
else
part.body = body
end
# Always set the content_type after setting the body and or parts!
# 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,
"charset" => nil,
"name" => filename)
part.set_content_disposition(content_disposition, "filename" => filename)
else
part.set_content_type(content_type || defaults.content_type, nil,
"charset" => (charset || defaults.charset))
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_disposition "inline"
m.parts << part
end
@parts.each do |p|
prt = (TMail::Mail === p ? p : p.to_mail(defaults))
part.parts << prt
end
part.set_content_type(content_type, nil, { "charset" => charset }) if content_type =~ /multipart/
end
part
end
end
......
module ActionMailer
module PartContainer
attr_reader :parts
# Add a part to a multipart message, with the given content-type. The
# part itself is yielded to the block, so that other properties (charset,
# body, headers, etc.) can be set on it.
def part(params)
params = {:content_type => params} if String === params
part = Part.new(params)
yield part if block_given?
@parts << part
end
# Add an attachment to a multipart message. This is simply a part with the
# content-disposition set to "attachment".
def attachment(params, &block)
params = { :content_type => params } if String === params
params = { :disposition => "attachment",
:transfer_encoding => "base64" }.merge(params)
part(params, &block)
end
end
end
......@@ -145,6 +145,20 @@ def various_newlines(recipient)
"line #5\n\nline#6\r\n\r\nline #7"
end
def nested_multipart(recipient)
recipients recipient
subject "nested multipart"
from "test@example.com"
content_type "multipart/mixed"
part :content_type => "multipart/alternative", :content_disposition => "inline" do |p|
p.part :content_type => "text/plain", :body => "test text\nline #2"
p.part :content_type => "text/html", :body => "<b>test</b> HTML<br/>\nline #2"
end
attachment :content_type => "application/octet-stream",:filename => "test.txt", :body => "test abcdefghijklmnopqstuvwxyz"
end
class <<self
attr_accessor :received_body
end
......@@ -179,6 +193,19 @@ def setup
@recipient = 'test@localhost'
end
def test_nested_parts
created = nil
assert_nothing_raised { created = TestMailer.create_nested_multipart(@recipient)}
assert_equal 2,created.parts.size
assert_equal 2,created.parts.first.parts.size
assert_equal "multipart/mixed", created.content_type
assert_equal "multipart/alternative", created.parts.first.content_type
assert_equal "text/plain", created.parts.first.parts.first.content_type
assert_equal "text/html", created.parts.first.parts[1].content_type
assert_equal "application/octet-stream", created.parts[1].content_type
end
def test_signed_up
expected = new_mail
expected.to = @recipient
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册