mail 2.6.1 → 2.7.1
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.
- 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
|
|