Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

We’re showing branches in this repository, but you can also compare across forks.

base fork: rails/rails
...
head fork: rails/rails
  • 11 commits
  • 11 files changed
  • 0 commit comments
  • 1 contributor
14 actionmailer/CHANGELOG
View
@@ -1,3 +1,7 @@
+* Removed all quoting.rb type files from ActionMailer and put Mail 2.2.0 in instead [ML]
+
+* Lot of updates to various test cases that now work better with the new Mail and so have different expectations
+
*Rails 3.0.0 [beta 2] (April 1st, 2010)*
* Added interceptors and observers from Mail [ML]
@@ -5,6 +9,16 @@
ActionMailer::Base.register_interceptor calls Mail.register_interceptor
ActionMailer::Base.register_observer calls Mail.register_observer
+* Mail::Part now no longer has nil as a default charset, it is always set to something, and defaults to UTF-8
+
+* Added explict setting of charset in set_fields! method to make sure Mail has the user defined default
+
+* Removed quoting.rb and refactored for Mail to take responsibility of all quoting and auto encoding requirements for the header.
+
+* Fixed several tests which had incorrect encoding.
+
+* Changed all utf-8 to UTF-8 for consistency
+
* Whole new API added with tests. See base.rb for full details. Old API is deprecated.
2  actionmailer/actionmailer.gemspec
View
@@ -20,6 +20,6 @@ Gem::Specification.new do |s|
s.has_rdoc = true
s.add_dependency('actionpack', version)
- s.add_dependency('mail', '~> 2.1.5.3')
+ s.add_dependency('mail', '~> 2.2.0')
s.add_dependency('text-format', '~> 1.0.0')
end
1  actionmailer/lib/action_mailer.rb
View
@@ -46,7 +46,6 @@ module ActionMailer
autoload :DeprecatedApi
autoload :MailHelper
autoload :OldApi
- autoload :Quoting
autoload :TestCase
autoload :TestHelper
end
24 actionmailer/lib/action_mailer/base.rb
View
@@ -207,7 +207,7 @@ module ActionMailer #:nodoc:
# scores instead of hyphens, so <tt>Content-Transfer-Encoding:</tt>
# becomes <tt>:content_transfer_encoding</tt>. The defaults set by Action Mailer are:
# * <tt>:mime_version => "1.0"</tt>
- # * <tt>:charset => "utf-8",</tt>
+ # * <tt>:charset => "UTF-8",</tt>
# * <tt>:content_type => "text/plain",</tt>
# * <tt>:parts_order => [ "text/plain", "text/enriched", "text/html" ]</tt>
#
@@ -264,7 +264,7 @@ module ActionMailer #:nodoc:
# (i.e. multiple parts are assembled from templates which specify the content type in their
# filenames) this variable controls how the parts are ordered.
class Base < AbstractController::Base
- include DeliveryMethods, Quoting
+ include DeliveryMethods
abstract!
include AbstractController::Logger
@@ -286,7 +286,7 @@ class Base < AbstractController::Base
class_attribute :default_params
self.default_params = {
:mime_version => "1.0",
- :charset => "utf-8",
+ :charset => "UTF-8",
:content_type => "text/plain",
:parts_order => [ "text/plain", "text/enriched", "text/html" ]
}.freeze
@@ -531,7 +531,7 @@ def mail(headers={}, &block)
# Quote fields
headers[:subject] ||= default_i18n_subject
- quote_fields!(headers, charset)
+ set_fields!(headers, charset)
# Render the templates and blocks
responses, explicit_order = collect_responses_and_parts_order(headers, &block)
@@ -577,15 +577,15 @@ def default_i18n_subject #:nodoc:
I18n.t(:subject, :scope => [:actionmailer, mailer_scope, action_name], :default => action_name.humanize)
end
- # TODO: Move this into Mail
- def quote_fields!(headers, charset) #:nodoc:
+ def set_fields!(headers, charset) #:nodoc:
m = @_message
- m.subject ||= quote_if_necessary(headers.delete(:subject), charset) if headers[:subject]
- m.to ||= quote_address_if_necessary(headers.delete(:to), charset) if headers[:to]
- m.from ||= quote_address_if_necessary(headers.delete(:from), charset) if headers[:from]
- m.cc ||= quote_address_if_necessary(headers.delete(:cc), charset) if headers[:cc]
- m.bcc ||= quote_address_if_necessary(headers.delete(:bcc), charset) if headers[:bcc]
- m.reply_to ||= quote_address_if_necessary(headers.delete(:reply_to), charset) if headers[:reply_to]
+ m.charset = charset
+ m.subject ||= headers.delete(:subject) if headers[:subject]
+ m.to ||= headers.delete(:to) if headers[:to]
+ m.from ||= headers.delete(:from) if headers[:from]
+ m.cc ||= headers.delete(:cc) if headers[:cc]
+ m.bcc ||= headers.delete(:bcc) if headers[:bcc]
+ m.reply_to ||= headers.delete(:reply_to) if headers[:reply_to]
end
def collect_responses_and_parts_order(headers) #:nodoc:
4 actionmailer/lib/action_mailer/old_api.rb
View
@@ -147,8 +147,8 @@ def normalize_file_hash(params)
def create_mail
m = @_message
- quote_fields!({:subject => subject, :to => recipients, :from => from,
- :bcc => bcc, :cc => cc, :reply_to => reply_to}, charset)
+ set_fields!({:subject => subject, :to => recipients, :from => from,
+ :bcc => bcc, :cc => cc, :reply_to => reply_to}, charset)
m.mime_version = mime_version unless mime_version.nil?
m.date = sent_on.to_time rescue sent_on if sent_on
64 actionmailer/lib/action_mailer/quoting.rb
View
@@ -1,64 +0,0 @@
-module ActionMailer
- module Quoting #:nodoc:
- # TODO extract this into Mail itself.
- #
- #
- # Convert the given text into quoted printable format, with an instruction
- # that the text be eventually interpreted in the given charset.
- def quoted_printable(text, charset)
- text = text.gsub( /[^a-z ]/i ) { quoted_printable_encode($&) }.
- gsub( / /, "_" )
- "=?#{charset}?Q?#{text}?="
- end
-
- # Convert the given character to quoted printable format, taking into
- # account multi-byte characters (if executing with $KCODE="u", for instance)
- def quoted_printable_encode(character)
- result = ""
- character.each_byte { |b| result << "=%02X" % b }
- result
- end
-
- # A quick-and-dirty regexp for determining whether a string contains any
- # characters that need escaping.
- if !defined?(CHARS_NEEDING_QUOTING)
- CHARS_NEEDING_QUOTING = Regexp.new('[\000-\011\013\014\016-\037\177-\377]', nil, 'n')
- end
-
- # Quote the given text if it contains any "illegal" characters
- def quote_if_necessary(text, charset)
- text = text.dup.force_encoding(Encoding::ASCII_8BIT) if text.respond_to?(:force_encoding)
-
- (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", "bcc" and "reply-to" headers.
- def quote_address_if_necessary(address, charset)
- if Array === address
- address.map { |a| quote_address_if_necessary(a, charset) }.join(", ")
- elsif address =~ /^(\S.*)\s+(<.*>)$/
- address = $2
- phrase = quote_if_necessary($1.gsub(/^['"](.*)['"]$/, '\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
- end
-end
6 actionmailer/lib/action_mailer/test_case.rb
View
@@ -8,7 +8,7 @@ def initialize(name)
end
class TestCase < ActiveSupport::TestCase
- include Quoting, TestHelper
+ include TestHelper
setup :initialize_test_deliveries
setup :set_expected_mail
@@ -48,11 +48,11 @@ def set_expected_mail
private
def charset
- "utf-8"
+ "UTF-8"
end
def encode(subject)
- quoted_printable(subject, charset)
+ Mail::Encodings.q_value_encode(subject, charset)
end
def read_fixture(action)
85 actionmailer/test/old_base/mail_service_test.rb
View
@@ -105,7 +105,7 @@ def utf8_body(recipient)
sent_on Time.local(2004, 12, 12)
cc "Foo áëô îü <extended@example.net>"
bcc "Foo áëô îü <extended@example.net>"
- charset "utf-8"
+ charset "UTF-8"
body "åœö blah"
end
@@ -131,7 +131,7 @@ def multipart_with_utf8_subject(recipient)
recipients recipient
subject "Foo áëô îü"
from "test@example.com"
- charset "utf-8"
+ charset "UTF-8"
part "text/plain" do |p|
p.body = "blah"
@@ -316,18 +316,15 @@ def receive(mail)
end
class ActionMailerTest < Test::Unit::TestCase
- include ActionMailer::Quoting
- def encode( text, charset="utf-8" )
- quoted_printable( text, charset )
+ def encode( text, charset="UTF-8" )
+ Mail::Encodings.q_value_encode( text, charset )
end
- def new_mail( charset="utf-8" )
+ def new_mail( charset="UTF-8" )
mail = Mail.new
+ mail.charset = charset
mail.mime_version = "1.0"
- if charset
- mail.content_type ["text", "plain", { "charset" => charset }]
- end
mail
end
@@ -358,7 +355,7 @@ def test_nested_parts
assert_equal "multipart/mixed", created.mime_type
assert_equal "multipart/alternative", created.parts[0].mime_type
assert_equal "bar", created.parts[0].header['foo'].to_s
- assert_nil created.parts[0].charset
+ assert_not_nil created.parts[0].charset
assert_equal "text/plain", created.parts[0].parts[0].mime_type
assert_equal "text/html", created.parts[0].parts[1].mime_type
assert_equal "application/octet-stream", created.parts[1].mime_type
@@ -570,7 +567,6 @@ def test_reply_to
def test_iso_charset
TestMailer.delivery_method = :test
-
expected = new_mail( "iso-8859-1" )
expected.to = @recipient
expected.subject = encode "testing isø charsets", "iso-8859-1"
@@ -671,14 +667,14 @@ def test_performs_delivery_via_sendmail
def test_unquote_quoted_printable_subject
msg = <<EOF
From: me@example.com
-Subject: =?utf-8?Q?testing_testing_=D6=A4?=
+Subject: =?UTF-8?Q?testing_testing_=D6=A4?=
Content-Type: text/plain; charset=iso-8859-1
The body
EOF
mail = Mail.new(msg)
assert_equal "testing testing \326\244", mail.subject
- assert_equal "Subject: =?utf-8?Q?testing_testing_=D6=A4?=\r\n", mail[:subject].encoded
+ assert_equal "Subject: testing testing =?UTF-8?Q?_=D6=A4=?=\r\n", mail[:subject].encoded
end
def test_unquote_7bit_subject
@@ -719,7 +715,7 @@ def test_unquote_quoted_printable_body
EOF
mail = Mail.new(msg)
assert_equal "The=body", mail.body.to_s.strip
- assert_equal "The=3Dbody", mail.body.encoded.strip
+ assert_equal "The=3Dbody=", mail.body.encoded.strip
end
def test_unquote_base64_body
@@ -740,12 +736,12 @@ def test_extended_headers
@recipient = "Grytøyr <test@localhost>"
expected = new_mail "iso-8859-1"
- expected.to = quote_address_if_necessary @recipient, "iso-8859-1"
+ expected.to = @recipient
expected.subject = "testing extended headers"
expected.body = "Nothing to see here."
- expected.from = quote_address_if_necessary "Grytøyr <stian1@example.net>", "iso-8859-1"
- expected.cc = quote_address_if_necessary "Grytøyr <stian2@example.net>", "iso-8859-1"
- expected.bcc = quote_address_if_necessary "Grytøyr <stian3@example.net>", "iso-8859-1"
+ expected.from = "Grytøyr <stian1@example.net>"
+ expected.cc = "Grytøyr <stian2@example.net>"
+ expected.bcc = "Grytøyr <stian3@example.net>"
expected.date = Time.local 2004, 12, 12
created = nil
@@ -774,13 +770,13 @@ def test_extended_headers
def test_utf8_body_is_not_quoted
@recipient = "Foo áëô îü <extended@example.net>"
- expected = new_mail "utf-8"
- expected.to = quote_address_if_necessary @recipient, "utf-8"
- expected.subject = "testing utf-8 body"
+ expected = new_mail "UTF-8"
+ expected.to = @recipient
+ expected.subject = "testing UTF-8 body"
expected.body = "åœö blah"
- expected.from = quote_address_if_necessary @recipient, "utf-8"
- expected.cc = quote_address_if_necessary @recipient, "utf-8"
- expected.bcc = quote_address_if_necessary @recipient, "utf-8"
+ expected.from = @recipient
+ expected.cc = @recipient
+ expected.bcc = @recipient
expected.date = Time.local 2004, 12, 12
created = TestMailer.utf8_body @recipient
@@ -789,18 +785,21 @@ def test_utf8_body_is_not_quoted
def test_multiple_utf8_recipients
@recipient = ["\"Foo áëô îü\" <extended@example.net>", "\"Example Recipient\" <me@example.com>"]
- expected = new_mail "utf-8"
- expected.to = quote_address_if_necessary @recipient, "utf-8"
- expected.subject = "testing utf-8 body"
+ expected = new_mail "UTF-8"
+ expected.to = @recipient
+ expected.subject = "testing UTF-8 body"
expected.body = "åœö blah"
- expected.from = quote_address_if_necessary @recipient.first, "utf-8"
- expected.cc = quote_address_if_necessary @recipient, "utf-8"
- expected.bcc = quote_address_if_necessary @recipient, "utf-8"
+ expected.from = @recipient.first
+ expected.cc = @recipient
+ expected.bcc = @recipient
expected.date = Time.local 2004, 12, 12
created = TestMailer.utf8_body @recipient
- assert_match(/\nFrom: =\?utf-8\?Q\?Foo_.*?\?= <extended@example.net>\r/, created.encoded)
- assert_match(/\nTo: =\?utf-8\?Q\?Foo_.*?\?= <extended@example.net>, \r\n\tExample Recipient <me/, created.encoded)
+ from_regexp = Regexp.escape('From: Foo =?UTF-8?B?w6HDq8O0?= =?UTF-8?B?IMOuw7w=?=')
+ assert_match(/#{from_regexp}/m, created.encoded)
+
+ to_regexp = Regexp.escape("To: =?UTF-8?B?Rm9vIMOhw6vDtCDDrsO8?= <extended@example.net>")
+ assert_match(/#{to_regexp}/m, created.encoded)
end
def test_receive_decodes_base64_encoded_mail
@@ -864,12 +863,20 @@ def test_multipart_with_mime_version
def test_multipart_with_utf8_subject
mail = TestMailer.multipart_with_utf8_subject(@recipient)
- assert_match(/\nSubject: =\?utf-8\?Q\?Foo_.*?\?=/, mail.encoded)
+ regex = Regexp.escape('Subject: Foo =?UTF-8?Q?=C3=A1=C3=AB=C3=B4=?= =?UTF-8?Q?_=C3=AE=C3=BC=?=')
+ assert_match(/#{regex}/, mail.encoded)
+ string = "Foo áëô îü"
+ string.force_encoding('UTF-8') if string.respond_to?(:force_encoding)
+ assert_match(string, mail.subject)
end
def test_implicitly_multipart_with_utf8
mail = TestMailer.implicitly_multipart_with_utf8
- assert_match(/\nSubject: =\?utf-8\?Q\?Foo_.*?\?=/, mail.encoded)
+ regex = Regexp.escape('Subject: Foo =?UTF-8?Q?=C3=A1=C3=AB=C3=B4=?= =?UTF-8?Q?_=C3=AE=C3=BC=?=')
+ assert_match(/#{regex}/, mail.encoded)
+ string = "Foo áëô îü"
+ string.force_encoding('UTF-8') if string.respond_to?(:force_encoding)
+ assert_match(string, mail.subject)
end
def test_explicitly_multipart_messages
@@ -909,11 +916,11 @@ def test_implicitly_multipart_messages
assert_equal "1.0", mail.mime_version.to_s
assert_equal "multipart/alternative", mail.mime_type
assert_equal "text/plain", mail.parts[0].mime_type
- assert_equal "utf-8", mail.parts[0].charset
+ assert_equal "UTF-8", mail.parts[0].charset
assert_equal "text/html", mail.parts[1].mime_type
- assert_equal "utf-8", mail.parts[1].charset
+ assert_equal "UTF-8", mail.parts[1].charset
assert_equal "application/x-yaml", mail.parts[2].mime_type
- assert_equal "utf-8", mail.parts[2].charset
+ assert_equal "UTF-8", mail.parts[2].charset
end
def test_implicitly_multipart_messages_with_custom_order
@@ -1044,13 +1051,13 @@ def test_multipart_with_template_path_with_dots
mail = FunkyPathMailer.multipart_with_template_path_with_dots(@recipient)
assert_equal 2, mail.parts.length
assert "text/plain", mail.parts[1].mime_type
- assert "utf-8", mail.parts[1].charset
+ assert "UTF-8", mail.parts[1].charset
end
def test_custom_content_type_attributes
mail = TestMailer.custom_content_type_attributes
assert_match %r{format=flowed}, mail.content_type
- assert_match %r{charset=utf-8}, mail.content_type
+ assert_match %r{charset=UTF-8}, mail.content_type
end
def test_return_path_with_create
5 actionmailer/test/old_base/url_test.rb
View
@@ -29,13 +29,12 @@ def signed_up_with_url(recipient)
end
class ActionMailerUrlTest < Test::Unit::TestCase
- include ActionMailer::Quoting
- def encode( text, charset="utf-8" )
+ def encode( text, charset="UTF-8" )
quoted_printable( text, charset )
end
- def new_mail( charset="utf-8" )
+ def new_mail( charset="UTF-8" )
mail = Mail.new
mail.mime_version = "1.0"
if charset
106 actionmailer/test/quoting_test.rb
View
@@ -1,106 +0,0 @@
-# encoding: utf-8
-require 'abstract_unit'
-require 'tempfile'
-
-class QuotingTest < Test::Unit::TestCase
- # Move some tests from TMAIL here
- def test_unquote_quoted_printable
- a ="=?ISO-8859-1?Q?[166417]_Bekr=E6ftelse_fra_Rejsefeber?="
- b = Mail::Encodings.unquote_and_convert_to(a, 'utf-8')
- assert_equal "[166417] Bekr\303\246ftelse fra Rejsefeber", b
- end
-
- def test_unquote_base64
- a ="=?ISO-8859-1?B?WzE2NjQxN10gQmVrcuZmdGVsc2UgZnJhIFJlanNlZmViZXI=?="
- b = Mail::Encodings.unquote_and_convert_to(a, 'utf-8')
- assert_equal "[166417] Bekr\303\246ftelse fra Rejsefeber", b
- end
-
- def test_unquote_without_charset
- a ="[166417]_Bekr=E6ftelse_fra_Rejsefeber"
- b = Mail::Encodings.unquote_and_convert_to(a, 'utf-8')
- assert_equal "[166417]_Bekr=E6ftelse_fra_Rejsefeber", b
- end
-
- def test_unqoute_multiple
- a ="=?utf-8?q?Re=3A_=5B12=5D_=23137=3A_Inkonsistente_verwendung_von_=22Hin?==?utf-8?b?enVmw7xnZW4i?="
- b = Mail::Encodings.unquote_and_convert_to(a, 'utf-8')
- assert_equal "Re: [12] #137: Inkonsistente verwendung von \"Hinzuf\303\274gen\"", b
- end
-
- def test_unqoute_in_the_middle
- a ="Re: Photos =?ISO-8859-1?Q?Brosch=FCre_Rand?="
- b = Mail::Encodings.unquote_and_convert_to(a, 'utf-8')
- assert_equal "Re: Photos Brosch\303\274re Rand", b
- end
-
- def test_unqoute_iso
- a ="=?ISO-8859-1?Q?Brosch=FCre_Rand?="
- b = Mail::Encodings.unquote_and_convert_to(a, 'iso-8859-1')
- expected = "Brosch\374re Rand"
- expected.force_encoding 'iso-8859-1' if expected.respond_to?(:force_encoding)
- assert_equal expected, b
- end
-
- def test_quote_multibyte_chars
- original = "\303\246 \303\270 and \303\245"
- original.force_encoding('ASCII-8BIT') if original.respond_to?(:force_encoding)
-
- result = execute_in_sandbox(<<-CODE)
- $:.unshift(File.dirname(__FILE__) + "/../lib/")
- if RUBY_VERSION < '1.9'
- $KCODE = 'u'
- end
- require 'action_mailer/quoting'
- include ActionMailer::Quoting
- quoted_printable(#{original.inspect}, "UTF-8")
- CODE
-
- unquoted = Mail::Encodings.unquote_and_convert_to(result, nil)
-
- unquoted.force_encoding(Encoding::ASCII_8BIT) if unquoted.respond_to?(:force_encoding)
- original.force_encoding(Encoding::ASCII_8BIT) if original.respond_to?(:force_encoding)
-
- assert_equal unquoted, original
- end
-
-
- # test an email that has been created using \r\n newlines, instead of
- # \n newlines.
- def test_email_quoted_with_0d0a
- mail = Mail.new(IO.read("#{File.dirname(__FILE__)}/fixtures/raw_email_quoted_with_0d0a"))
- # CHANGED: subject returns an object now
- # assert_match %r{Elapsed time}, mail.body
- assert_match %r{Elapsed time}, mail.body.to_s
- end
-
- def test_email_with_partially_quoted_subject
- mail = Mail.new(IO.read("#{File.dirname(__FILE__)}/fixtures/raw_email_with_partially_quoted_subject"))
- # CHANGED: subject returns an object now
- # assert_equal "Re: Test: \"\346\274\242\345\255\227\" mid \"\346\274\242\345\255\227\" tail", mail.subject
- assert_equal "Re: Test: \"\346\274\242\345\255\227\" mid \"\346\274\242\345\255\227\" tail", mail.subject
- end
-
- private
- # This whole thing *could* be much simpler, but I don't think Tempfile,
- # popen and others exist on all platforms (like Windows).
- def execute_in_sandbox(code)
- test_name = "#{File.dirname(__FILE__)}/am-quoting-test.#{$$}.rb"
- res_name = "#{File.dirname(__FILE__)}/am-quoting-test.#{$$}.out"
-
- File.open(test_name, "w+") do |file|
- file.write(<<-CODE)
- block = Proc.new do
- #{code}
- end
- puts block.call
- CODE
- end
-
- system("ruby #{test_name} > #{res_name}") or raise "could not run test in sandbox"
- File.read(res_name).chomp
- ensure
- File.delete(test_name) rescue nil
- File.delete(res_name) rescue nil
- end
-end
6 actionmailer/test/test_helper_test.rb
View
@@ -34,11 +34,7 @@ def test_determine_default_mailer_raises_correct_error
end
def test_charset_is_utf_8
- assert_equal "utf-8", charset
- end
-
- def test_encode
- assert_equal "=?utf-8?Q?=0Aasdf=0A?=", encode("\nasdf\n")
+ assert_equal "UTF-8", charset
end
def test_assert_emails

No commit comments for this range

Something went wrong with that request. Please try again.