staugaard-idn_actionmailer 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ === 0.2 / 2008-05-27
2
+
3
+ * 1 major enhancement
4
+
5
+ * Implemented the main feature
6
+
@@ -0,0 +1,9 @@
1
+ = IdnActionmailer
2
+
3
+ idn_actionmailer is a gem that patches actionmailer to support recipients on domains with international characters.
4
+
5
+ This is done by encoding these domain names.
6
+
7
+ To use this gem in your rails project just install it and and " require 'idn_actionmailer' " to the bottom of your environment.rb.
8
+
9
+ I KNOW NOTHING ABOUT HOW THE ENCODING WORKS. I just patched the actionmailer code.
@@ -0,0 +1,17 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/idn_actionmailer.rb'
6
+
7
+ Hoe.new('IdnActionmailer', IdnActionmailer::VERSION) do |p|
8
+ p.author = 'Mick Staugaard'
9
+ p.email = 'mick@staugaard.com'
10
+ p.summary = 'monkey patch for ActionMailer to support international domain names'
11
+ p.description = 'monkey patch for ActionMailer to support international domain names'
12
+ p.url = 'http://github.com/staugaard/idn_actionmailer'
13
+ p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
14
+ #p.extra_deps << ['mime-types']
15
+ end
16
+
17
+ # vim: syntax=Ruby
@@ -0,0 +1,18 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "idn_actionmailer"
3
+ s.version = "0.2"
4
+ s.date = "2008-05-27"
5
+ s.summary = "monkey patch for ActionMailer to support international domain names"
6
+ s.email = "mick@staugaard.com"
7
+ s.homepage = "http://github.com/staugaard/idn_actionmailer"
8
+ s.description = "monkey patch for ActionMailer to support international domain names"
9
+ s.has_rdoc = false
10
+ s.authors = ["Mick Staugaard"]
11
+ s.files = ["History.txt", "README.txt", "Rakefile", "idn_actionmailer.gemspec", "lib/idn_actionmailer.rb"]
12
+ s.test_files = ["test/test_encoding.rb", "test/test_idn_actionmailer.rb", "test/fixtures/test_mailer/signed_up_with_url.erb", "test/fixtures/test_mailer/signed_up_with_url.rhtml"]
13
+ s.rdoc_options = ["--main", "README.txt"]
14
+ s.extra_rdoc_files = ["History.txt", "README.txt"]
15
+ s.add_dependency("actionmailer", [">= 2.0.2"])
16
+ s.add_dependency("unicode", [">= 0.1"])
17
+ s.add_dependency("punycode4r", [">= 0.2.0"])
18
+ end
@@ -0,0 +1,69 @@
1
+ require 'rubygems'
2
+ require 'unicode'
3
+ require 'punycode'
4
+ require 'actionmailer'
5
+
6
+ class IdnActionmailer
7
+ VERSION = '0.2'
8
+
9
+ UTF8REGEX = /\A(?:
10
+ [\x09\x0A\x0D\x20-\x7E] # ASCII
11
+ | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
12
+ | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
13
+ | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
14
+ | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
15
+ | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
16
+ | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
17
+ | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
18
+ )*\z/mnx
19
+
20
+
21
+ UTF8_REGEX_MBYTE = /(?:
22
+ [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
23
+ | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
24
+ | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
25
+ | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
26
+ | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
27
+ | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
28
+ | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
29
+ )/mnx
30
+
31
+ def self.encode(str)
32
+ if str =~ UTF8REGEX && str =~ UTF8_REGEX_MBYTE
33
+
34
+ parts = Unicode::downcase(str).split('.')
35
+ parts.map! do |part|
36
+ if part =~ UTF8REGEX && part =~ UTF8_REGEX_MBYTE
37
+ "xn--" + Punycode.encode(Unicode::normalize_KC(part))
38
+ else
39
+ part
40
+ end
41
+ end
42
+
43
+ parts.join('.')
44
+ else
45
+ str
46
+ end
47
+ end
48
+ end
49
+
50
+ module ActionMailer
51
+ module Quoting
52
+ alias_method :orig_quote_address_if_necessary, :quote_address_if_necessary
53
+
54
+ def quote_address_if_necessary(address, charset)
55
+ if Array === address
56
+ orig_quote_address_if_necessary(address, charset)
57
+ else
58
+ if(address =~ /^(.*(<)?.*@)(.*)(>)?$/)
59
+ predomain = $1
60
+ domain = IdnActionmailer.encode($3)
61
+ postdomain = $4
62
+ orig_quote_address_if_necessary("#{predomain}#{domain}#{postdomain}", charset)
63
+ else
64
+ orig_quote_address_if_necessary(address, charset)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,24 @@
1
+ require "test/unit"
2
+
3
+ require "idn_actionmailer"
4
+
5
+ class EncodingTest < Test::Unit::TestCase
6
+ def setup
7
+ @domains = [['مثال.إختبار', 'xn--mgbh0fb.xn--kgbechtv'],
8
+ ['例子.测试', 'xn--fsqu00a.xn--0zwm56d'],
9
+ ['例子.測試', 'xn--fsqu00a.xn--g6w251d'],
10
+ ['παράδειγμα.δοκιμή', 'xn--hxajbheg2az3al.xn--jxalpdlp'],
11
+ ['उदाहरण.परीक्षा', 'xn--p1b6ci4b4b3a.xn--11b5bs3a9aj6g'],
12
+ ['例え.テスト', 'xn--r8jz45g.xn--zckzah'],
13
+ ['실례.테스트', 'xn--9n2bp8q.xn--9t4b11yi5a'],
14
+ ['пример.испытание', 'xn--e1afmkfd.xn--80akhbyknj4f'],
15
+ ['உதாரணம்.பரிட்சை', 'xn--zkc6cc5bi7f6e.xn--hlcj6aya9esc7a'],
16
+ ['blåbærgrød.dk', 'xn--blbrgrd-fxak7p.dk']]
17
+ end
18
+
19
+ def test_encoding
20
+ @domains.each do |pair|
21
+ assert_equal(pair[1], IdnActionmailer.encode(pair[0]))
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,83 @@
1
+ require "test/unit"
2
+
3
+ require "idn_actionmailer"
4
+
5
+ ActionMailer::Base.template_root = "#{File.dirname(__FILE__)}/fixtures"
6
+
7
+ class TestMailer < ActionMailer::Base
8
+
9
+ default_url_options[:host] = 'www.basecamphq.com'
10
+
11
+ def signed_up_with_url(recipient)
12
+ @recipients = recipient
13
+ @subject = "[Signed up] Welcome"
14
+ @from = "bla <system@loudthinking.com>"
15
+ @sent_on = Time.local(2004, 12, 12)
16
+
17
+ @body["recipient"] = recipient
18
+ end
19
+
20
+ class <<self
21
+ attr_accessor :received_body
22
+ end
23
+
24
+ def receive(mail)
25
+ self.class.received_body = mail.body
26
+ end
27
+ end
28
+
29
+ class ActionMailerUrlTest < Test::Unit::TestCase
30
+ include ActionMailer::Quoting
31
+
32
+ def encode( text, charset="utf-8" )
33
+ quoted_printable( text, charset )
34
+ end
35
+
36
+ def new_mail( charset="utf-8" )
37
+ mail = TMail::Mail.new
38
+ mail.mime_version = "1.0"
39
+ if charset
40
+ mail.set_content_type "text", "plain", { "charset" => charset }
41
+ end
42
+ mail
43
+ end
44
+
45
+ def setup
46
+ ActionMailer::Base.delivery_method = :test
47
+ ActionMailer::Base.perform_deliveries = true
48
+ ActionMailer::Base.deliveries = []
49
+ end
50
+
51
+ def test_single_address
52
+
53
+ expected = new_mail
54
+ expected.to = 'bla <mick@xn--brndendekrlighed-vobh.dk>'
55
+ expected.subject = "[Signed up] Welcome"
56
+ expected.body = "Hello there"
57
+ expected.from = "bla <system@loudthinking.com>"
58
+ expected.date = Time.local(2004, 12, 12)
59
+
60
+ created = nil
61
+ assert_nothing_raised { created = TestMailer.create_signed_up_with_url('bla <mick@brændendekærlighed.dk>') }
62
+ assert_not_nil created
63
+ assert_equal expected.encoded, created.encoded
64
+
65
+ assert_nothing_raised { TestMailer.deliver_signed_up_with_url('bla <mick@brændendekærlighed.dk>') }
66
+ assert_not_nil ActionMailer::Base.deliveries.first
67
+ assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
68
+ end
69
+
70
+ def test_multi_addresses
71
+ expected = new_mail
72
+ expected.to = ['bla <mick@xn--brndendekrlighed-vobh.dk>', 'mick@xn--brndendekrlighed-vobh.dk']
73
+ expected.subject = "[Signed up] Welcome"
74
+ expected.body = "Hello there"
75
+ expected.from = "bla <system@loudthinking.com>"
76
+ expected.date = Time.local(2004, 12, 12)
77
+
78
+ created = nil
79
+ assert_nothing_raised { created = TestMailer.create_signed_up_with_url(['bla <mick@brændendekærlighed.dk>', 'mick@brændendekærlighed.dk']) }
80
+ assert_not_nil created
81
+ assert_equal expected.encoded, created.encoded
82
+ end
83
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: staugaard-idn_actionmailer
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.2"
5
+ platform: ruby
6
+ authors:
7
+ - Mick Staugaard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-05-27 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: actionmailer
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.0.2
23
+ version:
24
+ - !ruby/object:Gem::Dependency
25
+ name: unicode
26
+ version_requirement:
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - ">="
30
+ - !ruby/object:Gem::Version
31
+ version: "0.1"
32
+ version:
33
+ - !ruby/object:Gem::Dependency
34
+ name: punycode4r
35
+ version_requirement:
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.2.0
41
+ version:
42
+ description: monkey patch for ActionMailer to support international domain names
43
+ email: mick@staugaard.com
44
+ executables: []
45
+
46
+ extensions: []
47
+
48
+ extra_rdoc_files:
49
+ - History.txt
50
+ - README.txt
51
+ files:
52
+ - History.txt
53
+ - README.txt
54
+ - Rakefile
55
+ - idn_actionmailer.gemspec
56
+ - lib/idn_actionmailer.rb
57
+ has_rdoc: false
58
+ homepage: http://github.com/staugaard/idn_actionmailer
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --main
62
+ - README.txt
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "0"
70
+ version:
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ requirements: []
78
+
79
+ rubyforge_project:
80
+ rubygems_version: 1.0.1
81
+ signing_key:
82
+ specification_version: 2
83
+ summary: monkey patch for ActionMailer to support international domain names
84
+ test_files:
85
+ - test/test_encoding.rb
86
+ - test/test_idn_actionmailer.rb
87
+ - test/fixtures/test_mailer/signed_up_with_url.erb
88
+ - test/fixtures/test_mailer/signed_up_with_url.rhtml