1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

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
This commit is contained in:
David Heinemeier Hansson 2005-04-11 10:29:15 +00:00
parent ea803aa4e3
commit 256e800a01
3 changed files with 91 additions and 20 deletions

View file

@ -1,5 +1,9 @@
*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]

View file

@ -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 @@ module ActionMailer #:nodoc:
@@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 @@ module ActionMailer #: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 @@ module ActionMailer #: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 @@ module ActionMailer #:nodoc:
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

View file

@ -33,7 +33,7 @@ class TestMailer < ActionMailer::Base
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 @@ class TestMailer < ActionMailer::Base
@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 @@ class ActionMailerTest < Test::Unit::TestCase
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 @@ class ActionMailerTest < Test::Unit::TestCase
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 @@ class ActionMailerTest < Test::Unit::TestCase
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 @@ class ActionMailerTest < Test::Unit::TestCase
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 @@ EOF
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