staugaard-idn_actionmailer 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +6 -0
- data/README.txt +9 -0
- data/Rakefile +17 -0
- data/idn_actionmailer.gemspec +18 -0
- data/lib/idn_actionmailer.rb +69 -0
- data/test/fixtures/test_mailer/signed_up_with_url.erb +1 -0
- data/test/fixtures/test_mailer/signed_up_with_url.rhtml +0 -0
- data/test/test_encoding.rb +24 -0
- data/test/test_idn_actionmailer.rb +83 -0
- metadata +88 -0
data/History.txt
ADDED
data/README.txt
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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 @@
|
|
1
|
+
Hello there
|
File without changes
|
@@ -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
|