mail 2.6.1 → 2.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/MIT-LICENSE +1 -1
- data/README.md +92 -80
- data/lib/mail/attachments_list.rb +11 -5
- data/lib/mail/body.rb +81 -44
- data/lib/mail/check_delivery_params.rb +50 -10
- data/lib/mail/configuration.rb +3 -0
- data/lib/mail/{patterns.rb → constants.rb} +26 -6
- data/lib/mail/core_extensions/smtp.rb +20 -16
- data/lib/mail/core_extensions/string.rb +1 -27
- data/lib/mail/elements/address.rb +81 -93
- data/lib/mail/elements/address_list.rb +12 -29
- data/lib/mail/elements/content_disposition_element.rb +9 -15
- data/lib/mail/elements/content_location_element.rb +8 -12
- data/lib/mail/elements/content_transfer_encoding_element.rb +6 -10
- data/lib/mail/elements/content_type_element.rb +9 -19
- data/lib/mail/elements/date_time_element.rb +7 -14
- data/lib/mail/elements/envelope_from_element.rb +15 -21
- data/lib/mail/elements/message_ids_element.rb +12 -14
- data/lib/mail/elements/mime_version_element.rb +7 -14
- data/lib/mail/elements/phrase_list.rb +7 -9
- data/lib/mail/elements/received_element.rb +10 -15
- data/lib/mail/elements.rb +1 -0
- data/lib/mail/encodings/7bit.rb +6 -15
- data/lib/mail/encodings/8bit.rb +5 -18
- data/lib/mail/encodings/base64.rb +15 -10
- data/lib/mail/encodings/binary.rb +4 -22
- data/lib/mail/encodings/identity.rb +24 -0
- data/lib/mail/encodings/quoted_printable.rb +13 -7
- data/lib/mail/encodings/transfer_encoding.rb +47 -28
- data/lib/mail/encodings/unix_to_unix.rb +20 -0
- data/lib/mail/encodings.rb +121 -82
- data/lib/mail/envelope.rb +2 -1
- data/lib/mail/field.rb +114 -62
- data/lib/mail/field_list.rb +2 -1
- data/lib/mail/fields/bcc_field.rb +17 -5
- data/lib/mail/fields/cc_field.rb +2 -2
- data/lib/mail/fields/comments_field.rb +2 -1
- data/lib/mail/fields/common/address_container.rb +3 -2
- data/lib/mail/fields/common/common_address.rb +40 -14
- data/lib/mail/fields/common/common_date.rb +2 -1
- data/lib/mail/fields/common/common_field.rb +6 -11
- data/lib/mail/fields/common/common_message_id.rb +3 -2
- data/lib/mail/fields/common/parameter_hash.rb +5 -4
- data/lib/mail/fields/content_description_field.rb +2 -1
- data/lib/mail/fields/content_disposition_field.rb +14 -13
- data/lib/mail/fields/content_id_field.rb +5 -4
- data/lib/mail/fields/content_location_field.rb +3 -2
- data/lib/mail/fields/content_transfer_encoding_field.rb +3 -2
- data/lib/mail/fields/content_type_field.rb +7 -11
- data/lib/mail/fields/date_field.rb +4 -4
- data/lib/mail/fields/from_field.rb +2 -2
- data/lib/mail/fields/in_reply_to_field.rb +2 -1
- data/lib/mail/fields/keywords_field.rb +3 -3
- data/lib/mail/fields/message_id_field.rb +3 -2
- data/lib/mail/fields/mime_version_field.rb +4 -3
- data/lib/mail/fields/optional_field.rb +5 -1
- data/lib/mail/fields/received_field.rb +5 -4
- data/lib/mail/fields/references_field.rb +2 -1
- data/lib/mail/fields/reply_to_field.rb +2 -2
- data/lib/mail/fields/resent_bcc_field.rb +2 -2
- data/lib/mail/fields/resent_cc_field.rb +2 -2
- data/lib/mail/fields/resent_date_field.rb +2 -2
- data/lib/mail/fields/resent_from_field.rb +2 -2
- data/lib/mail/fields/resent_message_id_field.rb +2 -1
- data/lib/mail/fields/resent_sender_field.rb +2 -2
- data/lib/mail/fields/resent_to_field.rb +2 -2
- data/lib/mail/fields/return_path_field.rb +2 -2
- data/lib/mail/fields/sender_field.rb +2 -2
- data/lib/mail/fields/structured_field.rb +1 -0
- data/lib/mail/fields/subject_field.rb +2 -1
- data/lib/mail/fields/to_field.rb +2 -2
- data/lib/mail/fields/unstructured_field.rb +28 -10
- data/lib/mail/fields.rb +1 -0
- data/lib/mail/header.rb +18 -14
- data/lib/mail/indifferent_hash.rb +1 -0
- data/lib/mail/mail.rb +6 -11
- data/lib/mail/matchers/attachment_matchers.rb +29 -0
- data/lib/mail/matchers/has_sent_mail.rb +53 -9
- data/lib/mail/message.rb +99 -89
- data/lib/mail/multibyte/chars.rb +32 -30
- data/lib/mail/multibyte/unicode.rb +31 -26
- data/lib/mail/multibyte/utils.rb +1 -0
- data/lib/mail/multibyte.rb +65 -15
- data/lib/mail/network/delivery_methods/exim.rb +7 -10
- data/lib/mail/network/delivery_methods/file_delivery.rb +5 -8
- data/lib/mail/network/delivery_methods/logger_delivery.rb +37 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +17 -11
- data/lib/mail/network/delivery_methods/smtp.rb +60 -53
- data/lib/mail/network/delivery_methods/smtp_connection.rb +11 -6
- data/lib/mail/network/delivery_methods/test_mailer.rb +6 -8
- data/lib/mail/network/retriever_methods/base.rb +1 -0
- data/lib/mail/network/retriever_methods/imap.rb +19 -5
- data/lib/mail/network/retriever_methods/pop3.rb +4 -1
- data/lib/mail/network/retriever_methods/test_retriever.rb +2 -1
- data/lib/mail/network.rb +2 -0
- data/lib/mail/parser_tools.rb +15 -0
- data/lib/mail/parsers/address_lists_parser.rb +33208 -104
- data/lib/mail/parsers/address_lists_parser.rl +172 -0
- data/lib/mail/parsers/content_disposition_parser.rb +877 -49
- data/lib/mail/parsers/content_disposition_parser.rl +82 -0
- data/lib/mail/parsers/content_location_parser.rb +804 -23
- data/lib/mail/parsers/content_location_parser.rl +71 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +502 -19
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +64 -0
- data/lib/mail/parsers/content_type_parser.rb +1024 -46
- data/lib/mail/parsers/content_type_parser.rl +83 -0
- data/lib/mail/parsers/date_time_parser.rb +872 -23
- data/lib/mail/parsers/date_time_parser.rl +62 -0
- data/lib/mail/parsers/envelope_from_parser.rb +3570 -34
- data/lib/mail/parsers/envelope_from_parser.rl +82 -0
- data/lib/mail/parsers/message_ids_parser.rb +2840 -25
- data/lib/mail/parsers/message_ids_parser.rl +82 -0
- data/lib/mail/parsers/mime_version_parser.rb +492 -26
- data/lib/mail/parsers/mime_version_parser.rl +61 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +862 -17
- data/lib/mail/parsers/phrase_lists_parser.rl +83 -0
- data/lib/mail/parsers/received_parser.rb +8765 -36
- data/lib/mail/parsers/received_parser.rl +84 -0
- data/lib/mail/parsers/rfc2045_content_transfer_encoding.rl +13 -0
- data/lib/mail/parsers/rfc2045_content_type.rl +25 -0
- data/lib/mail/parsers/rfc2045_mime.rl +16 -0
- data/lib/mail/parsers/rfc2183_content_disposition.rl +15 -0
- data/lib/mail/parsers/rfc3629_utf8.rl +19 -0
- data/lib/mail/parsers/rfc5234_abnf_core_rules.rl +22 -0
- data/lib/mail/parsers/rfc5322.rl +59 -0
- data/lib/mail/parsers/rfc5322_address.rl +72 -0
- data/lib/mail/parsers/{ragel/date_time.rl → rfc5322_date_time.rl} +8 -1
- data/lib/mail/parsers/rfc5322_lexical_tokens.rl +60 -0
- data/lib/mail/parsers.rb +17 -24
- data/lib/mail/part.rb +8 -5
- data/lib/mail/parts_list.rb +31 -14
- data/lib/mail/utilities.rb +112 -13
- data/lib/mail/values/unicode_tables.dat +0 -0
- data/lib/mail/version.rb +8 -15
- data/lib/mail/version_specific/ruby_1_8.rb +52 -8
- data/lib/mail/version_specific/ruby_1_9.rb +143 -24
- data/lib/mail.rb +8 -14
- metadata +71 -81
- data/CHANGELOG.rdoc +0 -752
- data/CONTRIBUTING.md +0 -60
- data/Dependencies.txt +0 -2
- data/Gemfile +0 -15
- data/Rakefile +0 -29
- data/TODO.rdoc +0 -9
- data/VERSION +0 -4
- data/lib/mail/core_extensions/nil.rb +0 -19
- data/lib/mail/core_extensions/object.rb +0 -13
- data/lib/mail/core_extensions/string/access.rb +0 -145
- data/lib/mail/core_extensions/string/multibyte.rb +0 -78
- data/lib/mail/multibyte/exceptions.rb +0 -8
- data/lib/mail/parsers/ragel/common.rl +0 -184
- data/lib/mail/parsers/ragel/parser_info.rb +0 -61
- data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb +0 -14864
- data/lib/mail/parsers/ragel/ruby/machines/address_lists_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb +0 -751
- data/lib/mail/parsers/ragel/ruby/machines/content_disposition_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb +0 -614
- data/lib/mail/parsers/ragel/ruby/machines/content_location_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb +0 -447
- data/lib/mail/parsers/ragel/ruby/machines/content_transfer_encoding_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb +0 -825
- data/lib/mail/parsers/ragel/ruby/machines/content_type_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb +0 -817
- data/lib/mail/parsers/ragel/ruby/machines/date_time_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb +0 -2129
- data/lib/mail/parsers/ragel/ruby/machines/envelope_from_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb +0 -1570
- data/lib/mail/parsers/ragel/ruby/machines/message_ids_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb +0 -440
- data/lib/mail/parsers/ragel/ruby/machines/mime_version_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb +0 -564
- data/lib/mail/parsers/ragel/ruby/machines/phrase_lists_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/machines/rb_actions.rl +0 -51
- data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb +0 -5144
- data/lib/mail/parsers/ragel/ruby/machines/received_machine.rb.rl +0 -37
- data/lib/mail/parsers/ragel/ruby/parser.rb.rl.erb +0 -37
- data/lib/mail/parsers/ragel/ruby.rb +0 -39
- data/lib/mail/parsers/ragel.rb +0 -17
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# = Resent-Cc Field
|
4
5
|
#
|
@@ -38,8 +39,7 @@ module Mail
|
|
38
39
|
|
39
40
|
def initialize(value = nil, charset = 'utf-8')
|
40
41
|
self.charset = charset
|
41
|
-
super(CAPITALIZED_FIELD,
|
42
|
-
self.parse
|
42
|
+
super(CAPITALIZED_FIELD, value, charset)
|
43
43
|
self
|
44
44
|
end
|
45
45
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# resent-date = "Resent-Date:" date-time CRLF
|
4
5
|
require 'mail/fields/common/common_date'
|
@@ -13,10 +14,9 @@ module Mail
|
|
13
14
|
|
14
15
|
def initialize(value = nil, charset = 'utf-8')
|
15
16
|
self.charset = charset
|
16
|
-
if
|
17
|
+
if Utilities.blank?(value)
|
17
18
|
value = ::DateTime.now.strftime('%a, %d %b %Y %H:%M:%S %z')
|
18
19
|
else
|
19
|
-
value = strip_field(FIELD_NAME, value)
|
20
20
|
value = ::DateTime.parse(value.to_s).strftime('%a, %d %b %Y %H:%M:%S %z')
|
21
21
|
end
|
22
22
|
super(CAPITALIZED_FIELD, value, charset)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# = Resent-From Field
|
4
5
|
#
|
@@ -38,8 +39,7 @@ module Mail
|
|
38
39
|
|
39
40
|
def initialize(value = nil, charset = 'utf-8')
|
40
41
|
self.charset = charset
|
41
|
-
super(CAPITALIZED_FIELD,
|
42
|
-
self.parse
|
42
|
+
super(CAPITALIZED_FIELD, value, charset)
|
43
43
|
self
|
44
44
|
end
|
45
45
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# resent-msg-id = "Resent-Message-ID:" msg-id CRLF
|
4
5
|
require 'mail/fields/common/common_message_id'
|
@@ -13,7 +14,7 @@ module Mail
|
|
13
14
|
|
14
15
|
def initialize(value = nil, charset = 'utf-8')
|
15
16
|
self.charset = charset
|
16
|
-
super(CAPITALIZED_FIELD,
|
17
|
+
super(CAPITALIZED_FIELD, value, charset)
|
17
18
|
self.parse
|
18
19
|
self
|
19
20
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# = Resent-Sender Field
|
4
5
|
#
|
@@ -37,8 +38,7 @@ module Mail
|
|
37
38
|
|
38
39
|
def initialize(value = nil, charset = 'utf-8')
|
39
40
|
self.charset = charset
|
40
|
-
super(CAPITALIZED_FIELD,
|
41
|
-
self.parse
|
41
|
+
super(CAPITALIZED_FIELD, value, charset)
|
42
42
|
self
|
43
43
|
end
|
44
44
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# = Resent-To Field
|
4
5
|
#
|
@@ -38,8 +39,7 @@ module Mail
|
|
38
39
|
|
39
40
|
def initialize(value = nil, charset = 'utf-8')
|
40
41
|
self.charset = charset
|
41
|
-
super(CAPITALIZED_FIELD,
|
42
|
-
self.parse
|
42
|
+
super(CAPITALIZED_FIELD, value, charset)
|
43
43
|
self
|
44
44
|
end
|
45
45
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# 4.4.3. REPLY-TO / RESENT-REPLY-TO
|
4
5
|
#
|
@@ -40,8 +41,7 @@ module Mail
|
|
40
41
|
def initialize(value = nil, charset = 'utf-8')
|
41
42
|
value = nil if value == '<>'
|
42
43
|
self.charset = charset
|
43
|
-
super(CAPITALIZED_FIELD,
|
44
|
-
self.parse
|
44
|
+
super(CAPITALIZED_FIELD, value, charset)
|
45
45
|
self
|
46
46
|
end
|
47
47
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# = Sender Field
|
4
5
|
#
|
@@ -38,8 +39,7 @@ module Mail
|
|
38
39
|
|
39
40
|
def initialize(value = nil, charset = 'utf-8')
|
40
41
|
self.charset = charset
|
41
|
-
super(CAPITALIZED_FIELD,
|
42
|
-
self.parse
|
42
|
+
super(CAPITALIZED_FIELD, value, charset)
|
43
43
|
self
|
44
44
|
end
|
45
45
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# subject = "Subject:" unstructured CRLF
|
4
5
|
module Mail
|
@@ -9,7 +10,7 @@ module Mail
|
|
9
10
|
|
10
11
|
def initialize(value = nil, charset = 'utf-8')
|
11
12
|
self.charset = charset
|
12
|
-
super(CAPITALIZED_FIELD,
|
13
|
+
super(CAPITALIZED_FIELD, value, charset)
|
13
14
|
end
|
14
15
|
|
15
16
|
end
|
data/lib/mail/fields/to_field.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
#
|
3
4
|
# = To Field
|
4
5
|
#
|
@@ -38,8 +39,7 @@ module Mail
|
|
38
39
|
|
39
40
|
def initialize(value = nil, charset = 'utf-8')
|
40
41
|
self.charset = charset
|
41
|
-
super(CAPITALIZED_FIELD,
|
42
|
-
self.parse
|
42
|
+
super(CAPITALIZED_FIELD, value, charset)
|
43
43
|
self
|
44
44
|
end
|
45
45
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
require 'mail/fields/common/common_field'
|
3
4
|
|
4
5
|
module Mail
|
@@ -31,6 +32,12 @@ module Mail
|
|
31
32
|
else
|
32
33
|
# Ensure we are dealing with a string
|
33
34
|
value = value.to_s
|
35
|
+
|
36
|
+
# Mark UTF-8 strings parsed from ASCII-8BIT
|
37
|
+
if value.respond_to?(:force_encoding) && value.encoding == Encoding::ASCII_8BIT
|
38
|
+
utf8 = value.dup.force_encoding(Encoding::UTF_8)
|
39
|
+
value = utf8 if utf8.valid_encoding?
|
40
|
+
end
|
34
41
|
end
|
35
42
|
|
36
43
|
if charset
|
@@ -66,11 +73,15 @@ module Mail
|
|
66
73
|
private
|
67
74
|
|
68
75
|
def do_encode
|
69
|
-
value.
|
76
|
+
if value && !value.empty?
|
77
|
+
"#{wrapped_value}\r\n"
|
78
|
+
else
|
79
|
+
''
|
80
|
+
end
|
70
81
|
end
|
71
82
|
|
72
83
|
def do_decode
|
73
|
-
|
84
|
+
Utilities.blank?(value) ? nil : Encodings.decode_encode(value, :decode)
|
74
85
|
end
|
75
86
|
|
76
87
|
# 2.2.3. Long Header Fields
|
@@ -120,16 +131,16 @@ module Mail
|
|
120
131
|
def fold(prepend = 0) # :nodoc:
|
121
132
|
encoding = normalized_encoding
|
122
133
|
decoded_string = decoded.to_s
|
123
|
-
should_encode = decoded_string.
|
134
|
+
should_encode = !decoded_string.ascii_only?
|
124
135
|
if should_encode
|
125
136
|
first = true
|
126
137
|
words = decoded_string.split(/[ \t]/).map do |word|
|
127
138
|
if first
|
128
139
|
first = !first
|
129
140
|
else
|
130
|
-
word = " "
|
141
|
+
word = " #{word}"
|
131
142
|
end
|
132
|
-
if word.
|
143
|
+
if !word.ascii_only?
|
133
144
|
word
|
134
145
|
else
|
135
146
|
word.scan(/.{7}|.+$/)
|
@@ -143,11 +154,18 @@ module Mail
|
|
143
154
|
while !words.empty?
|
144
155
|
limit = 78 - prepend
|
145
156
|
limit = limit - 7 - encoding.length if should_encode
|
146
|
-
line =
|
157
|
+
line = String.new
|
147
158
|
first_word = true
|
148
159
|
while !words.empty?
|
149
160
|
break unless word = words.first.dup
|
150
|
-
|
161
|
+
|
162
|
+
# Convert on 1.9+ only since we aren't sure of the current
|
163
|
+
# charset encoding on 1.8. We'd need to track internal/external
|
164
|
+
# charset on each field.
|
165
|
+
if charset && word.respond_to?(:encoding)
|
166
|
+
word = Encodings.transcode_charset(word, word.encoding, charset)
|
167
|
+
end
|
168
|
+
|
151
169
|
word = encode(word) if should_encode
|
152
170
|
word = encode_crlf(word)
|
153
171
|
# Skip to next line if we're going to go past the limit
|
@@ -178,7 +196,7 @@ module Mail
|
|
178
196
|
end
|
179
197
|
|
180
198
|
def encode(value)
|
181
|
-
value = [value].pack(
|
199
|
+
value = [value].pack(CAPITAL_M).gsub(EQUAL_LF, EMPTY)
|
182
200
|
value.gsub!(/"/, '=22')
|
183
201
|
value.gsub!(/\(/, '=28')
|
184
202
|
value.gsub!(/\)/, '=29')
|
@@ -189,8 +207,8 @@ module Mail
|
|
189
207
|
end
|
190
208
|
|
191
209
|
def encode_crlf(value)
|
192
|
-
value.gsub!(
|
193
|
-
value.gsub!(
|
210
|
+
value.gsub!(CR, CR_ENCODED)
|
211
|
+
value.gsub!(LF, LF_ENCODED)
|
194
212
|
value
|
195
213
|
end
|
196
214
|
|
data/lib/mail/fields.rb
CHANGED
data/lib/mail/header.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
module Mail
|
3
4
|
|
4
5
|
# Provides access to a header object.
|
@@ -17,7 +18,7 @@ module Mail
|
|
17
18
|
# 2.2.3. All field bodies MUST conform to the syntax described in
|
18
19
|
# sections 3 and 4 of this standard.
|
19
20
|
class Header
|
20
|
-
include
|
21
|
+
include Constants
|
21
22
|
include Utilities
|
22
23
|
include Enumerable
|
23
24
|
|
@@ -49,13 +50,14 @@ module Mail
|
|
49
50
|
# me the example so we can fix it.
|
50
51
|
def initialize(header_text = nil, charset = nil)
|
51
52
|
@charset = charset
|
52
|
-
self.raw_source = header_text
|
53
|
+
self.raw_source = header_text
|
53
54
|
split_header if header_text
|
54
55
|
end
|
55
56
|
|
56
57
|
def initialize_copy(original)
|
57
58
|
super
|
58
59
|
@fields = @fields.dup
|
60
|
+
@fields.map!(&:dup)
|
59
61
|
end
|
60
62
|
|
61
63
|
# The preserved raw source of the header as you passed it in, untouched
|
@@ -91,14 +93,15 @@ module Mail
|
|
91
93
|
# h.fields = ['From: mikel@me.com', 'To: bob@you.com']
|
92
94
|
def fields=(unfolded_fields)
|
93
95
|
@fields = Mail::FieldList.new
|
94
|
-
warn "
|
96
|
+
Kernel.warn "WARNING: More than #{self.class.maximum_amount} header fields; only using the first #{self.class.maximum_amount} and ignoring the rest" if unfolded_fields.length > self.class.maximum_amount
|
95
97
|
unfolded_fields[0..(self.class.maximum_amount-1)].each do |field|
|
96
98
|
|
97
|
-
field = Field.
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
99
|
+
if field = Field.parse(field, charset)
|
100
|
+
if limited_field?(field.name) && (selected = select_field_for(field.name)) && selected.any?
|
101
|
+
selected.first.update(field.name, field.value)
|
102
|
+
else
|
103
|
+
@fields << field
|
104
|
+
end
|
102
105
|
end
|
103
106
|
end
|
104
107
|
|
@@ -130,12 +133,13 @@ module Mail
|
|
130
133
|
# h['To'] #=> 'mikel@me.com'
|
131
134
|
# h['X-Mail-SPAM'] #=> ['15', '20']
|
132
135
|
def [](name)
|
133
|
-
name = dasherize(name)
|
136
|
+
name = dasherize(name)
|
137
|
+
name.downcase!
|
134
138
|
selected = select_field_for(name)
|
135
139
|
case
|
136
140
|
when selected.length > 1
|
137
141
|
selected.map { |f| f }
|
138
|
-
when !
|
142
|
+
when !Utilities.blank?(selected)
|
139
143
|
selected.first
|
140
144
|
else
|
141
145
|
nil
|
@@ -165,11 +169,11 @@ module Mail
|
|
165
169
|
|
166
170
|
case
|
167
171
|
# User wants to delete the field
|
168
|
-
when !
|
172
|
+
when !Utilities.blank?(selected) && value == nil
|
169
173
|
fields.delete_if { |f| selected.include?(f) }
|
170
174
|
|
171
175
|
# User wants to change the field
|
172
|
-
when !
|
176
|
+
when !Utilities.blank?(selected) && limited_field?(fn)
|
173
177
|
selected.first.update(fn, value)
|
174
178
|
|
175
179
|
# User wants to create the field
|
@@ -203,7 +207,7 @@ module Mail
|
|
203
207
|
content-id content-disposition content-location]
|
204
208
|
|
205
209
|
def encoded
|
206
|
-
buffer =
|
210
|
+
buffer = String.new
|
207
211
|
buffer.force_encoding('us-ascii') if buffer.respond_to?(:force_encoding)
|
208
212
|
fields.each do |field|
|
209
213
|
buffer << field.encoded
|
@@ -246,7 +250,7 @@ module Mail
|
|
246
250
|
private
|
247
251
|
|
248
252
|
def raw_source=(val)
|
249
|
-
@raw_source = val
|
253
|
+
@raw_source = ::Mail::Utilities.to_crlf(val).lstrip
|
250
254
|
end
|
251
255
|
|
252
256
|
# Splits an unfolded and line break cleaned header into individual field
|
data/lib/mail/mail.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
module Mail
|
3
4
|
|
4
5
|
# Allows you to create a new Mail::Message object.
|
@@ -89,19 +90,11 @@ module Mail
|
|
89
90
|
# Each mail object inherits the default set in Mail.delivery_method, however, on
|
90
91
|
# a per email basis, you can override the method:
|
91
92
|
#
|
92
|
-
# mail.delivery_method :
|
93
|
+
# mail.delivery_method :smtp
|
93
94
|
#
|
94
95
|
# Or you can override the method and pass in settings:
|
95
96
|
#
|
96
|
-
# mail.delivery_method :
|
97
|
-
#
|
98
|
-
# You can also just modify the settings:
|
99
|
-
#
|
100
|
-
# mail.delivery_settings = { :address => 'some.host' }
|
101
|
-
#
|
102
|
-
# The passed in hash is just merged against the defaults with +merge!+ and the result
|
103
|
-
# assigned the mail object. So the above example will change only the :address value
|
104
|
-
# of the global smtp_settings to be 'some.host', keeping all other values
|
97
|
+
# mail.delivery_method :smtp, :address => 'some.host'
|
105
98
|
def self.defaults(&block)
|
106
99
|
Configuration.instance.instance_eval(&block)
|
107
100
|
end
|
@@ -245,9 +238,11 @@ module Mail
|
|
245
238
|
|
246
239
|
protected
|
247
240
|
|
241
|
+
RANDOM_TAG='%x%x_%x%x%d%x'
|
242
|
+
|
248
243
|
def self.random_tag
|
249
244
|
t = Time.now
|
250
|
-
sprintf(
|
245
|
+
sprintf(RANDOM_TAG,
|
251
246
|
t.to_i, t.tv_usec,
|
252
247
|
$$, Thread.current.object_id.abs, self.uniq, rand(255))
|
253
248
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Mail
|
3
|
+
module Matchers
|
4
|
+
def any_attachment
|
5
|
+
AnyAttachmentMatcher.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def an_attachment_with_filename(filename)
|
9
|
+
AttachmentFilenameMatcher.new(filename)
|
10
|
+
end
|
11
|
+
|
12
|
+
class AnyAttachmentMatcher
|
13
|
+
def ===(other)
|
14
|
+
other.attachment?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class AttachmentFilenameMatcher
|
19
|
+
attr_reader :filename
|
20
|
+
def initialize(filename)
|
21
|
+
@filename = filename
|
22
|
+
end
|
23
|
+
|
24
|
+
def ===(other)
|
25
|
+
other.attachment? && other.filename == filename
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Mail
|
2
3
|
module Matchers
|
3
4
|
def have_sent_email
|
@@ -42,15 +43,25 @@ module Mail
|
|
42
43
|
|
43
44
|
def bcc(recipient_or_list)
|
44
45
|
@blind_copy_recipients ||= []
|
46
|
+
@blind_copy_recipients.concat(Array(recipient_or_list))
|
47
|
+
self
|
48
|
+
end
|
45
49
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
50
|
+
def with_attachments(attachments)
|
51
|
+
@attachments ||= []
|
52
|
+
@attachments.concat(Array(attachments))
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def with_no_attachments
|
57
|
+
@having_attachments = false
|
51
58
|
self
|
52
59
|
end
|
53
60
|
|
61
|
+
def with_any_attachments
|
62
|
+
@having_attachments = true
|
63
|
+
self
|
64
|
+
end
|
54
65
|
|
55
66
|
def with_subject(subject)
|
56
67
|
@subject = subject
|
@@ -72,6 +83,16 @@ module Mail
|
|
72
83
|
self
|
73
84
|
end
|
74
85
|
|
86
|
+
def with_html(body)
|
87
|
+
@html_part_body = body
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
def with_text(body)
|
92
|
+
@text_part_body = body
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
75
96
|
def description
|
76
97
|
result = "send a matching email"
|
77
98
|
result
|
@@ -84,7 +105,7 @@ module Mail
|
|
84
105
|
result
|
85
106
|
end
|
86
107
|
|
87
|
-
def
|
108
|
+
def failure_message_when_negated
|
88
109
|
result = "Expected no email to be sent "
|
89
110
|
result += explain_expectations
|
90
111
|
result += dump_deliveries
|
@@ -92,11 +113,13 @@ module Mail
|
|
92
113
|
end
|
93
114
|
|
94
115
|
protected
|
95
|
-
|
116
|
+
|
96
117
|
def filter_matched_deliveries(deliveries)
|
97
118
|
candidate_deliveries = deliveries
|
98
|
-
|
99
|
-
|
119
|
+
modifiers =
|
120
|
+
%w(sender recipients copy_recipients blind_copy_recipients subject
|
121
|
+
subject_matcher body body_matcher html_part_body text_part_body having_attachments attachments)
|
122
|
+
modifiers.each do |modifier_name|
|
100
123
|
next unless instance_variable_defined?("@#{modifier_name}")
|
101
124
|
candidate_deliveries = candidate_deliveries.select{|matching_delivery| self.send("matches_on_#{modifier_name}?", matching_delivery)}
|
102
125
|
end
|
@@ -128,6 +151,17 @@ module Mail
|
|
128
151
|
@subject_matcher.match delivery.subject
|
129
152
|
end
|
130
153
|
|
154
|
+
def matches_on_having_attachments?(delivery)
|
155
|
+
@having_attachments && delivery.attachments.any? ||
|
156
|
+
(!@having_attachments && delivery.attachments.none?)
|
157
|
+
end
|
158
|
+
|
159
|
+
def matches_on_attachments?(delivery)
|
160
|
+
@attachments.each_with_index.inject( true ) do |sent_attachments, (attachment, index)|
|
161
|
+
sent_attachments &&= (attachment === delivery.attachments[index])
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
131
165
|
def matches_on_body?(delivery)
|
132
166
|
delivery.body == @body
|
133
167
|
end
|
@@ -136,6 +170,14 @@ module Mail
|
|
136
170
|
@body_matcher.match delivery.body.raw_source
|
137
171
|
end
|
138
172
|
|
173
|
+
def matches_on_html_part_body?(delivery)
|
174
|
+
delivery.html_part.body == @html_part_body
|
175
|
+
end
|
176
|
+
|
177
|
+
def matches_on_text_part_body?(delivery)
|
178
|
+
delivery.text_part.body == @text_part_body
|
179
|
+
end
|
180
|
+
|
139
181
|
def explain_expectations
|
140
182
|
result = ''
|
141
183
|
result += "from #{@sender} " if instance_variable_defined?('@sender')
|
@@ -146,6 +188,8 @@ module Mail
|
|
146
188
|
result += "with subject matching \"#{@subject_matcher}\" " if instance_variable_defined?('@subject_matcher')
|
147
189
|
result += "with body \"#{@body}\" " if instance_variable_defined?('@body')
|
148
190
|
result += "with body matching \"#{@body_matcher}\" " if instance_variable_defined?('@body_matcher')
|
191
|
+
result += "with a text part matching \"#{@text_part_body}\" " if instance_variable_defined?('@text_part_body')
|
192
|
+
result += "with an HTML part matching \"#{@html_part_body}\" " if instance_variable_defined?('@html_part_body')
|
149
193
|
result
|
150
194
|
end
|
151
195
|
|