mail 2.6.3 → 2.7.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.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +91 -79
- data/lib/mail/attachments_list.rb +11 -5
- data/lib/mail/body.rb +46 -39
- data/lib/mail/check_delivery_params.rb +50 -10
- data/lib/mail/configuration.rb +3 -0
- data/lib/mail/constants.rb +4 -2
- data/lib/mail/core_extensions/smtp.rb +20 -16
- data/lib/mail/core_extensions/string.rb +1 -30
- data/lib/mail/elements/address.rb +43 -32
- data/lib/mail/elements/address_list.rb +11 -18
- 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 +3 -1
- data/lib/mail/encodings.rb +114 -60
- data/lib/mail/envelope.rb +2 -1
- data/lib/mail/field.rb +112 -62
- data/lib/mail/field_list.rb +1 -0
- 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 +5 -11
- data/lib/mail/fields/common/common_message_id.rb +3 -2
- data/lib/mail/fields/common/parameter_hash.rb +2 -1
- 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 +6 -10
- 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 +25 -7
- data/lib/mail/fields.rb +1 -0
- data/lib/mail/header.rb +15 -12
- data/lib/mail/indifferent_hash.rb +1 -0
- data/lib/mail/mail.rb +3 -10
- data/lib/mail/matchers/attachment_matchers.rb +29 -0
- data/lib/mail/matchers/has_sent_mail.rb +51 -7
- data/lib/mail/message.rb +91 -85
- data/lib/mail/multibyte/chars.rb +32 -30
- data/lib/mail/multibyte/unicode.rb +21 -16
- 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 +33187 -112
- data/lib/mail/parsers/address_lists_parser.rl +172 -0
- data/lib/mail/parsers/content_disposition_parser.rb +889 -55
- data/lib/mail/parsers/content_disposition_parser.rl +82 -0
- data/lib/mail/parsers/content_location_parser.rb +801 -23
- data/lib/mail/parsers/content_location_parser.rl +71 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +511 -22
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +64 -0
- data/lib/mail/parsers/content_type_parser.rb +1033 -54
- data/lib/mail/parsers/content_type_parser.rl +83 -0
- data/lib/mail/parsers/date_time_parser.rb +875 -25
- data/lib/mail/parsers/date_time_parser.rl +62 -0
- data/lib/mail/parsers/envelope_from_parser.rb +3565 -36
- data/lib/mail/parsers/envelope_from_parser.rl +82 -0
- data/lib/mail/parsers/message_ids_parser.rb +2844 -25
- data/lib/mail/parsers/message_ids_parser.rl +82 -0
- data/lib/mail/parsers/mime_version_parser.rb +494 -26
- data/lib/mail/parsers/mime_version_parser.rl +61 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +876 -18
- data/lib/mail/parsers/phrase_lists_parser.rl +83 -0
- data/lib/mail/parsers/received_parser.rb +8744 -37
- 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 +6 -3
- data/lib/mail/parts_list.rb +31 -14
- data/lib/mail/utilities.rb +107 -8
- data/lib/mail/values/unicode_tables.dat +0 -0
- data/lib/mail/version.rb +3 -2
- data/lib/mail/version_specific/ruby_1_8.rb +50 -6
- data/lib/mail/version_specific/ruby_1_9.rb +103 -18
- data/lib/mail.rb +5 -12
- metadata +33 -57
- data/CHANGELOG.rdoc +0 -759
- data/CONTRIBUTING.md +0 -60
- data/Dependencies.txt +0 -2
- data/Gemfile +0 -15
- data/Rakefile +0 -29
- data/TODO.rdoc +0 -9
- 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 -185
- 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 -2149
- 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 -40
- data/lib/mail/parsers/ragel.rb +0 -17
data/lib/mail/field.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mail/fields'
|
|
3
|
+
require 'mail/constants'
|
|
2
4
|
|
|
3
5
|
# encoding: utf-8
|
|
4
6
|
module Mail
|
|
@@ -82,9 +84,31 @@ module Mail
|
|
|
82
84
|
|
|
83
85
|
def initialize(element, value, reason)
|
|
84
86
|
@element = element
|
|
85
|
-
@value = value
|
|
86
|
-
@reason = reason
|
|
87
|
-
super("#{element} can not parse |#{value}
|
|
87
|
+
@value = to_utf8(value)
|
|
88
|
+
@reason = to_utf8(reason)
|
|
89
|
+
super("#{@element} can not parse |#{@value}|: #{@reason}")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
private
|
|
93
|
+
def to_utf8(text)
|
|
94
|
+
if text.respond_to?(:force_encoding)
|
|
95
|
+
text.dup.force_encoding(Encoding::UTF_8)
|
|
96
|
+
else
|
|
97
|
+
text
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
class NilParseError < ParseError #:nodoc:
|
|
103
|
+
def initialize(element)
|
|
104
|
+
super element, nil, 'nil is invalid'
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
class IncompleteParseError < ParseError #:nodoc:
|
|
109
|
+
def initialize(element, original_text, unparsed_index)
|
|
110
|
+
parsed_text = to_utf8(original_text[0...unparsed_index])
|
|
111
|
+
super element, original_text, "Only able to parse up to #{parsed_text.inspect}"
|
|
88
112
|
end
|
|
89
113
|
end
|
|
90
114
|
|
|
@@ -92,41 +116,62 @@ module Mail
|
|
|
92
116
|
class SyntaxError < FieldError #:nodoc:
|
|
93
117
|
end
|
|
94
118
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
119
|
+
class << self
|
|
120
|
+
# Parse a field from a raw header line:
|
|
121
|
+
#
|
|
122
|
+
# Mail::Field.parse("field-name: field data")
|
|
123
|
+
# # => #<Mail::Field …>
|
|
124
|
+
def parse(field, charset = nil)
|
|
125
|
+
name, value = split(field)
|
|
126
|
+
if name && value
|
|
127
|
+
new name, value, charset
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def split(raw_field) #:nodoc:
|
|
132
|
+
if raw_field.index(Constants::COLON)
|
|
133
|
+
name, value = raw_field.split(Constants::COLON, 2)
|
|
134
|
+
name.rstrip!
|
|
135
|
+
if name =~ /\A#{Constants::FIELD_NAME}\z/
|
|
136
|
+
[ name.rstrip, value.strip ]
|
|
137
|
+
else
|
|
138
|
+
Kernel.warn "WARNING: Ignoring unparsable header #{raw_field.inspect}: invalid header name syntax: #{name.inspect}"
|
|
139
|
+
nil
|
|
140
|
+
end
|
|
141
|
+
else
|
|
142
|
+
raw_field.strip
|
|
143
|
+
end
|
|
144
|
+
rescue => error
|
|
145
|
+
warn "WARNING: Ignoring unparsable header #{raw_field.inspect}: #{error.class}: #{error.message}"
|
|
146
|
+
nil
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Create a field by name and optional value:
|
|
102
151
|
#
|
|
103
|
-
#
|
|
152
|
+
# Mail::Field.new("field-name", "value")
|
|
153
|
+
# # => #<Mail::Field …>
|
|
104
154
|
#
|
|
105
|
-
#
|
|
155
|
+
# Values that aren't strings or arrays are coerced to Strings with `#to_s`.
|
|
106
156
|
#
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
# it will be passed through as is, for example, content-type
|
|
110
|
-
# field can accept an array with the type and a hash of
|
|
111
|
-
# parameters:
|
|
157
|
+
# Mail::Field.new("field-name", 1234)
|
|
158
|
+
# # => #<Mail::Field …>
|
|
112
159
|
#
|
|
113
|
-
# Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
|
|
160
|
+
# Mail::Field.new('content-type', ['text', 'plain', {:charset => 'UTF-8'}])
|
|
161
|
+
# # => #<Mail::Field …>
|
|
114
162
|
def initialize(name, value = nil, charset = 'utf-8')
|
|
115
163
|
case
|
|
116
|
-
when name.index(COLON)
|
|
117
|
-
|
|
118
|
-
@name = name
|
|
119
|
-
@
|
|
120
|
-
|
|
121
|
-
when value.blank? # Field.new("field-name")
|
|
164
|
+
when name.index(COLON)
|
|
165
|
+
Kernel.warn 'Passing an unparsed header field to Mail::Field.new is deprecated and will be removed in Mail 2.8.0. Use Mail::Field.parse instead.'
|
|
166
|
+
@name, @unparsed_value = self.class.split(name)
|
|
167
|
+
@charset = Utilities.blank?(value) ? charset : value
|
|
168
|
+
when Utilities.blank?(value)
|
|
122
169
|
@name = name
|
|
123
|
-
@
|
|
124
|
-
@raw_value = nil
|
|
170
|
+
@unparsed_value = nil
|
|
125
171
|
@charset = charset
|
|
126
|
-
else
|
|
172
|
+
else
|
|
127
173
|
@name = name
|
|
128
|
-
@
|
|
129
|
-
@raw_value = nil
|
|
174
|
+
@unparsed_value = value
|
|
130
175
|
@charset = charset
|
|
131
176
|
end
|
|
132
177
|
@name = FIELD_NAME_MAP[@name.to_s.downcase] || @name
|
|
@@ -137,8 +182,7 @@ module Mail
|
|
|
137
182
|
end
|
|
138
183
|
|
|
139
184
|
def field
|
|
140
|
-
|
|
141
|
-
@field ||= create_field(@name, @value, @charset)
|
|
185
|
+
@field ||= create_field(@name, @unparsed_value, @charset)
|
|
142
186
|
end
|
|
143
187
|
|
|
144
188
|
def name
|
|
@@ -168,15 +212,19 @@ module Mail
|
|
|
168
212
|
end
|
|
169
213
|
|
|
170
214
|
def same( other )
|
|
215
|
+
return false unless other.kind_of?(self.class)
|
|
171
216
|
match_to_s(other.name, self.name)
|
|
172
217
|
end
|
|
173
218
|
|
|
219
|
+
def ==( other )
|
|
220
|
+
return false unless other.kind_of?(self.class)
|
|
221
|
+
match_to_s(other.name, self.name) && match_to_s(other.value, self.value)
|
|
222
|
+
end
|
|
223
|
+
|
|
174
224
|
def responsible_for?( val )
|
|
175
225
|
name.to_s.casecmp(val.to_s) == 0
|
|
176
226
|
end
|
|
177
227
|
|
|
178
|
-
alias_method :==, :same
|
|
179
|
-
|
|
180
228
|
def <=>( other )
|
|
181
229
|
self.field_order_id <=> other.field_order_id
|
|
182
230
|
end
|
|
@@ -189,6 +237,16 @@ module Mail
|
|
|
189
237
|
field.send(name, *args, &block)
|
|
190
238
|
end
|
|
191
239
|
|
|
240
|
+
if RUBY_VERSION >= '1.9.2'
|
|
241
|
+
def respond_to_missing?(method_name, include_private)
|
|
242
|
+
field.respond_to?(method_name, include_private) || super
|
|
243
|
+
end
|
|
244
|
+
else
|
|
245
|
+
def respond_to?(method_name, include_private = false)
|
|
246
|
+
field.respond_to?(method_name, include_private) || super
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
192
250
|
FIELD_ORDER = %w[ return-path received
|
|
193
251
|
resent-date resent-from resent-sender resent-to
|
|
194
252
|
resent-cc resent-bcc resent-message-id
|
|
@@ -202,11 +260,26 @@ module Mail
|
|
|
202
260
|
|
|
203
261
|
private
|
|
204
262
|
|
|
205
|
-
def
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
263
|
+
def create_field(name, value, charset)
|
|
264
|
+
new_field(name, value, charset)
|
|
265
|
+
rescue Mail::Field::ParseError => e
|
|
266
|
+
field = Mail::UnstructuredField.new(name, value)
|
|
267
|
+
field.errors << [name, value, e]
|
|
268
|
+
field
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def new_field(name, value, charset)
|
|
272
|
+
value = unfold(value) if value.is_a?(String)
|
|
273
|
+
|
|
274
|
+
if klass = field_class_for(name)
|
|
275
|
+
klass.new(value, charset)
|
|
276
|
+
else
|
|
277
|
+
OptionalField.new(name, value, charset)
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def field_class_for(name)
|
|
282
|
+
FIELDS_MAP[name.to_s.downcase]
|
|
210
283
|
end
|
|
211
284
|
|
|
212
285
|
# 2.2.3. Long Header Fields
|
|
@@ -218,30 +291,7 @@ module Mail
|
|
|
218
291
|
# treated in its unfolded form for further syntactic and semantic
|
|
219
292
|
# evaluation.
|
|
220
293
|
def unfold(string)
|
|
221
|
-
string.gsub(/
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
def create_field(name, value, charset)
|
|
225
|
-
value = unfold(value) if value.is_a?(String)
|
|
226
|
-
|
|
227
|
-
begin
|
|
228
|
-
new_field(name, value, charset)
|
|
229
|
-
rescue Mail::Field::ParseError => e
|
|
230
|
-
field = Mail::UnstructuredField.new(name, value)
|
|
231
|
-
field.errors << [name, value, e]
|
|
232
|
-
field
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
def new_field(name, value, charset)
|
|
237
|
-
lower_case_name = name.to_s.downcase
|
|
238
|
-
if field_klass = FIELDS_MAP[lower_case_name]
|
|
239
|
-
field_klass.new(value, charset)
|
|
240
|
-
else
|
|
241
|
-
OptionalField.new(name, value, charset)
|
|
242
|
-
end
|
|
294
|
+
string.gsub(/#{CRLF}(#{WSP})/m, '\1')
|
|
243
295
|
end
|
|
244
|
-
|
|
245
296
|
end
|
|
246
|
-
|
|
247
297
|
end
|
data/lib/mail/field_list.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# = Blind Carbon Copy Field
|
|
4
5
|
#
|
|
@@ -36,16 +37,27 @@ module Mail
|
|
|
36
37
|
FIELD_NAME = 'bcc'
|
|
37
38
|
CAPITALIZED_FIELD = 'Bcc'
|
|
38
39
|
|
|
39
|
-
def initialize(value =
|
|
40
|
+
def initialize(value = nil, charset = 'utf-8')
|
|
40
41
|
@charset = charset
|
|
41
|
-
super(CAPITALIZED_FIELD,
|
|
42
|
-
self.parse
|
|
42
|
+
super(CAPITALIZED_FIELD, value, charset)
|
|
43
43
|
self
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
def include_in_headers=(include_in_headers)
|
|
47
|
+
@include_in_headers = include_in_headers
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def include_in_headers
|
|
51
|
+
defined?(@include_in_headers) ? @include_in_headers : self.include_in_headers = false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Bcc field should not be :encoded by default
|
|
47
55
|
def encoded
|
|
48
|
-
|
|
56
|
+
if include_in_headers
|
|
57
|
+
do_encode(CAPITALIZED_FIELD)
|
|
58
|
+
else
|
|
59
|
+
''
|
|
60
|
+
end
|
|
49
61
|
end
|
|
50
62
|
|
|
51
63
|
def decoded
|
data/lib/mail/fields/cc_field.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# = Carbon Copy 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
|
# = Comments Field
|
|
4
5
|
#
|
|
@@ -32,7 +33,7 @@ module Mail
|
|
|
32
33
|
|
|
33
34
|
def initialize(value = nil, charset = 'utf-8')
|
|
34
35
|
@charset = charset
|
|
35
|
-
super(CAPITALIZED_FIELD,
|
|
36
|
+
super(CAPITALIZED_FIELD, value)
|
|
36
37
|
self.parse
|
|
37
38
|
self
|
|
38
39
|
end
|
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
require 'mail/fields/common/address_container'
|
|
3
4
|
|
|
4
5
|
module Mail
|
|
5
6
|
module CommonAddress # :nodoc:
|
|
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
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
def charset
|
|
16
16
|
@charset
|
|
17
17
|
end
|
|
18
|
-
|
|
19
|
-
def encode_if_needed(val)
|
|
20
|
-
|
|
18
|
+
|
|
19
|
+
def encode_if_needed(val) #:nodoc:
|
|
20
|
+
# Need to join arrays of addresses into a single value
|
|
21
|
+
if val.kind_of?(Array)
|
|
22
|
+
val.compact.map { |a| encode_if_needed a }.join(', ')
|
|
23
|
+
|
|
24
|
+
# Pass through UTF-8; encode non-UTF-8.
|
|
25
|
+
else
|
|
26
|
+
utf8_if_needed(val) || Encodings.encode_non_usascii(val, charset)
|
|
27
|
+
end
|
|
21
28
|
end
|
|
22
|
-
|
|
29
|
+
|
|
23
30
|
# Allows you to iterate through each address object in the address_list
|
|
24
31
|
def each
|
|
25
32
|
address_list.addresses.each do |address|
|
|
@@ -84,10 +91,10 @@ module Mail
|
|
|
84
91
|
case
|
|
85
92
|
when val.nil?
|
|
86
93
|
raise ArgumentError, "Need to pass an address to <<"
|
|
87
|
-
when
|
|
94
|
+
when Utilities.blank?(val)
|
|
88
95
|
parse(encoded)
|
|
89
96
|
else
|
|
90
|
-
self.value = [self.value, val].reject {|a|
|
|
97
|
+
self.value = [self.value, val].reject {|a| Utilities.blank?(a) }.join(", ")
|
|
91
98
|
end
|
|
92
99
|
end
|
|
93
100
|
|
|
@@ -97,24 +104,43 @@ module Mail
|
|
|
97
104
|
end
|
|
98
105
|
|
|
99
106
|
private
|
|
100
|
-
|
|
107
|
+
|
|
108
|
+
if 'string'.respond_to?(:encoding)
|
|
109
|
+
# Pass through UTF-8 addresses
|
|
110
|
+
def utf8_if_needed(val)
|
|
111
|
+
if charset =~ /\AUTF-?8\z/i
|
|
112
|
+
val
|
|
113
|
+
elsif val.encoding == Encoding::UTF_8
|
|
114
|
+
val
|
|
115
|
+
elsif (utf8 = val.dup.force_encoding(Encoding::UTF_8)).valid_encoding?
|
|
116
|
+
utf8
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
else
|
|
120
|
+
def utf8_if_needed(val)
|
|
121
|
+
if charset =~ /\AUTF-?8\z/i
|
|
122
|
+
val
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
101
127
|
def do_encode(field_name)
|
|
102
|
-
return '' if
|
|
128
|
+
return '' if Utilities.blank?(value)
|
|
103
129
|
address_array = address_list.addresses.reject { |a| encoded_group_addresses.include?(a.encoded) }.compact.map { |a| a.encoded }
|
|
104
130
|
address_text = address_array.join(", \r\n\s")
|
|
105
131
|
group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.encoded }.join(", \r\n\s")};" }
|
|
106
132
|
group_text = group_array.join(" \r\n\s")
|
|
107
|
-
return_array = [address_text, group_text].reject { |a|
|
|
133
|
+
return_array = [address_text, group_text].reject { |a| Utilities.blank?(a) }
|
|
108
134
|
"#{field_name}: #{return_array.join(", \r\n\s")}\r\n"
|
|
109
135
|
end
|
|
110
136
|
|
|
111
137
|
def do_decode
|
|
112
|
-
return nil if
|
|
138
|
+
return nil if Utilities.blank?(value)
|
|
113
139
|
address_array = address_list.addresses.reject { |a| decoded_group_addresses.include?(a.decoded) }.map { |a| a.decoded }
|
|
114
140
|
address_text = address_array.join(", ")
|
|
115
141
|
group_array = groups.map { |k,v| "#{k}: #{v.map { |a| a.decoded }.join(", ")};" }
|
|
116
142
|
group_text = group_array.join(" ")
|
|
117
|
-
return_array = [address_text, group_text].reject { |a|
|
|
143
|
+
return_array = [address_text, group_text].reject { |a| Utilities.blank?(a) }
|
|
118
144
|
return_array.join(", ")
|
|
119
145
|
end
|
|
120
146
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Mail
|
|
3
4
|
module CommonDate # :nodoc:
|
|
4
5
|
# Returns a date time object of the parsed date
|
|
@@ -11,7 +12,7 @@ module Mail
|
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
def parse(val = value)
|
|
14
|
-
unless
|
|
15
|
+
unless Utilities.blank?(val)
|
|
15
16
|
@element = Mail::DateTimeElement.new(val)
|
|
16
17
|
else
|
|
17
18
|
nil
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Mail
|
|
3
4
|
module CommonField # :nodoc:
|
|
4
5
|
include Mail::Constants
|
|
@@ -13,9 +14,8 @@ module Mail
|
|
|
13
14
|
|
|
14
15
|
def value=(value)
|
|
15
16
|
@length = nil
|
|
16
|
-
@tree = nil
|
|
17
17
|
@element = nil
|
|
18
|
-
@value = value
|
|
18
|
+
@value = value.is_a?(Array) ? value : value.to_s
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def value
|
|
@@ -40,18 +40,12 @@ module Mail
|
|
|
40
40
|
|
|
41
41
|
private
|
|
42
42
|
|
|
43
|
-
def strip_field(field_name, value)
|
|
44
|
-
if value.is_a?(Array)
|
|
45
|
-
value
|
|
46
|
-
else
|
|
47
|
-
value.to_s.sub(/#{field_name}:\s+/i, EMPTY)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
43
|
FILENAME_RE = /\b(filename|name)=([^;"\r\n]+\s[^;"\r\n]+)/
|
|
52
44
|
def ensure_filename_quoted(value)
|
|
53
45
|
if value.is_a?(String)
|
|
54
|
-
value.sub
|
|
46
|
+
value.sub FILENAME_RE, '\1="\2"'
|
|
47
|
+
else
|
|
48
|
+
value
|
|
55
49
|
end
|
|
56
50
|
end
|
|
57
51
|
end
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Mail
|
|
3
4
|
module CommonMessageId # :nodoc:
|
|
4
5
|
def element
|
|
5
|
-
@element ||= Mail::MessageIdsElement.new(value) unless
|
|
6
|
+
@element ||= Mail::MessageIdsElement.new(value) unless Utilities.blank?(value)
|
|
6
7
|
end
|
|
7
8
|
|
|
8
9
|
def parse(val = value)
|
|
9
|
-
unless
|
|
10
|
+
unless Utilities.blank?(val)
|
|
10
11
|
@element = Mail::MessageIdsElement.new(val)
|
|
11
12
|
else
|
|
12
13
|
nil
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Mail
|
|
3
4
|
|
|
4
5
|
# ParameterHash is an intelligent Hash that allows you to add
|
|
@@ -29,7 +30,7 @@ module Mail
|
|
|
29
30
|
super(exact || key_name)
|
|
30
31
|
else # Dealing with a multiple value pair or a single encoded value pair
|
|
31
32
|
string = pairs.sort { |a,b| a.first.to_s <=> b.first.to_s }.map { |v| v.last }.join('')
|
|
32
|
-
if mt = string.match(/([\w\-]+)'(\w\w)'(.*)/)
|
|
33
|
+
if mt = string.match(/([\w\-]+)?'(\w\w)?'(.*)/)
|
|
33
34
|
string = mt[3]
|
|
34
35
|
encoding = mt[1]
|
|
35
36
|
else
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
#
|
|
4
5
|
#
|
|
@@ -10,7 +11,7 @@ module Mail
|
|
|
10
11
|
|
|
11
12
|
def initialize(value = nil, charset = 'utf-8')
|
|
12
13
|
self.charset = charset
|
|
13
|
-
super(CAPITALIZED_FIELD,
|
|
14
|
+
super(CAPITALIZED_FIELD, value, charset)
|
|
14
15
|
self.parse
|
|
15
16
|
self
|
|
16
17
|
end
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
require 'mail/fields/common/parameter_hash'
|
|
3
4
|
|
|
4
5
|
module Mail
|
|
5
6
|
class ContentDispositionField < StructuredField
|
|
6
|
-
|
|
7
|
+
|
|
7
8
|
FIELD_NAME = 'content-disposition'
|
|
8
9
|
CAPITALIZED_FIELD = 'Content-Disposition'
|
|
9
|
-
|
|
10
|
+
|
|
10
11
|
def initialize(value = nil, charset = 'utf-8')
|
|
11
12
|
self.charset = charset
|
|
12
|
-
ensure_filename_quoted(value)
|
|
13
|
-
super(CAPITALIZED_FIELD,
|
|
13
|
+
value = ensure_filename_quoted(value)
|
|
14
|
+
super(CAPITALIZED_FIELD, value, charset)
|
|
14
15
|
self.parse
|
|
15
16
|
self
|
|
16
17
|
end
|
|
17
|
-
|
|
18
|
+
|
|
18
19
|
def parse(val = value)
|
|
19
|
-
unless
|
|
20
|
+
unless Utilities.blank?(val)
|
|
20
21
|
@element = Mail::ContentDispositionElement.new(val)
|
|
21
22
|
end
|
|
22
23
|
end
|
|
23
|
-
|
|
24
|
+
|
|
24
25
|
def element
|
|
25
26
|
@element ||= Mail::ContentDispositionElement.new(value)
|
|
26
27
|
end
|
|
@@ -28,20 +29,20 @@ module Mail
|
|
|
28
29
|
def disposition_type
|
|
29
30
|
element.disposition_type
|
|
30
31
|
end
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
def parameters
|
|
33
34
|
@parameters = ParameterHash.new
|
|
34
|
-
element.parameters.each { |p| @parameters.merge!(p) }
|
|
35
|
+
element.parameters.each { |p| @parameters.merge!(p) } unless element.parameters.nil?
|
|
35
36
|
@parameters
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
def filename
|
|
39
40
|
case
|
|
40
|
-
when
|
|
41
|
+
when parameters['filename']
|
|
41
42
|
@filename = parameters['filename']
|
|
42
|
-
when
|
|
43
|
+
when parameters['name']
|
|
43
44
|
@filename = parameters['name']
|
|
44
|
-
else
|
|
45
|
+
else
|
|
45
46
|
@filename = nil
|
|
46
47
|
end
|
|
47
48
|
@filename
|
|
@@ -56,7 +57,7 @@ module Mail
|
|
|
56
57
|
end
|
|
57
58
|
"#{CAPITALIZED_FIELD}: #{disposition_type}" + p
|
|
58
59
|
end
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
def decoded
|
|
61
62
|
if parameters.length > 0
|
|
62
63
|
p = "; #{parameters.decoded}"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
#
|
|
4
5
|
#
|
|
@@ -11,18 +12,18 @@ module Mail
|
|
|
11
12
|
def initialize(value = nil, charset = 'utf-8')
|
|
12
13
|
self.charset = charset
|
|
13
14
|
@uniq = 1
|
|
14
|
-
if
|
|
15
|
+
if Utilities.blank?(value)
|
|
15
16
|
value = generate_content_id
|
|
16
17
|
else
|
|
17
|
-
value =
|
|
18
|
+
value = value.to_s
|
|
18
19
|
end
|
|
19
|
-
super(CAPITALIZED_FIELD,
|
|
20
|
+
super(CAPITALIZED_FIELD, value, charset)
|
|
20
21
|
self.parse
|
|
21
22
|
self
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def parse(val = value)
|
|
25
|
-
unless
|
|
26
|
+
unless Utilities.blank?(val)
|
|
26
27
|
@element = Mail::MessageIdsElement.new(val)
|
|
27
28
|
end
|
|
28
29
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
#
|
|
4
5
|
#
|
|
@@ -10,13 +11,13 @@ module Mail
|
|
|
10
11
|
|
|
11
12
|
def initialize(value = nil, charset = 'utf-8')
|
|
12
13
|
self.charset = charset
|
|
13
|
-
super(CAPITALIZED_FIELD,
|
|
14
|
+
super(CAPITALIZED_FIELD, value, charset)
|
|
14
15
|
self.parse
|
|
15
16
|
self
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def parse(val = value)
|
|
19
|
-
unless
|
|
20
|
+
unless Utilities.blank?(val)
|
|
20
21
|
@element = Mail::ContentLocationElement.new(val)
|
|
21
22
|
end
|
|
22
23
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
#
|
|
4
5
|
#
|
|
@@ -12,13 +13,13 @@ module Mail
|
|
|
12
13
|
self.charset = charset
|
|
13
14
|
value = '7bit' if value.to_s =~ /7-?bits?/i
|
|
14
15
|
value = '8bit' if value.to_s =~ /8-?bits?/i
|
|
15
|
-
super(CAPITALIZED_FIELD,
|
|
16
|
+
super(CAPITALIZED_FIELD, value, charset)
|
|
16
17
|
self.parse
|
|
17
18
|
self
|
|
18
19
|
end
|
|
19
20
|
|
|
20
21
|
def parse(val = value)
|
|
21
|
-
unless
|
|
22
|
+
unless Utilities.blank?(val)
|
|
22
23
|
@element = Mail::ContentTransferEncodingElement.new(val)
|
|
23
24
|
end
|
|
24
25
|
end
|