Fixed quoting for all address headers, not just to #955 [Jamis Buck] Added...

Fixed quoting for all address headers, not just to #955 [Jamis Buck] Added that quoting to UTF-8 only happens if the characters used are in that range #955 [Jamis Buck]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@1142 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 ea803aa4
*SVN*
* Fixed quoting for all address headers, not just to #955 [Jamis Buck]
* Added that quoting to UTF-8 only happens if the characters used are in that range #955 [Jamis Buck]
* Fixed unquoting of emails that doesn't have an explicit charset #1036 [wolfgang@stufenlos.net]
......
......@@ -58,8 +58,6 @@ module ActionMailer #:nodoc:
#
# * <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>@encoding</tt>.
#
# * <tt>encode_subject</tt> - Whether or not to encode the subject with the active charset. Defaults to true.
class Base
private_class_method :new #:nodoc:
......@@ -91,15 +89,11 @@ class Base
@@default_charset = "utf-8"
cattr_accessor :default_charset
@@encode_subject = true
cattr_accessor :encode_subject
attr_accessor :recipients, :subject, :body, :from, :sent_on, :headers, :bcc, :cc, :charset, :encode_subject
attr_accessor :recipients, :subject, :body, :from, :sent_on, :headers, :bcc, :cc, :charset
def initialize
@bcc = @cc = @from = @recipients = @sent_on = @subject = @body = nil
@charset = @@default_charset.dup
@encode_subject = @@encode_subject
@headers = {}
end
......@@ -118,17 +112,18 @@ def method_missing(method_symbol, *parameters)#:nodoc:
end
def mail(to, subject, body, from, timestamp = nil, headers = {},
encode = @@encode_subject, charset = @@default_charset
charset = @@default_charset
) #:nodoc:
deliver(create(to, subject, body, from, timestamp, headers, charset))
end
def create(to, subject, body, from, timestamp = nil, headers = {},
encode = @@encode_subject, charset = @@default_charset
charset = @@default_charset
) #:nodoc:
m = TMail::Mail.new
m.to, m.subject, m.body, m.from = to,
( encode ? quoted_printable(subject,charset) : subject ), body, from
m.subject, m.body = quote_any_if_necessary(charset, subject, body)
m.to, m.from = quote_any_address_if_necessary(charset, to, from)
m.date = timestamp.respond_to?("to_time") ? timestamp.to_time : (timestamp || Time.now)
m.set_content_type "text", "plain", { "charset" => charset }
......@@ -150,6 +145,40 @@ def quoted_printable(text, charset)#:nodoc:
"=?#{charset}?Q?#{text}?="
end
CHARS_NEEDING_QUOTING = /[\000-\011\013\014\016-\037\177-\377]/
# Quote the given text if it contains any "illegal" characters
def quote_if_necessary(text, charset)
(text =~ CHARS_NEEDING_QUOTING) ?
quoted_printable(text, charset) :
text
end
# Quote any of the given strings if they contain any "illegal" characters
def quote_any_if_necessary(charset, *args)
args.map { |v| quote_if_necessary(v, charset) }
end
# Quote the given address if it needs to be. The address may be a
# regular email address, or it can be a phrase followed by an address in
# brackets. The phrase is the only part that will be quoted, and only if
# it needs to be. This allows extended characters to be used in the
# "to", "from", "cc", and "bcc" headers.
def quote_address_if_necessary(address, charset)
if address =~ /^([^<>\s]+) (<.*>)$/
address = $2
phrase = quote_if_necessary($1, charset)
"#{phrase} #{address}"
else
address
end
end
# Quote any of the given addresses, if they need to be.
def quote_any_address_if_necessary(charset, *args)
args.map { |v| quote_address_if_necessary(v, charset) }
end
def receive(raw_email)
logger.info "Received mail:\n #{raw_email}" unless logger.nil?
new.receive(TMail::Mail.parse(raw_email))
......@@ -185,10 +214,10 @@ def create_from_action(method_name, *parameters)
mail = create(mailer.recipients, mailer.subject, mailer.body,
mailer.from, mailer.sent_on, mailer.headers,
mailer.encode_subject, mailer.charset)
mailer.charset)
mail.bcc = mailer.bcc unless mailer.bcc.nil?
mail.cc = mailer.cc unless mailer.cc.nil?
mail.bcc = quote_address_if_necessary(mailer.bcc, mailer.charset) unless mailer.bcc.nil?
mail.cc = quote_address_if_necessary(mailer.cc, mailer.charset) unless mailer.cc.nil?
return mail
end
......
......@@ -33,7 +33,7 @@ def cc_bcc(recipient)
def iso_charset(recipient)
@recipients = recipient
@subject = "testing iso charsets"
@subject = "testing isø charsets"
@from = "system@loudthinking.com"
@sent_on = Time.local 2004, 12, 12
@cc = "nobody@loudthinking.com"
......@@ -50,7 +50,17 @@ def unencoded_subject(recipient)
@cc = "nobody@loudthinking.com"
@bcc = "root@loudthinking.com"
@body = "Nothing to see here."
@encode_subject = false
end
def extended_headers(recipient)
@recipients = recipient
@subject = "testing extended headers"
@from = "Grytøyr <stian1@example.net>"
@sent_on = Time.local 2004, 12, 12
@cc = "Grytøyr <stian2@example.net>"
@bcc = "Grytøyr <stian3@example.net>"
@body = "Nothing to see here."
@charset = "iso-8859-1"
end
end
......@@ -82,7 +92,7 @@ def setup
def test_signed_up
expected = new_mail
expected.to = @recipient
expected.subject = encode "[Signed up] Welcome #{@recipient}"
expected.subject = "[Signed up] Welcome #{@recipient}"
expected.body = "Hello there, \n\nMr. #{@recipient}"
expected.from = "system@loudthinking.com"
expected.date = Time.local(2004, 12, 12)
......@@ -100,7 +110,7 @@ def test_signed_up
def test_cancelled_account
expected = new_mail
expected.to = @recipient
expected.subject = encode "[Cancelled] Goodbye #{@recipient}"
expected.subject = "[Cancelled] Goodbye #{@recipient}"
expected.body = "Goodbye, Mr. #{@recipient}"
expected.from = "system@loudthinking.com"
expected.date = Time.local(2004, 12, 12)
......@@ -118,7 +128,7 @@ def test_cancelled_account
def test_cc_bcc
expected = new_mail
expected.to = @recipient
expected.subject = encode "testing bcc/cc"
expected.subject = "testing bcc/cc"
expected.body = "Nothing to see here."
expected.from = "system@loudthinking.com"
expected.cc = "nobody@loudthinking.com"
......@@ -143,7 +153,7 @@ def test_cc_bcc
def test_iso_charset
expected = new_mail( "iso-8859-1" )
expected.to = @recipient
expected.subject = encode "testing iso charsets", "iso-8859-1"
expected.subject = encode "testing isø charsets", "iso-8859-1"
expected.body = "Nothing to see here."
expected.from = "system@loudthinking.com"
expected.cc = "nobody@loudthinking.com"
......@@ -228,5 +238,33 @@ def test_unquote_subject
assert_equal "This_is_a_test\n2 + 2 =3D 4\n", mail.quoted_body
end
def test_extended_headers
@recipient = "Grytøyr <test@localhost>"
expected = new_mail "iso-8859-1"
expected.to = TestMailer.quote_address_if_necessary @recipient, "iso-8859-1"
expected.subject = "testing extended headers"
expected.body = "Nothing to see here."
expected.from = TestMailer.quote_address_if_necessary "Grytøyr <stian1@example.net>", "iso-8859-1"
expected.cc = TestMailer.quote_address_if_necessary "Grytøyr <stian2@example.net>", "iso-8859-1"
expected.bcc = TestMailer.quote_address_if_necessary "Grytøyr <stian3@example.net>", "iso-8859-1"
expected.date = Time.local 2004, 12, 12
created = nil
assert_nothing_raised do
created = TestMailer.create_extended_headers @recipient
end
assert_not_nil created
assert_equal expected.encoded, created.encoded
assert_nothing_raised do
TestMailer.deliver_extended_headers @recipient
end
assert_not_nil ActionMailer::Base.deliveries.first
assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册