mail 2.6.3 → 2.6.4.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.rdoc +22 -0
- data/Gemfile +1 -4
- data/MIT-LICENSE +1 -1
- data/README.md +38 -2
- data/Rakefile +2 -2
- data/lib/mail.rb +8 -2
- data/lib/mail/body.rb +4 -4
- data/lib/mail/check_delivery_params.rb +3 -3
- data/lib/mail/constants.rb +2 -1
- data/lib/mail/core_extensions/nil.rb +0 -6
- data/lib/mail/core_extensions/string.rb +0 -6
- data/lib/mail/elements/address.rb +7 -7
- data/lib/mail/encodings.rb +25 -28
- data/lib/mail/encodings/8bit.rb +5 -0
- data/lib/mail/encodings/base64.rb +5 -0
- data/lib/mail/encodings/quoted_printable.rb +6 -1
- data/lib/mail/encodings/transfer_encoding.rb +26 -17
- data/lib/mail/field.rb +18 -4
- data/lib/mail/fields/bcc_field.rb +14 -3
- data/lib/mail/fields/cc_field.rb +0 -1
- data/lib/mail/fields/common/common_address.rb +7 -7
- data/lib/mail/fields/common/common_date.rb +1 -1
- data/lib/mail/fields/common/common_field.rb +1 -1
- data/lib/mail/fields/common/common_message_id.rb +2 -2
- data/lib/mail/fields/content_disposition_field.rb +11 -11
- data/lib/mail/fields/content_id_field.rb +2 -2
- data/lib/mail/fields/content_location_field.rb +1 -1
- data/lib/mail/fields/content_transfer_encoding_field.rb +1 -1
- data/lib/mail/fields/content_type_field.rb +1 -1
- data/lib/mail/fields/date_field.rb +1 -1
- data/lib/mail/fields/from_field.rb +0 -1
- data/lib/mail/fields/keywords_field.rb +1 -2
- data/lib/mail/fields/message_id_field.rb +1 -1
- data/lib/mail/fields/mime_version_field.rb +2 -2
- data/lib/mail/fields/received_field.rb +3 -3
- data/lib/mail/fields/reply_to_field.rb +0 -1
- data/lib/mail/fields/resent_bcc_field.rb +0 -1
- data/lib/mail/fields/resent_cc_field.rb +0 -1
- data/lib/mail/fields/resent_date_field.rb +1 -1
- data/lib/mail/fields/resent_from_field.rb +0 -1
- data/lib/mail/fields/resent_sender_field.rb +0 -1
- data/lib/mail/fields/resent_to_field.rb +0 -1
- data/lib/mail/fields/return_path_field.rb +0 -1
- data/lib/mail/fields/sender_field.rb +0 -1
- data/lib/mail/fields/to_field.rb +0 -1
- data/lib/mail/fields/unstructured_field.rb +1 -1
- data/lib/mail/header.rb +3 -3
- data/lib/mail/matchers/attachment_matchers.rb +28 -0
- data/lib/mail/matchers/has_sent_mail.rb +30 -7
- data/lib/mail/message.rb +15 -21
- data/lib/mail/multibyte/unicode.rb +20 -16
- data/lib/mail/parsers/address_lists_parser.rb +1 -1
- data/lib/mail/parsers/content_disposition_parser.rb +1 -1
- data/lib/mail/parsers/content_location_parser.rb +1 -1
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +1 -1
- data/lib/mail/parsers/envelope_from_parser.rb +1 -1
- data/lib/mail/parsers/message_ids_parser.rb +1 -1
- data/lib/mail/parsers/mime_version_parser.rb +1 -1
- data/lib/mail/part.rb +4 -2
- data/lib/mail/parts_list.rb +25 -8
- data/lib/mail/utilities.rb +15 -0
- data/lib/mail/values/unicode_tables.dat +0 -0
- data/lib/mail/version.rb +2 -2
- data/lib/mail/version_specific/ruby_1_8.rb +10 -4
- data/lib/mail/version_specific/ruby_1_9.rb +39 -10
- metadata +8 -8
- data/lib/mail/core_extensions/object.rb +0 -13
@@ -23,30 +23,39 @@ module Mail
|
|
23
23
|
raise "Unimplemented"
|
24
24
|
end
|
25
25
|
|
26
|
+
def self.compatible_input?(str)
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
26
30
|
def self.to_s
|
27
31
|
self::NAME
|
28
32
|
end
|
29
33
|
|
30
34
|
def self.get_best_compatible(source_encoding, str)
|
31
|
-
if self.can_transport?
|
32
|
-
|
35
|
+
if self.can_transport?(source_encoding) && self.compatible_input?(str)
|
36
|
+
source_encoding
|
33
37
|
else
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
38
|
+
choices = Encodings.get_all.select do |enc|
|
39
|
+
self.can_transport?(enc) && enc.can_encode?(source_encoding)
|
40
|
+
end
|
41
|
+
|
42
|
+
best = nil
|
43
|
+
best_cost = nil
|
44
|
+
|
45
|
+
choices.each do |enc|
|
46
|
+
# If the current choice cannot be transported safely,
|
47
|
+
# give priority to other choices but allow it to be used as a fallback.
|
48
|
+
this_cost = enc.cost(str) if enc.compatible_input?(str)
|
49
|
+
|
50
|
+
if !best_cost || (this_cost && this_cost < best_cost)
|
51
|
+
best_cost = this_cost
|
52
|
+
best = enc
|
53
|
+
elsif this_cost == best_cost
|
54
|
+
best = enc if enc::PRIORITY < best::PRIORITY
|
48
55
|
end
|
49
|
-
|
56
|
+
end
|
57
|
+
|
58
|
+
best
|
50
59
|
end
|
51
60
|
end
|
52
61
|
|
data/lib/mail/field.rb
CHANGED
@@ -114,11 +114,11 @@ module Mail
|
|
114
114
|
def initialize(name, value = nil, charset = 'utf-8')
|
115
115
|
case
|
116
116
|
when name.index(COLON) # Field.new("field-name: field data")
|
117
|
-
@charset =
|
117
|
+
@charset = Utilities.blank?(value) ? charset : value
|
118
118
|
@name = name[FIELD_PREFIX]
|
119
119
|
@raw_value = name
|
120
120
|
@value = nil
|
121
|
-
when
|
121
|
+
when Utilities.blank?(value) # Field.new("field-name")
|
122
122
|
@name = name
|
123
123
|
@value = nil
|
124
124
|
@raw_value = nil
|
@@ -168,15 +168,19 @@ module Mail
|
|
168
168
|
end
|
169
169
|
|
170
170
|
def same( other )
|
171
|
+
return false unless other.kind_of?(self.class)
|
171
172
|
match_to_s(other.name, self.name)
|
172
173
|
end
|
173
174
|
|
175
|
+
def ==( other )
|
176
|
+
return false unless other.kind_of?(self.class)
|
177
|
+
match_to_s(other.name, self.name) && match_to_s(other.value, self.value)
|
178
|
+
end
|
179
|
+
|
174
180
|
def responsible_for?( val )
|
175
181
|
name.to_s.casecmp(val.to_s) == 0
|
176
182
|
end
|
177
183
|
|
178
|
-
alias_method :==, :same
|
179
|
-
|
180
184
|
def <=>( other )
|
181
185
|
self.field_order_id <=> other.field_order_id
|
182
186
|
end
|
@@ -189,6 +193,16 @@ module Mail
|
|
189
193
|
field.send(name, *args, &block)
|
190
194
|
end
|
191
195
|
|
196
|
+
if RUBY_VERSION >= '1.9.2'
|
197
|
+
def respond_to_missing?(method_name, include_private)
|
198
|
+
field.respond_to?(method_name, include_private) || super
|
199
|
+
end
|
200
|
+
else
|
201
|
+
def respond_to?(method_name, include_private = false)
|
202
|
+
field.respond_to?(method_name, include_private) || super
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
192
206
|
FIELD_ORDER = %w[ return-path received
|
193
207
|
resent-date resent-from resent-sender resent-to
|
194
208
|
resent-cc resent-bcc resent-message-id
|
@@ -39,13 +39,24 @@ module Mail
|
|
39
39
|
def initialize(value = '', charset = 'utf-8')
|
40
40
|
@charset = charset
|
41
41
|
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
42
|
-
self.parse
|
43
42
|
self
|
44
43
|
end
|
45
44
|
|
46
|
-
|
45
|
+
def include_in_headers=(include_in_headers)
|
46
|
+
@include_in_headers = include_in_headers
|
47
|
+
end
|
48
|
+
|
49
|
+
def include_in_headers
|
50
|
+
defined?(@include_in_headers) ? @include_in_headers : self.include_in_headers = false
|
51
|
+
end
|
52
|
+
|
53
|
+
# Bcc field should not be :encoded by default
|
47
54
|
def encoded
|
48
|
-
|
55
|
+
if include_in_headers
|
56
|
+
do_encode(CAPITALIZED_FIELD)
|
57
|
+
else
|
58
|
+
''
|
59
|
+
end
|
49
60
|
end
|
50
61
|
|
51
62
|
def decoded
|
data/lib/mail/fields/cc_field.rb
CHANGED
@@ -5,7 +5,7 @@ module Mail
|
|
5
5
|
module CommonAddress # :nodoc:
|
6
6
|
|
7
7
|
def parse(val = value)
|
8
|
-
unless
|
8
|
+
unless Utilities.blank?(val)
|
9
9
|
@address_list = AddressList.new(encode_if_needed(val))
|
10
10
|
else
|
11
11
|
nil
|
@@ -84,10 +84,10 @@ module Mail
|
|
84
84
|
case
|
85
85
|
when val.nil?
|
86
86
|
raise ArgumentError, "Need to pass an address to <<"
|
87
|
-
when
|
87
|
+
when Utilities.blank?(val)
|
88
88
|
parse(encoded)
|
89
89
|
else
|
90
|
-
self.value = [self.value, val].reject {|a|
|
90
|
+
self.value = [self.value, val].reject {|a| Utilities.blank?(a) }.join(", ")
|
91
91
|
end
|
92
92
|
end
|
93
93
|
|
@@ -99,22 +99,22 @@ module Mail
|
|
99
99
|
private
|
100
100
|
|
101
101
|
def do_encode(field_name)
|
102
|
-
return '' if
|
102
|
+
return '' if Utilities.blank?(value)
|
103
103
|
address_array = address_list.addresses.reject { |a| encoded_group_addresses.include?(a.encoded) }.compact.map { |a| a.encoded }
|
104
104
|
address_text = address_array.join(", \r\n\s")
|
105
105
|
group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.encoded }.join(", \r\n\s")};" }
|
106
106
|
group_text = group_array.join(" \r\n\s")
|
107
|
-
return_array = [address_text, group_text].reject { |a|
|
107
|
+
return_array = [address_text, group_text].reject { |a| Utilities.blank?(a) }
|
108
108
|
"#{field_name}: #{return_array.join(", \r\n\s")}\r\n"
|
109
109
|
end
|
110
110
|
|
111
111
|
def do_decode
|
112
|
-
return nil if
|
112
|
+
return nil if Utilities.blank?(value)
|
113
113
|
address_array = address_list.addresses.reject { |a| decoded_group_addresses.include?(a.decoded) }.map { |a| a.decoded }
|
114
114
|
address_text = address_array.join(", ")
|
115
115
|
group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.decoded }.join(", ")};" }
|
116
116
|
group_text = group_array.join(" ")
|
117
|
-
return_array = [address_text, group_text].reject { |a|
|
117
|
+
return_array = [address_text, group_text].reject { |a| Utilities.blank?(a) }
|
118
118
|
return_array.join(", ")
|
119
119
|
end
|
120
120
|
|
@@ -2,11 +2,11 @@
|
|
2
2
|
module Mail
|
3
3
|
module CommonMessageId # :nodoc:
|
4
4
|
def element
|
5
|
-
@element ||= Mail::MessageIdsElement.new(value) unless
|
5
|
+
@element ||= Mail::MessageIdsElement.new(value) unless Utilities.blank?(value)
|
6
6
|
end
|
7
7
|
|
8
8
|
def parse(val = value)
|
9
|
-
unless
|
9
|
+
unless Utilities.blank?(val)
|
10
10
|
@element = Mail::MessageIdsElement.new(val)
|
11
11
|
else
|
12
12
|
nil
|
@@ -3,10 +3,10 @@ require 'mail/fields/common/parameter_hash'
|
|
3
3
|
|
4
4
|
module Mail
|
5
5
|
class ContentDispositionField < StructuredField
|
6
|
-
|
6
|
+
|
7
7
|
FIELD_NAME = 'content-disposition'
|
8
8
|
CAPITALIZED_FIELD = 'Content-Disposition'
|
9
|
-
|
9
|
+
|
10
10
|
def initialize(value = nil, charset = 'utf-8')
|
11
11
|
self.charset = charset
|
12
12
|
ensure_filename_quoted(value)
|
@@ -14,13 +14,13 @@ module Mail
|
|
14
14
|
self.parse
|
15
15
|
self
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def parse(val = value)
|
19
|
-
unless
|
19
|
+
unless Utilities.blank?(val)
|
20
20
|
@element = Mail::ContentDispositionElement.new(val)
|
21
21
|
end
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def element
|
25
25
|
@element ||= Mail::ContentDispositionElement.new(value)
|
26
26
|
end
|
@@ -28,20 +28,20 @@ module Mail
|
|
28
28
|
def disposition_type
|
29
29
|
element.disposition_type
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def parameters
|
33
33
|
@parameters = ParameterHash.new
|
34
|
-
element.parameters.each { |p| @parameters.merge!(p) }
|
34
|
+
element.parameters.each { |p| @parameters.merge!(p) } unless element.parameters.nil?
|
35
35
|
@parameters
|
36
36
|
end
|
37
37
|
|
38
38
|
def filename
|
39
39
|
case
|
40
|
-
when !parameters['filename']
|
40
|
+
when !Utilities.blank?(parameters['filename'])
|
41
41
|
@filename = parameters['filename']
|
42
|
-
when !parameters['name']
|
42
|
+
when !Utilities.blank?(parameters['name'])
|
43
43
|
@filename = parameters['name']
|
44
|
-
else
|
44
|
+
else
|
45
45
|
@filename = nil
|
46
46
|
end
|
47
47
|
@filename
|
@@ -56,7 +56,7 @@ module Mail
|
|
56
56
|
end
|
57
57
|
"#{CAPITALIZED_FIELD}: #{disposition_type}" + p
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
def decoded
|
61
61
|
if parameters.length > 0
|
62
62
|
p = "; #{parameters.decoded}"
|
@@ -11,7 +11,7 @@ module Mail
|
|
11
11
|
def initialize(value = nil, charset = 'utf-8')
|
12
12
|
self.charset = charset
|
13
13
|
@uniq = 1
|
14
|
-
if
|
14
|
+
if Utilities.blank?(value)
|
15
15
|
value = generate_content_id
|
16
16
|
else
|
17
17
|
value = strip_field(FIELD_NAME, value)
|
@@ -22,7 +22,7 @@ module Mail
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def parse(val = value)
|
25
|
-
unless
|
25
|
+
unless Utilities.blank?(val)
|
26
26
|
@element = Mail::MessageIdsElement.new(val)
|
27
27
|
end
|
28
28
|
end
|
@@ -10,12 +10,11 @@ module Mail
|
|
10
10
|
def initialize(value = nil, charset = 'utf-8')
|
11
11
|
self.charset = charset
|
12
12
|
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
13
|
-
self.parse
|
14
13
|
self
|
15
14
|
end
|
16
15
|
|
17
16
|
def parse(val = value)
|
18
|
-
unless
|
17
|
+
unless Utilities.blank?(val)
|
19
18
|
@phrase_list ||= PhraseList.new(value)
|
20
19
|
end
|
21
20
|
end
|
@@ -10,7 +10,7 @@ module Mail
|
|
10
10
|
|
11
11
|
def initialize(value = nil, charset = 'utf-8')
|
12
12
|
self.charset = charset
|
13
|
-
if
|
13
|
+
if Utilities.blank?(value)
|
14
14
|
value = '1.0'
|
15
15
|
end
|
16
16
|
super(CAPITALIZED_FIELD, strip_field(FIELD_NAME, value), charset)
|
@@ -20,7 +20,7 @@ module Mail
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def parse(val = value)
|
23
|
-
unless
|
23
|
+
unless Utilities.blank?(val)
|
24
24
|
@element = Mail::MimeVersionElement.new(val)
|
25
25
|
end
|
26
26
|
end
|
@@ -34,7 +34,7 @@ module Mail
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def parse(val = value)
|
37
|
-
unless
|
37
|
+
unless Utilities.blank?(val)
|
38
38
|
@element = Mail::ReceivedElement.new(val)
|
39
39
|
end
|
40
40
|
end
|
@@ -56,7 +56,7 @@ module Mail
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def encoded
|
59
|
-
if
|
59
|
+
if Utilities.blank?(value)
|
60
60
|
"#{CAPITALIZED_FIELD}: \r\n"
|
61
61
|
else
|
62
62
|
"#{CAPITALIZED_FIELD}: #{info}; #{formatted_date}\r\n"
|
@@ -64,7 +64,7 @@ module Mail
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def decoded
|
67
|
-
if
|
67
|
+
if Utilities.blank?(value)
|
68
68
|
""
|
69
69
|
else
|
70
70
|
"#{info}; #{formatted_date}"
|