mail 2.2.15 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +38 -0
- data/Dependencies.txt +3 -0
- data/Gemfile +29 -0
- data/Rakefile +1 -1
- data/lib/VERSION +2 -2
- data/lib/mail/body.rb +10 -4
- data/lib/mail/configuration.rb +2 -0
- data/lib/mail/core_extensions/nil.rb +2 -0
- data/lib/mail/core_extensions/object.rb +13 -0
- data/lib/mail/core_extensions/shellwords.rb +2 -0
- data/lib/mail/core_extensions/smtp.rb +1 -0
- data/lib/mail/core_extensions/string/access.rb +104 -0
- data/lib/mail/core_extensions/string/multibyte.rb +78 -0
- data/lib/mail/core_extensions/string.rb +5 -1
- data/lib/mail/encodings.rb +43 -43
- data/lib/mail/field.rb +2 -1
- data/lib/mail/fields/common/common_message_id.rb +1 -1
- data/lib/mail/fields/common/parameter_hash.rb +5 -5
- data/lib/mail/fields/received_field.rb +11 -3
- data/lib/mail/fields/return_path_field.rb +1 -0
- data/lib/mail/fields/unstructured_field.rb +1 -0
- data/lib/mail/header.rb +2 -1
- data/lib/mail/indifferent_hash.rb +146 -0
- data/lib/mail/message.rb +26 -4
- data/lib/mail/multibyte/chars.rb +474 -0
- data/lib/mail/multibyte/exceptions.rb +8 -0
- data/lib/mail/multibyte/unicode.rb +392 -0
- data/lib/mail/multibyte/utils.rb +60 -0
- data/lib/mail/multibyte.rb +42 -0
- data/lib/mail/network/delivery_methods/smtp.rb +4 -3
- data/lib/mail/network/delivery_methods/smtp_connection.rb +74 -0
- data/lib/mail/network/retriever_methods/test_retriever.rb +8 -1
- data/lib/mail/network.rb +1 -0
- data/lib/mail/part.rb +1 -1
- data/lib/mail/parts_list.rb +17 -9
- data/lib/mail/version_specific/ruby_1_8.rb +14 -13
- data/lib/mail/version_specific/ruby_1_9.rb +19 -16
- data/lib/mail.rb +12 -7
- metadata +31 -28
data/CHANGELOG.rdoc
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
== Tue Apr 26 09:59:56 UTC 2011 Mikel Lindsaar <mikel@rubyx.com>
|
|
2
|
+
|
|
3
|
+
* Remove ActiveSupport from the dependencies, load Active Support if present, or use internals if not
|
|
4
|
+
* Created v2.2 branch for all 2.2 related commits
|
|
5
|
+
* Update activesupport require to use inflector - closes #217
|
|
6
|
+
* Version bump to 2.3 and gem release
|
|
7
|
+
|
|
8
|
+
== Tue Apr 26 06:18:19 UTC 2011 Mikel Lindsaar <mikel@rubyx.com>
|
|
9
|
+
|
|
10
|
+
* Fixed charset warning issue with multipart messages - https://github.com/arvindsv
|
|
11
|
+
* Version bump to 2.2.18 and gem release
|
|
12
|
+
|
|
13
|
+
== Wed 20 Apr 2011 15:16:20 UTC Mikel Lindsaar <mikel@rubyx.com>
|
|
14
|
+
|
|
15
|
+
* Mail::Field.new("Subject: foobar", 'iso-2022-jp') does not set charset - https://github.com/yalab
|
|
16
|
+
|
|
17
|
+
== Tue Apr 19 00:20:54 UTC 2011 Mikel Lindsaar <mikel@rubyx.com>
|
|
18
|
+
|
|
19
|
+
* Fixed an exception with nil in Reply-To and References field - https://github.com/dcormier
|
|
20
|
+
* Version bump to 2.2.17 and gem release
|
|
21
|
+
|
|
22
|
+
== Sat Apr 16 12:57:27 UTC 2011 Mikel Lindsaar <mikel@rubyx.com>
|
|
23
|
+
|
|
24
|
+
* Added support for open SMTP connections and returning the Mail server's response - https://github.com/spiegela
|
|
25
|
+
* RE: not appended to subject when replying to a reply - https://github.com/prateekdayal
|
|
26
|
+
* Support not ascii compatible charset mail send - https://github.com/yalab
|
|
27
|
+
* Fix for issue 208 "mail.body after mail.add_file truncates message body" - https://github.com/glongman
|
|
28
|
+
* Handle bad subject encoding (or ":invalid => :replace" is ineffective for utf-8 to utf-8 encoding) - https://github.com/choonkeat
|
|
29
|
+
* Handle blank Received header field - https://github.com/bcantin
|
|
30
|
+
* Handle part with missing content type - https://github.com/bcantin
|
|
31
|
+
* Handle a "<>" Return field - https://github.com/bcantin
|
|
32
|
+
* Performance improvements for 1.9 - https://github.com/nobu
|
|
33
|
+
* Fix heavy CPU issues when messages are missing a space - https://github.com/scsmith
|
|
34
|
+
* Tighten up allowed encodings - https://github.com/scsmith
|
|
35
|
+
* Added to_yaml & from_yaml (as well as to_hash & from_hash) - https://github.com/srushti
|
|
36
|
+
* Fix up some comments - https://github.com/takahashim
|
|
37
|
+
* Version bump to 2.2.16 and gem release
|
|
38
|
+
|
|
1
39
|
== Wed 26 Jan 2011 02:23:09 UTC Mikel Lindsaar <mikel@rubyx.com>
|
|
2
40
|
|
|
3
41
|
* Update addresses passed into sendmail to escape them (Andy Lindeman)
|
data/Dependencies.txt
ADDED
data/Gemfile
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
source :rubygems
|
|
2
|
+
|
|
3
|
+
gem "activesupport", ">= 2.3.6"
|
|
4
|
+
gem "tlsmail" if RUBY_VERSION <= '1.8.6'
|
|
5
|
+
gem "mime-types", "~> 1.16"
|
|
6
|
+
gem "treetop", "~> 1.4.8"
|
|
7
|
+
gem "i18n", ">= 0.4.0"
|
|
8
|
+
|
|
9
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
|
10
|
+
gem 'jruby-openssl'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
group :test do
|
|
14
|
+
gem "ZenTest", "~> 4.4.0"
|
|
15
|
+
gem "rake", "~> 0.8.7"
|
|
16
|
+
gem "bundler"
|
|
17
|
+
gem "rspec", "~> 1.3.0"
|
|
18
|
+
gem "diff-lcs"
|
|
19
|
+
case
|
|
20
|
+
when defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
|
|
21
|
+
# Skip it
|
|
22
|
+
when RUBY_PLATFORM == 'java'
|
|
23
|
+
# Skip it
|
|
24
|
+
when RUBY_VERSION < '1.9'
|
|
25
|
+
gem "ruby-debug"
|
|
26
|
+
else
|
|
27
|
+
# Skip it
|
|
28
|
+
end
|
|
29
|
+
end
|
data/Rakefile
CHANGED
data/lib/VERSION
CHANGED
data/lib/mail/body.rb
CHANGED
|
@@ -162,7 +162,12 @@ module Mail
|
|
|
162
162
|
else
|
|
163
163
|
# Decode then encode to normalize and allow transforming
|
|
164
164
|
# from base64 to Q-P and vice versa
|
|
165
|
-
|
|
165
|
+
decoded = dec.decode(raw_source)
|
|
166
|
+
if defined?(Encoding) && charset && charset != "US-ASCII"
|
|
167
|
+
decoded.encode!(charset)
|
|
168
|
+
decoded.force_encoding('BINARY') unless Encoding.find(charset).ascii_compatible?
|
|
169
|
+
end
|
|
170
|
+
enc.encode(decoded)
|
|
166
171
|
end
|
|
167
172
|
end
|
|
168
173
|
end
|
|
@@ -196,10 +201,11 @@ module Mail
|
|
|
196
201
|
end
|
|
197
202
|
|
|
198
203
|
def encoding=( val )
|
|
199
|
-
if val == "text" || val.blank?
|
|
200
|
-
|
|
204
|
+
@encoding = if val == "text" || val.blank?
|
|
205
|
+
(only_us_ascii? ? '7bit' : '8bit')
|
|
206
|
+
else
|
|
207
|
+
val
|
|
201
208
|
end
|
|
202
|
-
@encoding = (val == "text") ? "8bit" : val
|
|
203
209
|
end
|
|
204
210
|
|
|
205
211
|
# Returns the preamble (any text that is before the first MIME boundary)
|
data/lib/mail/configuration.rb
CHANGED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# This is not loaded if ActiveSupport is already loaded
|
|
4
|
+
|
|
5
|
+
# This is an almost cut and paste from ActiveSupport v3.0.6, copied in here so that Mail
|
|
6
|
+
# itself does not depend on ActiveSupport to avoid versioning conflicts
|
|
7
|
+
|
|
8
|
+
class String
|
|
9
|
+
unless '1.9'.respond_to?(:force_encoding)
|
|
10
|
+
# Returns the character at the +position+ treating the string as an array (where 0 is the first character).
|
|
11
|
+
#
|
|
12
|
+
# Examples:
|
|
13
|
+
# "hello".at(0) # => "h"
|
|
14
|
+
# "hello".at(4) # => "o"
|
|
15
|
+
# "hello".at(10) # => ERROR if < 1.9, nil in 1.9
|
|
16
|
+
def at(position)
|
|
17
|
+
mb_chars[position, 1].to_s
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns the remaining of the string from the +position+ treating the string as an array (where 0 is the first character).
|
|
21
|
+
#
|
|
22
|
+
# Examples:
|
|
23
|
+
# "hello".from(0) # => "hello"
|
|
24
|
+
# "hello".from(2) # => "llo"
|
|
25
|
+
# "hello".from(10) # => "" if < 1.9, nil in 1.9
|
|
26
|
+
def from(position)
|
|
27
|
+
mb_chars[position..-1].to_s
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Returns the beginning of the string up to the +position+ treating the string as an array (where 0 is the first character).
|
|
31
|
+
#
|
|
32
|
+
# Examples:
|
|
33
|
+
# "hello".to(0) # => "h"
|
|
34
|
+
# "hello".to(2) # => "hel"
|
|
35
|
+
# "hello".to(10) # => "hello"
|
|
36
|
+
def to(position)
|
|
37
|
+
mb_chars[0..position].to_s
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Returns the first character of the string or the first +limit+ characters.
|
|
41
|
+
#
|
|
42
|
+
# Examples:
|
|
43
|
+
# "hello".first # => "h"
|
|
44
|
+
# "hello".first(2) # => "he"
|
|
45
|
+
# "hello".first(10) # => "hello"
|
|
46
|
+
def first(limit = 1)
|
|
47
|
+
if limit == 0
|
|
48
|
+
''
|
|
49
|
+
elsif limit >= size
|
|
50
|
+
self
|
|
51
|
+
else
|
|
52
|
+
mb_chars[0...limit].to_s
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Returns the last character of the string or the last +limit+ characters.
|
|
57
|
+
#
|
|
58
|
+
# Examples:
|
|
59
|
+
# "hello".last # => "o"
|
|
60
|
+
# "hello".last(2) # => "lo"
|
|
61
|
+
# "hello".last(10) # => "hello"
|
|
62
|
+
def last(limit = 1)
|
|
63
|
+
if limit == 0
|
|
64
|
+
''
|
|
65
|
+
elsif limit >= size
|
|
66
|
+
self
|
|
67
|
+
else
|
|
68
|
+
mb_chars[(-limit)..-1].to_s
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
else
|
|
72
|
+
def at(position)
|
|
73
|
+
self[position]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def from(position)
|
|
77
|
+
self[position..-1]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def to(position)
|
|
81
|
+
self[0..position]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def first(limit = 1)
|
|
85
|
+
if limit == 0
|
|
86
|
+
''
|
|
87
|
+
elsif limit >= size
|
|
88
|
+
self
|
|
89
|
+
else
|
|
90
|
+
to(limit - 1)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def last(limit = 1)
|
|
95
|
+
if limit == 0
|
|
96
|
+
''
|
|
97
|
+
elsif limit >= size
|
|
98
|
+
self
|
|
99
|
+
else
|
|
100
|
+
from(-limit)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
# This is not loaded if ActiveSupport is already loaded
|
|
4
|
+
|
|
5
|
+
# This is an almost cut and paste from ActiveSupport v3.0.6, copied in here so that Mail
|
|
6
|
+
# itself does not depend on ActiveSupport to avoid versioning conflicts
|
|
7
|
+
|
|
8
|
+
require 'mail/multibyte'
|
|
9
|
+
|
|
10
|
+
class String
|
|
11
|
+
if RUBY_VERSION >= "1.9"
|
|
12
|
+
# == Multibyte proxy
|
|
13
|
+
#
|
|
14
|
+
# +mb_chars+ is a multibyte safe proxy for string methods.
|
|
15
|
+
#
|
|
16
|
+
# In Ruby 1.8 and older it creates and returns an instance of the Mail::Multibyte::Chars class which
|
|
17
|
+
# encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy
|
|
18
|
+
# class. If the proxy class doesn't respond to a certain method, it's forwarded to the encapsuled string.
|
|
19
|
+
#
|
|
20
|
+
# name = 'Claus Müller'
|
|
21
|
+
# name.reverse # => "rell??M sualC"
|
|
22
|
+
# name.length # => 13
|
|
23
|
+
#
|
|
24
|
+
# name.mb_chars.reverse.to_s # => "rellüM sualC"
|
|
25
|
+
# name.mb_chars.length # => 12
|
|
26
|
+
#
|
|
27
|
+
# In Ruby 1.9 and newer +mb_chars+ returns +self+ because String is (mostly) encoding aware. This means that
|
|
28
|
+
# it becomes easy to run one version of your code on multiple Ruby versions.
|
|
29
|
+
#
|
|
30
|
+
# == Method chaining
|
|
31
|
+
#
|
|
32
|
+
# All the methods on the Chars proxy which normally return a string will return a Chars object. This allows
|
|
33
|
+
# method chaining on the result of any of these methods.
|
|
34
|
+
#
|
|
35
|
+
# name.mb_chars.reverse.length # => 12
|
|
36
|
+
#
|
|
37
|
+
# == Interoperability and configuration
|
|
38
|
+
#
|
|
39
|
+
# The Chars object tries to be as interchangeable with String objects as possible: sorting and comparing between
|
|
40
|
+
# String and Char work like expected. The bang! methods change the internal string representation in the Chars
|
|
41
|
+
# object. Interoperability problems can be resolved easily with a +to_s+ call.
|
|
42
|
+
#
|
|
43
|
+
# For more information about the methods defined on the Chars proxy see Mail::Multibyte::Chars. For
|
|
44
|
+
# information about how to change the default Multibyte behaviour see Mail::Multibyte.
|
|
45
|
+
def mb_chars
|
|
46
|
+
if Mail::Multibyte.proxy_class.consumes?(self)
|
|
47
|
+
Mail::Multibyte.proxy_class.new(self)
|
|
48
|
+
else
|
|
49
|
+
self
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def is_utf8? #:nodoc
|
|
54
|
+
case encoding
|
|
55
|
+
when Encoding::UTF_8
|
|
56
|
+
valid_encoding?
|
|
57
|
+
when Encoding::ASCII_8BIT, Encoding::US_ASCII
|
|
58
|
+
dup.force_encoding(Encoding::UTF_8).valid_encoding?
|
|
59
|
+
else
|
|
60
|
+
false
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
else
|
|
64
|
+
def mb_chars
|
|
65
|
+
if Mail::Multibyte.proxy_class.wants?(self)
|
|
66
|
+
Mail::Multibyte.proxy_class.new(self)
|
|
67
|
+
else
|
|
68
|
+
self
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Returns true if the string has UTF-8 semantics (a String used for purely byte resources is unlikely to have
|
|
73
|
+
# them), returns false otherwise.
|
|
74
|
+
def is_utf8?
|
|
75
|
+
Mail::Multibyte::Chars.consumes?(self)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -8,6 +8,10 @@ class String #:nodoc:
|
|
|
8
8
|
gsub(/\n|\r\n|\r/) { "\n" }
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def blank?
|
|
12
|
+
self !~ /\S/
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
unless method_defined?(:ascii_only?)
|
|
12
16
|
# Provides all strings with the Ruby 1.9 method of .ascii_only? and
|
|
13
17
|
# returns true or false
|
|
@@ -16,7 +20,7 @@ class String #:nodoc:
|
|
|
16
20
|
!(self =~ /[^#{US_ASCII_REGEXP}]/)
|
|
17
21
|
end
|
|
18
22
|
end
|
|
19
|
-
|
|
23
|
+
|
|
20
24
|
def not_ascii_only?
|
|
21
25
|
!ascii_only?
|
|
22
26
|
end
|
data/lib/mail/encodings.rb
CHANGED
|
@@ -6,12 +6,12 @@ module Mail
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
module Encodings
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
include Mail::Patterns
|
|
11
11
|
extend Mail::Utilities
|
|
12
12
|
|
|
13
13
|
@transfer_encodings = {}
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
# Register transfer encoding
|
|
16
16
|
#
|
|
17
17
|
# Example
|
|
@@ -20,23 +20,23 @@ module Mail
|
|
|
20
20
|
def Encodings.register(name, cls)
|
|
21
21
|
@transfer_encodings[get_name(name)] = cls
|
|
22
22
|
end
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
# Is the encoding we want defined?
|
|
25
|
-
#
|
|
25
|
+
#
|
|
26
26
|
# Example:
|
|
27
|
-
#
|
|
27
|
+
#
|
|
28
28
|
# Encodings.defined?(:base64) #=> true
|
|
29
29
|
def Encodings.defined?( str )
|
|
30
30
|
@transfer_encodings.include? get_name(str)
|
|
31
31
|
end
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
# Gets a defined encoding type, QuotedPrintable or Base64 for now.
|
|
34
|
-
#
|
|
35
|
-
# Each encoding needs to be defined as a Mail::Encodings::ClassName for
|
|
34
|
+
#
|
|
35
|
+
# Each encoding needs to be defined as a Mail::Encodings::ClassName for
|
|
36
36
|
# this to work, allows us to add other encodings in the future.
|
|
37
|
-
#
|
|
37
|
+
#
|
|
38
38
|
# Example:
|
|
39
|
-
#
|
|
39
|
+
#
|
|
40
40
|
# Encodings.get_encoding(:base64) #=> Mail::Encodings::Base64
|
|
41
41
|
def Encodings.get_encoding( str )
|
|
42
42
|
@transfer_encodings[get_name(str)]
|
|
@@ -52,16 +52,16 @@ module Mail
|
|
|
52
52
|
|
|
53
53
|
# Encodes a parameter value using URI Escaping, note the language field 'en' can
|
|
54
54
|
# be set using Mail::Configuration, like so:
|
|
55
|
-
#
|
|
55
|
+
#
|
|
56
56
|
# Mail.defaults.do
|
|
57
57
|
# param_encode_language 'jp'
|
|
58
58
|
# end
|
|
59
59
|
#
|
|
60
|
-
# The character set used for encoding will either be the value of $KCODE for
|
|
60
|
+
# The character set used for encoding will either be the value of $KCODE for
|
|
61
61
|
# Ruby < 1.9 or the encoding on the string passed in.
|
|
62
|
-
#
|
|
62
|
+
#
|
|
63
63
|
# Example:
|
|
64
|
-
#
|
|
64
|
+
#
|
|
65
65
|
# Mail::Encodings.param_encode("This is fun") #=> "us-ascii'en'This%20is%20fun"
|
|
66
66
|
def Encodings.param_encode(str)
|
|
67
67
|
case
|
|
@@ -75,9 +75,9 @@ module Mail
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
# Decodes a parameter value using URI Escaping.
|
|
78
|
-
#
|
|
78
|
+
#
|
|
79
79
|
# Example:
|
|
80
|
-
#
|
|
80
|
+
#
|
|
81
81
|
# Mail::Encodings.param_decode("This%20is%20fun", 'us-ascii') #=> "This is fun"
|
|
82
82
|
#
|
|
83
83
|
# str = Mail::Encodings.param_decode("This%20is%20fun", 'iso-8559-1')
|
|
@@ -86,14 +86,14 @@ module Mail
|
|
|
86
86
|
def Encodings.param_decode(str, encoding)
|
|
87
87
|
RubyVer.param_decode(str, encoding)
|
|
88
88
|
end
|
|
89
|
-
|
|
89
|
+
|
|
90
90
|
# Decodes or encodes a string as needed for either Base64 or QP encoding types in
|
|
91
91
|
# the =?<encoding>?[QB]?<string>?=" format.
|
|
92
|
-
#
|
|
92
|
+
#
|
|
93
93
|
# The output type needs to be :decode to decode the input string or :encode to
|
|
94
94
|
# encode the input string. The character set used for encoding will either be
|
|
95
95
|
# the value of $KCODE for Ruby < 1.9 or the encoding on the string passed in.
|
|
96
|
-
#
|
|
96
|
+
#
|
|
97
97
|
# On encoding, will only send out Base64 encoded strings.
|
|
98
98
|
def Encodings.decode_encode(str, output_type)
|
|
99
99
|
case
|
|
@@ -110,12 +110,12 @@ module Mail
|
|
|
110
110
|
|
|
111
111
|
# Decodes a given string as Base64 or Quoted Printable, depending on what
|
|
112
112
|
# type it is.
|
|
113
|
-
#
|
|
113
|
+
#
|
|
114
114
|
# String has to be of the format =?<encoding>?[QB]?<string>?=
|
|
115
115
|
def Encodings.value_decode(str)
|
|
116
116
|
# Optimization: If there's no encoded-words in the string, just return it
|
|
117
117
|
return str unless str.index("=?")
|
|
118
|
-
|
|
118
|
+
|
|
119
119
|
str = str.gsub(/\?=(\s*)=\?/, '?==?') # Remove whitespaces between 'encoded-word's
|
|
120
120
|
|
|
121
121
|
# Split on white-space boundaries with capture, so we capture the white-space as well
|
|
@@ -125,18 +125,18 @@ module Mail
|
|
|
125
125
|
else
|
|
126
126
|
# Join QP encoded-words that are adjacent to avoid decoding partial chars
|
|
127
127
|
text.gsub!(/\?\=\=\?.+?\?[Qq]\?/m, '') if text =~ /\?==\?/
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
# Separate encoded-words with a space, so we can treat them one by one
|
|
130
130
|
text.gsub!(/\?\=\=\?/, '?= =?')
|
|
131
131
|
text.split(/ /).map do |word|
|
|
132
132
|
word.to_str.
|
|
133
|
-
gsub(/=\?.+\?[Bb]\?.+\?=/m) {|substr| b_value_decode(substr)}.
|
|
134
|
-
gsub(/=\?.+\?[Qq]\?.+\?=/m) {|substr| q_value_decode(substr)}
|
|
133
|
+
gsub( /=\?.+\?[Bb]\?.+\?=/m ) { |substr| b_value_decode(substr) }.
|
|
134
|
+
gsub( /=\?.+\?[Qq]\?.+\?=/m ) { |substr| q_value_decode(substr) }
|
|
135
135
|
end
|
|
136
136
|
end
|
|
137
137
|
end.join("")
|
|
138
138
|
end
|
|
139
|
-
|
|
139
|
+
|
|
140
140
|
# Takes an encoded string of the format =?<encoding>?[QB]?<string>?=
|
|
141
141
|
def Encodings.unquote_and_convert_to(str, to_encoding)
|
|
142
142
|
original_encoding, string = split_encoding_from_string( str )
|
|
@@ -166,7 +166,7 @@ module Mail
|
|
|
166
166
|
output
|
|
167
167
|
end
|
|
168
168
|
end
|
|
169
|
-
|
|
169
|
+
|
|
170
170
|
def Encodings.address_encode(address, charset = 'utf-8')
|
|
171
171
|
if address.is_a?(Array)
|
|
172
172
|
# loop back through for each element
|
|
@@ -196,13 +196,13 @@ module Mail
|
|
|
196
196
|
end
|
|
197
197
|
end.join(' ')
|
|
198
198
|
end
|
|
199
|
-
|
|
199
|
+
|
|
200
200
|
# Encode a string with Base64 Encoding and returns it ready to be inserted
|
|
201
201
|
# as a value for a field, that is, in the =?<charset>?B?<string>?= format
|
|
202
202
|
#
|
|
203
203
|
# Example:
|
|
204
|
-
#
|
|
205
|
-
# Encodings.b_value_encode('This is あ string', 'UTF-8')
|
|
204
|
+
#
|
|
205
|
+
# Encodings.b_value_encode('This is あ string', 'UTF-8')
|
|
206
206
|
# #=> "=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?="
|
|
207
207
|
def Encodings.b_value_encode(str, encoding = nil)
|
|
208
208
|
return str if str.to_s.ascii_only?
|
|
@@ -211,13 +211,13 @@ module Mail
|
|
|
211
211
|
"=?#{encoding}?B?#{str.chomp}?="
|
|
212
212
|
end.join(" ")
|
|
213
213
|
end
|
|
214
|
-
|
|
214
|
+
|
|
215
215
|
# Encode a string with Quoted-Printable Encoding and returns it ready to be inserted
|
|
216
216
|
# as a value for a field, that is, in the =?<charset>?Q?<string>?= format
|
|
217
217
|
#
|
|
218
218
|
# Example:
|
|
219
|
-
#
|
|
220
|
-
# Encodings.q_value_encode('This is あ string', 'UTF-8')
|
|
219
|
+
#
|
|
220
|
+
# Encodings.q_value_encode('This is あ string', 'UTF-8')
|
|
221
221
|
# #=> "=?UTF-8?Q?This_is_=E3=81=82_string?="
|
|
222
222
|
def Encodings.q_value_encode(str, encoding = nil)
|
|
223
223
|
return str if str.to_s.ascii_only?
|
|
@@ -227,29 +227,29 @@ module Mail
|
|
|
227
227
|
"=?#{encoding}?Q?#{str.chomp.gsub(/ /, '_')}?="
|
|
228
228
|
end.join(" ")
|
|
229
229
|
end
|
|
230
|
-
|
|
230
|
+
|
|
231
231
|
private
|
|
232
|
-
|
|
232
|
+
|
|
233
233
|
# Decodes a Base64 string from the "=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=" format
|
|
234
|
-
#
|
|
234
|
+
#
|
|
235
235
|
# Example:
|
|
236
|
-
#
|
|
237
|
-
# Encodings.
|
|
236
|
+
#
|
|
237
|
+
# Encodings.b_value_decode("=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=")
|
|
238
238
|
# #=> 'This is あ string'
|
|
239
239
|
def Encodings.b_value_decode(str)
|
|
240
240
|
RubyVer.b_value_decode(str)
|
|
241
241
|
end
|
|
242
|
-
|
|
242
|
+
|
|
243
243
|
# Decodes a Quoted-Printable string from the "=?UTF-8?Q?This_is_=E3=81=82_string?=" format
|
|
244
|
-
#
|
|
244
|
+
#
|
|
245
245
|
# Example:
|
|
246
|
-
#
|
|
247
|
-
# Encodings.
|
|
246
|
+
#
|
|
247
|
+
# Encodings.q_value_decode("=?UTF-8?Q?This_is_=E3=81=82_string?=")
|
|
248
248
|
# #=> 'This is あ string'
|
|
249
249
|
def Encodings.q_value_decode(str)
|
|
250
250
|
RubyVer.q_value_decode(str).gsub(/_/, ' ')
|
|
251
251
|
end
|
|
252
|
-
|
|
252
|
+
|
|
253
253
|
def Encodings.split_encoding_from_string( str )
|
|
254
254
|
match = str.match(/\=\?([^?]+)?\?[QB]\?(.+)?\?\=/mi)
|
|
255
255
|
if match
|
|
@@ -258,7 +258,7 @@ module Mail
|
|
|
258
258
|
nil
|
|
259
259
|
end
|
|
260
260
|
end
|
|
261
|
-
|
|
261
|
+
|
|
262
262
|
def Encodings.find_encoding(str)
|
|
263
263
|
RUBY_VERSION >= '1.9' ? str.encoding : $KCODE
|
|
264
264
|
end
|
data/lib/mail/field.rb
CHANGED
|
@@ -69,7 +69,8 @@ module Mail
|
|
|
69
69
|
# Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
|
|
70
70
|
def initialize(name, value = nil, charset = 'utf-8')
|
|
71
71
|
case
|
|
72
|
-
when name =~ /:/
|
|
72
|
+
when name =~ /:/ # Field.new("field-name: field data")
|
|
73
|
+
charset = value unless value.blank?
|
|
73
74
|
name, value = split(name)
|
|
74
75
|
create_field(name, value, charset)
|
|
75
76
|
when name !~ /:/ && value.blank? # Field.new("field-name")
|
|
@@ -8,7 +8,7 @@ module Mail
|
|
|
8
8
|
# to make that happen
|
|
9
9
|
# Parameters are defined in RFC2045, split keys are in RFC2231
|
|
10
10
|
|
|
11
|
-
class ParameterHash <
|
|
11
|
+
class ParameterHash < IndifferentHash
|
|
12
12
|
|
|
13
13
|
include Mail::Utilities
|
|
14
14
|
|
|
@@ -28,8 +28,8 @@ module Mail
|
|
|
28
28
|
if pairs.empty? # Just dealing with a single value pair
|
|
29
29
|
super(exact || key_name)
|
|
30
30
|
else # Dealing with a multiple value pair or a single encoded value pair
|
|
31
|
-
string = pairs.sort { |a,b| a.first <=> b.first }.map { |v| v.last }.join('')
|
|
32
|
-
if mt = string.match(/([\w\-]+)'(\w\w)'(.*)/)
|
|
31
|
+
string = pairs.sort { |a,b| a.first.to_s <=> b.first.to_s }.map { |v| v.last }.join('')
|
|
32
|
+
if mt = string.match(/([\w\d\-]+)'(\w\w)'(.*)/)
|
|
33
33
|
string = mt[3]
|
|
34
34
|
encoding = mt[1]
|
|
35
35
|
else
|
|
@@ -40,7 +40,7 @@ module Mail
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def encoded
|
|
43
|
-
map.sort { |a,b| a.first <=> b.first }.map do |key_name, value|
|
|
43
|
+
map.sort { |a,b| a.first.to_s <=> b.first.to_s }.map do |key_name, value|
|
|
44
44
|
unless value.ascii_only?
|
|
45
45
|
value = Mail::Encodings.param_encode(value)
|
|
46
46
|
key_name = "#{key_name}*"
|
|
@@ -50,7 +50,7 @@ module Mail
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def decoded
|
|
53
|
-
map.sort { |a,b| a.first <=> b.first }.map do |key_name, value|
|
|
53
|
+
map.sort { |a,b| a.first.to_s <=> b.first.to_s }.map do |key_name, value|
|
|
54
54
|
%Q{#{key_name}=#{quote_token(value)}}
|
|
55
55
|
end.join("; ")
|
|
56
56
|
end
|