From 3fad0cd06c2ff828dd9bb0bb18080572ee992f4f Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 19 Feb 2005 21:51:16 +0000 Subject: [PATCH] Added support for charsets for both subject and body. The default charset is now UTF-8 #673 [Jamis Buck] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@699 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionmailer/CHANGELOG | 22 ++++++ actionmailer/lib/action_mailer/base.rb | 35 ++++++++-- actionmailer/test/mail_service_test.rb | 96 ++++++++++++++++++++++++-- 3 files changed, 141 insertions(+), 12 deletions(-) diff --git a/actionmailer/CHANGELOG b/actionmailer/CHANGELOG index dfe93343f5..c48f47cde3 100644 --- a/actionmailer/CHANGELOG +++ b/actionmailer/CHANGELOG @@ -1,3 +1,25 @@ +*SVN* + +* Added support for charsets for both subject and body. The default charset is now UTF-8 #673 [Jamis Buck]. Examples: + + def iso_charset(recipient) + @recipients = recipient + @subject = "testing iso charsets" + @from = "system@loudthinking.com" + @body = "Nothing to see here." + @charset = "iso-8859-1" + end + + def unencoded_subject(recipient) + @recipients = recipient + @subject = "testing unencoded subject" + @from = "system@loudthinking.com" + @body = "Nothing to see here." + @encode_subject = false + @charset = "iso-8859-1" + end + + *0.6.1* (January 18th, 2005) * Fixed sending of emails to use Tmail#from not the deprecated Tmail#from_address diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 61701d62b7..8b04c42ee0 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -83,10 +83,18 @@ module ActionMailer #:nodoc: @@deliveries = [] cattr_accessor :deliveries - attr_accessor :recipients, :subject, :body, :from, :sent_on, :headers, :bcc, :cc + @@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 def initialize @bcc = @cc = @from = @recipients = @sent_on = @subject = @body = nil + @charset = @@default_charset.dup + @encode_subject = @@encode_subject @headers = {} end @@ -104,14 +112,22 @@ module ActionMailer #:nodoc: end end - def mail(to, subject, body, from, timestamp = nil, headers = nil) #:nodoc: - deliver(create(to, subject, body, from, timestamp, headers)) + def mail(to, subject, body, from, timestamp = nil, headers = {}, + encode = @@encode_subject, charset = @@default_charset + ) #:nodoc: + deliver(create(to, subject, body, from, timestamp, headers, charset)) end - def create(to, subject, body, from, timestamp = nil, headers = nil) #:nodoc: + def create(to, subject, body, from, timestamp = nil, headers = {}, + encode = @@encode_subject, charset = @@default_charset + ) #:nodoc: m = TMail::Mail.new - m.to, m.subject, m.body, m.from = to, subject, body, from + m.to, m.subject, m.body, m.from = to, + ( encode ? quoted_printable(subject,charset) : subject ), body, from m.date = timestamp.respond_to?("to_time") ? timestamp.to_time : (timestamp || Time.now) + + m.set_content_type "text", "plain", { "charset" => charset } + headers.each do |k, v| m[k] = v end @@ -124,6 +140,12 @@ module ActionMailer #:nodoc: send("perform_delivery_#{delivery_method}", mail) if perform_deliveries end + def quoted_printable( text, charset ) + text = text.gsub( /[^a-z ]/i ) { "=%02x" % $&[0] }. + gsub( / /, "_" ) + "=?#{charset}?Q?#{text}?=" + end + private def perform_delivery_smtp(mail) Net::SMTP.start(server_settings[:address], server_settings[:port], server_settings[:domain], @@ -153,7 +175,8 @@ module ActionMailer #:nodoc: end mail = create(mailer.recipients, mailer.subject, mailer.body, - mailer.from, mailer.sent_on, mailer.headers) + mailer.from, mailer.sent_on, mailer.headers, + mailer.encode_subject, mailer.charset) mail.bcc = mailer.bcc unless mailer.bcc.nil? mail.cc = mailer.cc unless mailer.cc.nil? diff --git a/actionmailer/test/mail_service_test.rb b/actionmailer/test/mail_service_test.rb index 2ad85b605c..45423a1960 100755 --- a/actionmailer/test/mail_service_test.rb +++ b/actionmailer/test/mail_service_test.rb @@ -31,12 +31,46 @@ class TestMailer < ActionMailer::Base @body = "Nothing to see here." end + def iso_charset(recipient) + @recipients = recipient + @subject = "testing iso charsets" + @from = "system@loudthinking.com" + @sent_on = Time.local 2004, 12, 12 + @cc = "nobody@loudthinking.com" + @bcc = "root@loudthinking.com" + @body = "Nothing to see here." + @charset = "iso-8859-1" + end + + def unencoded_subject(recipient) + @recipients = recipient + @subject = "testing unencoded subject" + @from = "system@loudthinking.com" + @sent_on = Time.local 2004, 12, 12 + @cc = "nobody@loudthinking.com" + @bcc = "root@loudthinking.com" + @body = "Nothing to see here." + @encode_subject = false + end + end TestMailer.template_root = File.dirname(__FILE__) + "/fixtures" class ActionMailerTest < Test::Unit::TestCase + def encode( text, charset="utf-8" ) + ActionMailer::Base.quoted_printable( text, charset ) + end + + def new_mail( charset="utf-8" ) + mail = TMail::Mail.new + if charset + mail.set_content_type "text", "plain", { "charset" => charset } + end + mail + end + def setup ActionMailer::Base.delivery_method = :test ActionMailer::Base.perform_deliveries = true @@ -46,9 +80,9 @@ class ActionMailerTest < Test::Unit::TestCase end def test_signed_up - expected = TMail::Mail.new + expected = new_mail expected.to = @recipient - expected.subject = "[Signed up] Welcome #{@recipient}" + expected.subject = encode "[Signed up] Welcome #{@recipient}" expected.body = "Hello there, \n\nMr. #{@recipient}" expected.from = "system@loudthinking.com" expected.date = Time.local(2004, 12, 12) @@ -64,9 +98,9 @@ class ActionMailerTest < Test::Unit::TestCase end def test_cancelled_account - expected = TMail::Mail.new + expected = new_mail expected.to = @recipient - expected.subject = "[Cancelled] Goodbye #{@recipient}" + expected.subject = encode "[Cancelled] Goodbye #{@recipient}" expected.body = "Goodbye, Mr. #{@recipient}" expected.from = "system@loudthinking.com" expected.date = Time.local(2004, 12, 12) @@ -82,9 +116,9 @@ class ActionMailerTest < Test::Unit::TestCase end def test_cc_bcc - expected = TMail::Mail.new + expected = new_mail expected.to = @recipient - expected.subject = "testing bcc/cc" + expected.subject = encode "testing bcc/cc" expected.body = "Nothing to see here." expected.from = "system@loudthinking.com" expected.cc = "nobody@loudthinking.com" @@ -106,6 +140,56 @@ class ActionMailerTest < Test::Unit::TestCase assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded end + def test_iso_charset + expected = new_mail( "iso-8859-1" ) + expected.to = @recipient + expected.subject = encode "testing iso charsets", "iso-8859-1" + expected.body = "Nothing to see here." + expected.from = "system@loudthinking.com" + expected.cc = "nobody@loudthinking.com" + expected.bcc = "root@loudthinking.com" + expected.date = Time.local 2004, 12, 12 + + created = nil + assert_nothing_raised do + created = TestMailer.create_iso_charset @recipient + end + assert_not_nil created + assert_equal expected.encoded, created.encoded + + assert_nothing_raised do + TestMailer.deliver_iso_charset @recipient + end + + assert_not_nil ActionMailer::Base.deliveries.first + assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded + end + + def test_unencoded_subject + expected = new_mail + expected.to = @recipient + expected.subject = "testing unencoded subject" + expected.body = "Nothing to see here." + expected.from = "system@loudthinking.com" + expected.cc = "nobody@loudthinking.com" + expected.bcc = "root@loudthinking.com" + expected.date = Time.local 2004, 12, 12 + + created = nil + assert_nothing_raised do + created = TestMailer.create_unencoded_subject @recipient + end + assert_not_nil created + assert_equal expected.encoded, created.encoded + + assert_nothing_raised do + TestMailer.deliver_unencoded_subject @recipient + end + + assert_not_nil ActionMailer::Base.deliveries.first + assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded + end + def test_instances_are_nil assert_nil ActionMailer::Base.new assert_nil TestMailer.new