mail 2.6.4 → 2.9.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 +5 -5
- data/README.md +208 -156
- data/lib/mail/attachments_list.rb +13 -10
- data/lib/mail/body.rb +96 -107
- data/lib/mail/configuration.rb +2 -0
- data/lib/mail/constants.rb +27 -5
- data/lib/mail/elements/address.rb +61 -50
- data/lib/mail/elements/address_list.rb +11 -19
- data/lib/mail/elements/content_disposition_element.rb +9 -16
- data/lib/mail/elements/content_location_element.rb +6 -11
- data/lib/mail/elements/content_transfer_encoding_element.rb +6 -11
- data/lib/mail/elements/content_type_element.rb +16 -23
- data/lib/mail/elements/date_time_element.rb +7 -15
- data/lib/mail/elements/envelope_from_element.rb +22 -23
- data/lib/mail/elements/message_ids_element.rb +18 -13
- data/lib/mail/elements/mime_version_element.rb +7 -15
- data/lib/mail/elements/phrase_list.rb +12 -10
- data/lib/mail/elements/received_element.rb +27 -19
- data/lib/mail/encodings/7bit.rb +9 -14
- data/lib/mail/encodings/8bit.rb +2 -21
- data/lib/mail/encodings/base64.rb +11 -12
- data/lib/mail/encodings/binary.rb +3 -22
- data/lib/mail/encodings/identity.rb +24 -0
- data/lib/mail/encodings/quoted_printable.rb +6 -6
- data/lib/mail/encodings/transfer_encoding.rb +38 -29
- data/lib/mail/encodings/unix_to_unix.rb +4 -2
- data/lib/mail/encodings.rb +83 -56
- data/lib/mail/envelope.rb +11 -14
- data/lib/mail/field.rb +181 -130
- data/lib/mail/field_list.rb +61 -8
- data/lib/mail/fields/bcc_field.rb +33 -52
- data/lib/mail/fields/cc_field.rb +27 -49
- data/lib/mail/fields/comments_field.rb +26 -37
- data/lib/mail/fields/common_address_field.rb +162 -0
- data/lib/mail/fields/common_date_field.rb +56 -0
- data/lib/mail/fields/common_field.rb +77 -0
- data/lib/mail/fields/common_message_id_field.rb +41 -0
- data/lib/mail/fields/content_description_field.rb +6 -14
- data/lib/mail/fields/content_disposition_field.rb +11 -38
- data/lib/mail/fields/content_id_field.rb +23 -51
- data/lib/mail/fields/content_location_field.rb +10 -25
- data/lib/mail/fields/content_transfer_encoding_field.rb +30 -31
- data/lib/mail/fields/content_type_field.rb +53 -84
- data/lib/mail/fields/date_field.rb +22 -52
- data/lib/mail/fields/from_field.rb +27 -49
- data/lib/mail/fields/in_reply_to_field.rb +37 -49
- data/lib/mail/fields/keywords_field.rb +17 -31
- data/lib/mail/fields/message_id_field.rb +24 -71
- data/lib/mail/fields/mime_version_field.rb +18 -30
- data/lib/mail/fields/named_structured_field.rb +10 -0
- data/lib/mail/fields/named_unstructured_field.rb +10 -0
- data/lib/mail/fields/optional_field.rb +9 -8
- data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +13 -11
- data/lib/mail/fields/received_field.rb +42 -57
- data/lib/mail/fields/references_field.rb +34 -49
- data/lib/mail/fields/reply_to_field.rb +27 -49
- data/lib/mail/fields/resent_bcc_field.rb +27 -49
- data/lib/mail/fields/resent_cc_field.rb +27 -49
- data/lib/mail/fields/resent_date_field.rb +4 -30
- data/lib/mail/fields/resent_from_field.rb +27 -49
- data/lib/mail/fields/resent_message_id_field.rb +4 -29
- data/lib/mail/fields/resent_sender_field.rb +26 -56
- data/lib/mail/fields/resent_to_field.rb +27 -49
- data/lib/mail/fields/return_path_field.rb +49 -54
- data/lib/mail/fields/sender_field.rb +33 -55
- data/lib/mail/fields/structured_field.rb +2 -30
- data/lib/mail/fields/subject_field.rb +8 -11
- data/lib/mail/fields/to_field.rb +27 -49
- data/lib/mail/fields/unstructured_field.rb +31 -47
- data/lib/mail/fields.rb +9 -0
- data/lib/mail/header.rb +71 -110
- data/lib/mail/mail.rb +34 -37
- data/lib/mail/matchers/attachment_matchers.rb +15 -0
- data/lib/mail/matchers/has_sent_mail.rb +21 -1
- data/lib/mail/message.rb +126 -127
- data/lib/mail/multibyte/chars.rb +24 -181
- data/lib/mail/multibyte/unicode.rb +11 -11
- data/lib/mail/multibyte/utils.rb +26 -43
- data/lib/mail/multibyte.rb +55 -16
- data/lib/mail/network/delivery_methods/exim.rb +8 -11
- data/lib/mail/network/delivery_methods/file_delivery.rb +15 -18
- data/lib/mail/network/delivery_methods/logger_delivery.rb +34 -0
- data/lib/mail/network/delivery_methods/sendmail.rb +32 -35
- data/lib/mail/network/delivery_methods/smtp.rb +125 -68
- data/lib/mail/network/delivery_methods/smtp_connection.rb +11 -16
- data/lib/mail/network/delivery_methods/test_mailer.rb +12 -13
- data/lib/mail/network/retriever_methods/base.rb +13 -13
- data/lib/mail/network/retriever_methods/imap.rb +25 -9
- data/lib/mail/network/retriever_methods/pop3.rb +25 -23
- data/lib/mail/network/retriever_methods/test_retriever.rb +3 -2
- data/lib/mail/network.rb +1 -0
- data/lib/mail/parser_tools.rb +15 -0
- data/lib/mail/parsers/address_lists_parser.rb +33228 -116
- data/lib/mail/parsers/address_lists_parser.rl +183 -0
- data/lib/mail/parsers/content_disposition_parser.rb +885 -49
- data/lib/mail/parsers/content_disposition_parser.rl +93 -0
- data/lib/mail/parsers/content_location_parser.rb +812 -23
- data/lib/mail/parsers/content_location_parser.rl +82 -0
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +512 -21
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +75 -0
- data/lib/mail/parsers/content_type_parser.rb +1039 -55
- data/lib/mail/parsers/content_type_parser.rl +94 -0
- data/lib/mail/parsers/date_time_parser.rb +880 -25
- data/lib/mail/parsers/date_time_parser.rl +73 -0
- data/lib/mail/parsers/envelope_from_parser.rb +3672 -40
- data/lib/mail/parsers/envelope_from_parser.rl +93 -0
- data/lib/mail/parsers/message_ids_parser.rb +5149 -25
- data/lib/mail/parsers/message_ids_parser.rl +97 -0
- data/lib/mail/parsers/mime_version_parser.rb +500 -26
- data/lib/mail/parsers/mime_version_parser.rl +72 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +873 -22
- data/lib/mail/parsers/phrase_lists_parser.rl +94 -0
- data/lib/mail/parsers/received_parser.rb +8779 -43
- data/lib/mail/parsers/received_parser.rl +95 -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 +74 -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 +11 -25
- data/lib/mail/part.rb +25 -29
- data/lib/mail/parts_list.rb +62 -6
- data/lib/mail/smtp_envelope.rb +57 -0
- data/lib/mail/utilities.rb +361 -74
- data/lib/mail/version.rb +2 -2
- data/lib/mail/yaml.rb +30 -0
- data/lib/mail.rb +4 -37
- metadata +125 -67
- data/CHANGELOG.rdoc +0 -787
- data/CONTRIBUTING.md +0 -60
- data/Dependencies.txt +0 -2
- data/Gemfile +0 -11
- data/Rakefile +0 -29
- data/TODO.rdoc +0 -9
- data/lib/mail/check_delivery_params.rb +0 -21
- data/lib/mail/core_extensions/smtp.rb +0 -25
- data/lib/mail/core_extensions/string/access.rb +0 -146
- data/lib/mail/core_extensions/string/multibyte.rb +0 -79
- data/lib/mail/core_extensions/string.rb +0 -21
- data/lib/mail/fields/common/address_container.rb +0 -17
- data/lib/mail/fields/common/common_address.rb +0 -136
- data/lib/mail/fields/common/common_date.rb +0 -36
- data/lib/mail/fields/common/common_field.rb +0 -61
- data/lib/mail/fields/common/common_message_id.rb +0 -49
- data/lib/mail/multibyte/exceptions.rb +0 -9
- 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 -18
- data/lib/mail/version_specific/ruby_1_8.rb +0 -126
- data/lib/mail/version_specific/ruby_1_9.rb +0 -223
data/lib/mail/message.rb
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
-
require
|
|
3
|
+
require 'mail/constants'
|
|
4
|
+
require 'mail/utilities'
|
|
5
|
+
require 'mail/yaml'
|
|
4
6
|
|
|
5
7
|
module Mail
|
|
6
8
|
# The Message class provides a single point of access to all things to do with an
|
|
@@ -46,25 +48,29 @@ module Mail
|
|
|
46
48
|
# follows the header and is separated from the header by an empty line
|
|
47
49
|
# (i.e., a line with nothing preceding the CRLF).
|
|
48
50
|
class Message
|
|
49
|
-
|
|
50
|
-
include Constants
|
|
51
|
-
include Utilities
|
|
52
|
-
|
|
53
51
|
# ==Making an email
|
|
54
52
|
#
|
|
55
53
|
# You can make an new mail object via a block, passing a string, file or direct assignment.
|
|
56
54
|
#
|
|
57
55
|
# ===Making an email via a block
|
|
58
56
|
#
|
|
59
|
-
# mail = Mail.new do
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
# subject 'This is a test email'
|
|
63
|
-
#
|
|
57
|
+
# mail = Mail.new do |m|
|
|
58
|
+
# m.from 'mikel@test.lindsaar.net'
|
|
59
|
+
# m.to 'you@test.lindsaar.net'
|
|
60
|
+
# m.subject 'This is a test email'
|
|
61
|
+
# m.body File.read('body.txt')
|
|
64
62
|
# end
|
|
65
63
|
#
|
|
66
64
|
# mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
|
|
67
65
|
#
|
|
66
|
+
# If may also pass a block with no arguments, in which case it will
|
|
67
|
+
# be evaluated in the scope of the new message instance:
|
|
68
|
+
#
|
|
69
|
+
# mail = Mail.new do
|
|
70
|
+
# from 'mikel@test.lindsaar.net'
|
|
71
|
+
# # …
|
|
72
|
+
# end
|
|
73
|
+
#
|
|
68
74
|
# ===Making an email via passing a string
|
|
69
75
|
#
|
|
70
76
|
# mail = Mail.new("To: mikel@test.lindsaar.net\r\nSubject: Hello\r\n\r\nHi there!")
|
|
@@ -129,8 +135,23 @@ module Mail
|
|
|
129
135
|
init_with_string(args.flatten[0].to_s)
|
|
130
136
|
end
|
|
131
137
|
|
|
138
|
+
# Support both builder styles:
|
|
139
|
+
#
|
|
140
|
+
# Mail.new do
|
|
141
|
+
# to 'recipient@example.com'
|
|
142
|
+
# end
|
|
143
|
+
#
|
|
144
|
+
# and
|
|
145
|
+
#
|
|
146
|
+
# Mail.new do |m|
|
|
147
|
+
# m.to 'recipient@example.com'
|
|
148
|
+
# end
|
|
132
149
|
if block_given?
|
|
133
|
-
|
|
150
|
+
if block.arity.zero?
|
|
151
|
+
instance_eval(&block)
|
|
152
|
+
else
|
|
153
|
+
yield self
|
|
154
|
+
end
|
|
134
155
|
end
|
|
135
156
|
|
|
136
157
|
self
|
|
@@ -212,11 +233,6 @@ module Mail
|
|
|
212
233
|
def self.default_charset=(charset); @@default_charset = charset; end
|
|
213
234
|
self.default_charset = 'UTF-8'
|
|
214
235
|
|
|
215
|
-
def register_for_delivery_notification(observer)
|
|
216
|
-
STDERR.puts("Message#register_for_delivery_notification is deprecated, please call Mail.register_observer instead")
|
|
217
|
-
Mail.register_observer(observer)
|
|
218
|
-
end
|
|
219
|
-
|
|
220
236
|
def inform_observers
|
|
221
237
|
Mail.inform_observers(self)
|
|
222
238
|
end
|
|
@@ -225,7 +241,7 @@ module Mail
|
|
|
225
241
|
Mail.inform_interceptors(self)
|
|
226
242
|
end
|
|
227
243
|
|
|
228
|
-
# Delivers
|
|
244
|
+
# Delivers a mail object.
|
|
229
245
|
#
|
|
230
246
|
# Examples:
|
|
231
247
|
#
|
|
@@ -278,7 +294,7 @@ module Mail
|
|
|
278
294
|
reply.references ||= bracketed_message_id
|
|
279
295
|
end
|
|
280
296
|
if subject
|
|
281
|
-
reply.subject =
|
|
297
|
+
reply.subject = /^Re:/i.match?(subject) ? subject : "Re: #{subject}"
|
|
282
298
|
end
|
|
283
299
|
if reply_to || from
|
|
284
300
|
reply.to = self[reply_to ? :reply_to : :from].to_s
|
|
@@ -333,6 +349,10 @@ module Mail
|
|
|
333
349
|
# the same content, ignoring the Message-ID field, unless BOTH emails have a defined and
|
|
334
350
|
# different Message-ID value, then they are false.
|
|
335
351
|
#
|
|
352
|
+
# Note that Mail creates Date and Mime-Type fields if they don't exist.
|
|
353
|
+
# The Date field is derived from the current time, so this needs to be allowed for in comparisons.
|
|
354
|
+
# (Mime-type does not depend on dynamic data, so cannot affect equality)
|
|
355
|
+
#
|
|
336
356
|
# So, in practice the == operator works like this:
|
|
337
357
|
#
|
|
338
358
|
# m1 = Mail.new("Subject: Hello\r\n\r\nHello")
|
|
@@ -354,19 +374,17 @@ module Mail
|
|
|
354
374
|
# m1 = Mail.new("Message-ID: <1234@test>\r\nSubject: Hello\r\n\r\nHello")
|
|
355
375
|
# m2 = Mail.new("Message-ID: <DIFFERENT@test>\r\nSubject: Hello\r\n\r\nHello")
|
|
356
376
|
# m1 == m2 #=> false
|
|
357
|
-
def ==(other)
|
|
377
|
+
def ==(other) # TODO could be more efficient
|
|
358
378
|
return false unless other.respond_to?(:encoded)
|
|
359
379
|
|
|
380
|
+
stamp = Mail::CommonDateField.normalize_datetime('')
|
|
381
|
+
# Note: must always dup the inputs so they are not altered by encoded
|
|
360
382
|
if self.message_id && other.message_id
|
|
361
|
-
|
|
383
|
+
dup.tap { |m| m.date ||= stamp }.encoded ==
|
|
384
|
+
other.dup.tap { |m| m.date ||= stamp }.encoded
|
|
362
385
|
else
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
self.message_id, other.message_id = '<temp@test>', '<temp@test>'
|
|
366
|
-
self.encoded == other.encoded
|
|
367
|
-
ensure
|
|
368
|
-
self.message_id, other.message_id = self_message_id, other_message_id
|
|
369
|
-
end
|
|
386
|
+
dup.tap { |m| m.message_id = '<temp@test>'; m.date ||= stamp }.encoded ==
|
|
387
|
+
other.dup.tap { |m| m.message_id = '<temp@test>'; m.date ||= stamp }.encoded
|
|
370
388
|
end
|
|
371
389
|
end
|
|
372
390
|
|
|
@@ -388,9 +406,9 @@ module Mail
|
|
|
388
406
|
end
|
|
389
407
|
|
|
390
408
|
# Sets the envelope from for the email
|
|
391
|
-
def set_envelope(
|
|
409
|
+
def set_envelope(val)
|
|
392
410
|
@raw_envelope = val
|
|
393
|
-
@envelope = Mail::Envelope.
|
|
411
|
+
@envelope = Mail::Envelope.parse(val) rescue nil
|
|
394
412
|
end
|
|
395
413
|
|
|
396
414
|
# The raw_envelope is the From mikel@test.lindsaar.net Mon May 2 16:07:05 2009
|
|
@@ -453,7 +471,7 @@ module Mail
|
|
|
453
471
|
# message.errors.size #=> 1
|
|
454
472
|
# message.errors.first[0] #=> "Content-Transfer-Encoding"
|
|
455
473
|
# message.errors.first[1] #=> "weirdo"
|
|
456
|
-
# message.errors.first[
|
|
474
|
+
# message.errors.first[2] #=> <The original error message exception>
|
|
457
475
|
#
|
|
458
476
|
# This is a good first defence on detecting spam by the way. Some spammers send
|
|
459
477
|
# invalid emails to try and get email parsers to give up parsing them.
|
|
@@ -1193,8 +1211,8 @@ module Mail
|
|
|
1193
1211
|
def default( sym, val = nil )
|
|
1194
1212
|
if val
|
|
1195
1213
|
header[sym] = val
|
|
1196
|
-
|
|
1197
|
-
|
|
1214
|
+
elsif field = header[sym]
|
|
1215
|
+
field.default
|
|
1198
1216
|
end
|
|
1199
1217
|
end
|
|
1200
1218
|
|
|
@@ -1240,14 +1258,13 @@ module Mail
|
|
|
1240
1258
|
def body(value = nil)
|
|
1241
1259
|
if value
|
|
1242
1260
|
self.body = value
|
|
1243
|
-
# add_encoding_to_body
|
|
1244
1261
|
else
|
|
1245
1262
|
process_body_raw if @body_raw
|
|
1246
1263
|
@body
|
|
1247
1264
|
end
|
|
1248
1265
|
end
|
|
1249
1266
|
|
|
1250
|
-
def body_encoding(value)
|
|
1267
|
+
def body_encoding(value = nil)
|
|
1251
1268
|
if value.nil?
|
|
1252
1269
|
body.encoding
|
|
1253
1270
|
else
|
|
@@ -1256,7 +1273,7 @@ module Mail
|
|
|
1256
1273
|
end
|
|
1257
1274
|
|
|
1258
1275
|
def body_encoding=(value)
|
|
1259
|
-
|
|
1276
|
+
body.encoding = value
|
|
1260
1277
|
end
|
|
1261
1278
|
|
|
1262
1279
|
# Returns the list of addresses this message should be sent to by
|
|
@@ -1306,7 +1323,7 @@ module Mail
|
|
|
1306
1323
|
def []=(name, value)
|
|
1307
1324
|
if name.to_s == 'body'
|
|
1308
1325
|
self.body = value
|
|
1309
|
-
elsif
|
|
1326
|
+
elsif /content[-_]type/i.match?(name.to_s)
|
|
1310
1327
|
header[name] = value
|
|
1311
1328
|
elsif name.to_s == 'charset'
|
|
1312
1329
|
self.charset = value
|
|
@@ -1322,7 +1339,7 @@ module Mail
|
|
|
1322
1339
|
# mail['foo'] = '1234'
|
|
1323
1340
|
# mail['foo'].to_s #=> '1234'
|
|
1324
1341
|
def [](name)
|
|
1325
|
-
header[underscoreize(name)]
|
|
1342
|
+
header[Utilities.underscoreize(name)]
|
|
1326
1343
|
end
|
|
1327
1344
|
|
|
1328
1345
|
# Method Missing in this implementation allows you to set any of the
|
|
@@ -1368,7 +1385,7 @@ module Mail
|
|
|
1368
1385
|
#:nodoc:
|
|
1369
1386
|
# Only take the structured fields, as we could take _anything_ really
|
|
1370
1387
|
# as it could become an optional field... "but therin lies the dark side"
|
|
1371
|
-
field_name = underscoreize(name).chomp("=")
|
|
1388
|
+
field_name = Utilities.underscoreize(name).chomp("=")
|
|
1372
1389
|
if Mail::Field::KNOWN_FIELDS.include?(field_name)
|
|
1373
1390
|
if args.empty?
|
|
1374
1391
|
header[field_name]
|
|
@@ -1399,7 +1416,7 @@ module Mail
|
|
|
1399
1416
|
header.has_date?
|
|
1400
1417
|
end
|
|
1401
1418
|
|
|
1402
|
-
# Returns true if the message has a
|
|
1419
|
+
# Returns true if the message has a MIME-Version field, the field may or may
|
|
1403
1420
|
# not have a value, but the field exists or not.
|
|
1404
1421
|
def has_mime_version?
|
|
1405
1422
|
header.has_mime_version?
|
|
@@ -1419,11 +1436,6 @@ module Mail
|
|
|
1419
1436
|
header[:content_transfer_encoding] && Utilities.blank?(header[:content_transfer_encoding].errors)
|
|
1420
1437
|
end
|
|
1421
1438
|
|
|
1422
|
-
def has_transfer_encoding? # :nodoc:
|
|
1423
|
-
STDERR.puts(":has_transfer_encoding? is deprecated in Mail 1.4.3. Please use has_content_transfer_encoding?\n#{caller}")
|
|
1424
|
-
has_content_transfer_encoding?
|
|
1425
|
-
end
|
|
1426
|
-
|
|
1427
1439
|
# Creates a new empty Message-ID field and inserts it in the correct order
|
|
1428
1440
|
# into the Header. The MessageIdField object will automatically generate
|
|
1429
1441
|
# a unique message ID if you try and encode it or output it to_s without
|
|
@@ -1468,35 +1480,19 @@ module Mail
|
|
|
1468
1480
|
if !body.empty?
|
|
1469
1481
|
# Only give a warning if this isn't an attachment, has non US-ASCII and the user
|
|
1470
1482
|
# has not specified an encoding explicitly.
|
|
1471
|
-
if @defaulted_charset && body.raw_source.
|
|
1483
|
+
if @defaulted_charset && !body.raw_source.ascii_only? && !self.attachment?
|
|
1472
1484
|
warning = "Non US-ASCII detected and no charset defined.\nDefaulting to UTF-8, set your own if this is incorrect.\n"
|
|
1473
|
-
|
|
1485
|
+
warn(warning)
|
|
1486
|
+
end
|
|
1487
|
+
if @charset
|
|
1488
|
+
header[:content_type].parameters['charset'] = @charset
|
|
1474
1489
|
end
|
|
1475
|
-
header[:content_type].parameters['charset'] = @charset
|
|
1476
1490
|
end
|
|
1477
1491
|
end
|
|
1478
1492
|
|
|
1479
1493
|
# Adds a content transfer encoding
|
|
1480
|
-
#
|
|
1481
|
-
# Otherwise raises a warning
|
|
1482
1494
|
def add_content_transfer_encoding
|
|
1483
|
-
|
|
1484
|
-
header[:content_transfer_encoding] = '7bit'
|
|
1485
|
-
else
|
|
1486
|
-
warning = "Non US-ASCII detected and no content-transfer-encoding defined.\nDefaulting to 8bit, set your own if this is incorrect.\n"
|
|
1487
|
-
STDERR.puts(warning)
|
|
1488
|
-
header[:content_transfer_encoding] = '8bit'
|
|
1489
|
-
end
|
|
1490
|
-
end
|
|
1491
|
-
|
|
1492
|
-
def add_transfer_encoding # :nodoc:
|
|
1493
|
-
STDERR.puts(":add_transfer_encoding is deprecated in Mail 1.4.3. Please use add_content_transfer_encoding\n#{caller}")
|
|
1494
|
-
add_content_transfer_encoding
|
|
1495
|
-
end
|
|
1496
|
-
|
|
1497
|
-
def transfer_encoding # :nodoc:
|
|
1498
|
-
STDERR.puts(":transfer_encoding is deprecated in Mail 1.4.3. Please use content_transfer_encoding\n#{caller}")
|
|
1499
|
-
content_transfer_encoding
|
|
1495
|
+
header[:content_transfer_encoding] ||= body.default_encoding
|
|
1500
1496
|
end
|
|
1501
1497
|
|
|
1502
1498
|
# Returns the MIME media type of part we are on, this is taken from the content-type header
|
|
@@ -1504,15 +1500,10 @@ module Mail
|
|
|
1504
1500
|
has_content_type? ? header[:content_type].string : nil rescue nil
|
|
1505
1501
|
end
|
|
1506
1502
|
|
|
1507
|
-
def message_content_type
|
|
1508
|
-
STDERR.puts(":message_content_type is deprecated in Mail 1.4.3. Please use mime_type\n#{caller}")
|
|
1509
|
-
mime_type
|
|
1510
|
-
end
|
|
1511
|
-
|
|
1512
1503
|
# Returns the character set defined in the content type field
|
|
1513
1504
|
def charset
|
|
1514
1505
|
if @header
|
|
1515
|
-
has_content_type? ? content_type_parameters['charset'] : @charset
|
|
1506
|
+
has_content_type? && !multipart? ? content_type_parameters['charset'] : @charset
|
|
1516
1507
|
else
|
|
1517
1508
|
@charset
|
|
1518
1509
|
end
|
|
@@ -1535,12 +1526,6 @@ module Mail
|
|
|
1535
1526
|
has_content_type? ? header[:content_type].sub_type : nil rescue nil
|
|
1536
1527
|
end
|
|
1537
1528
|
|
|
1538
|
-
# Returns the content type parameters
|
|
1539
|
-
def mime_parameters
|
|
1540
|
-
STDERR.puts(':mime_parameters is deprecated in Mail 1.4.3, please use :content_type_parameters instead')
|
|
1541
|
-
content_type_parameters
|
|
1542
|
-
end
|
|
1543
|
-
|
|
1544
1529
|
# Returns the content type parameters
|
|
1545
1530
|
def content_type_parameters
|
|
1546
1531
|
has_content_type? ? header[:content_type].parameters : nil rescue nil
|
|
@@ -1548,22 +1533,29 @@ module Mail
|
|
|
1548
1533
|
|
|
1549
1534
|
# Returns true if the message is multipart
|
|
1550
1535
|
def multipart?
|
|
1551
|
-
has_content_type? ?
|
|
1536
|
+
has_content_type? ? /^multipart$/i.match?(main_type) : false
|
|
1552
1537
|
end
|
|
1553
1538
|
|
|
1554
1539
|
# Returns true if the message is a multipart/report
|
|
1555
1540
|
def multipart_report?
|
|
1556
|
-
multipart? &&
|
|
1541
|
+
multipart? && /^report$/i.match?(sub_type)
|
|
1557
1542
|
end
|
|
1558
1543
|
|
|
1559
1544
|
# Returns true if the message is a multipart/report; report-type=delivery-status;
|
|
1560
1545
|
def delivery_status_report?
|
|
1561
|
-
multipart_report? && content_type_parameters['report-type']
|
|
1546
|
+
multipart_report? && /^delivery-status$/i.match?(content_type_parameters['report-type'])
|
|
1562
1547
|
end
|
|
1563
1548
|
|
|
1564
1549
|
# returns the part in a multipart/report email that has the content-type delivery-status
|
|
1565
1550
|
def delivery_status_part
|
|
1566
|
-
|
|
1551
|
+
unless defined? @delivery_status_part
|
|
1552
|
+
@delivery_status_part =
|
|
1553
|
+
if delivery_status_report?
|
|
1554
|
+
parts.detect(&:delivery_status_report_part?)
|
|
1555
|
+
end
|
|
1556
|
+
end
|
|
1557
|
+
|
|
1558
|
+
@delivery_status_part
|
|
1567
1559
|
end
|
|
1568
1560
|
|
|
1569
1561
|
def bounced?
|
|
@@ -1778,19 +1770,26 @@ module Mail
|
|
|
1778
1770
|
else
|
|
1779
1771
|
basename = values[:filename]
|
|
1780
1772
|
filedata = values
|
|
1781
|
-
unless filedata[:content]
|
|
1782
|
-
filedata = values.merge(:content=>File.open(values[:filename], 'rb') { |f| f.read })
|
|
1783
|
-
end
|
|
1784
1773
|
end
|
|
1785
1774
|
self.attachments[basename] = filedata
|
|
1786
1775
|
end
|
|
1787
1776
|
|
|
1777
|
+
MULTIPART_CONVERSION_CONTENT_FIELDS = [ :content_description, :content_disposition, :content_transfer_encoding, :content_type ]
|
|
1778
|
+
private_constant :MULTIPART_CONVERSION_CONTENT_FIELDS if respond_to?(:private_constant)
|
|
1779
|
+
|
|
1788
1780
|
def convert_to_multipart
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1781
|
+
text_part = Mail::Part.new(:content_type => 'text/plain;', :body => body.decoded)
|
|
1782
|
+
|
|
1783
|
+
MULTIPART_CONVERSION_CONTENT_FIELDS.each do |field_name|
|
|
1784
|
+
if value = send(field_name)
|
|
1785
|
+
writer = :"#{field_name}="
|
|
1786
|
+
text_part.send writer, value
|
|
1787
|
+
send writer, nil
|
|
1788
|
+
end
|
|
1789
|
+
end
|
|
1793
1790
|
text_part.charset = charset unless @defaulted_charset
|
|
1791
|
+
|
|
1792
|
+
self.body = ''
|
|
1794
1793
|
self.body << text_part
|
|
1795
1794
|
end
|
|
1796
1795
|
|
|
@@ -1798,7 +1797,6 @@ module Mail
|
|
|
1798
1797
|
# ready to send
|
|
1799
1798
|
def ready_to_send!
|
|
1800
1799
|
identify_and_set_transfer_encoding
|
|
1801
|
-
parts.sort!([ "text/plain", "text/enriched", "text/html", "multipart/alternative" ])
|
|
1802
1800
|
parts.each do |part|
|
|
1803
1801
|
part.transport_encoding = transport_encoding
|
|
1804
1802
|
part.ready_to_send!
|
|
@@ -1806,11 +1804,6 @@ module Mail
|
|
|
1806
1804
|
add_required_fields
|
|
1807
1805
|
end
|
|
1808
1806
|
|
|
1809
|
-
def encode!
|
|
1810
|
-
STDERR.puts("Deprecated in 1.1.0 in favour of :ready_to_send! as it is less confusing with encoding and decoding.")
|
|
1811
|
-
ready_to_send!
|
|
1812
|
-
end
|
|
1813
|
-
|
|
1814
1807
|
# Outputs an encoded string representation of the mail message including
|
|
1815
1808
|
# all headers, attachments, etc. This is an encoded email in US-ASCII,
|
|
1816
1809
|
# so it is able to be directly sent to an email server.
|
|
@@ -1823,16 +1816,13 @@ module Mail
|
|
|
1823
1816
|
end
|
|
1824
1817
|
|
|
1825
1818
|
def without_attachments!
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
parts.delete_if { |p| p.attachment? }
|
|
1829
|
-
body_raw = if parts.empty?
|
|
1830
|
-
''
|
|
1831
|
-
else
|
|
1832
|
-
body.encoded
|
|
1833
|
-
end
|
|
1819
|
+
if has_attachments?
|
|
1820
|
+
parts.delete_attachments
|
|
1834
1821
|
|
|
1835
|
-
|
|
1822
|
+
reencoded = parts.empty? ? '' : body.encoded(content_transfer_encoding)
|
|
1823
|
+
@body = nil # So the new parts won't be added to the existing body
|
|
1824
|
+
self.body = reencoded
|
|
1825
|
+
end
|
|
1836
1826
|
|
|
1837
1827
|
self
|
|
1838
1828
|
end
|
|
@@ -1858,7 +1848,7 @@ module Mail
|
|
|
1858
1848
|
end
|
|
1859
1849
|
|
|
1860
1850
|
def self.from_yaml(str)
|
|
1861
|
-
hash = YAML.load(str)
|
|
1851
|
+
hash = Mail::YAML.load(str)
|
|
1862
1852
|
m = self.new(:headers => hash['headers'])
|
|
1863
1853
|
hash.delete('headers')
|
|
1864
1854
|
hash.each do |k,v|
|
|
@@ -1872,7 +1862,7 @@ module Mail
|
|
|
1872
1862
|
m.transport_encoding(v)
|
|
1873
1863
|
when k == 'multipart_body'
|
|
1874
1864
|
v.map {|part| m.add_part Mail::Part.from_yaml(part) }
|
|
1875
|
-
when k
|
|
1865
|
+
when k.start_with?('@')
|
|
1876
1866
|
m.instance_variable_set(k.to_sym, v)
|
|
1877
1867
|
end
|
|
1878
1868
|
end
|
|
@@ -1891,6 +1881,15 @@ module Mail
|
|
|
1891
1881
|
"#<#{self.class}:#{self.object_id}, Multipart: #{multipart?}, Headers: #{header.field_summary}>"
|
|
1892
1882
|
end
|
|
1893
1883
|
|
|
1884
|
+
def inspect_structure
|
|
1885
|
+
inspect +
|
|
1886
|
+
if self.multipart?
|
|
1887
|
+
"\n" + parts.inspect_structure
|
|
1888
|
+
else
|
|
1889
|
+
''
|
|
1890
|
+
end
|
|
1891
|
+
end
|
|
1892
|
+
|
|
1894
1893
|
def decoded
|
|
1895
1894
|
case
|
|
1896
1895
|
when self.text?
|
|
@@ -1900,7 +1899,7 @@ module Mail
|
|
|
1900
1899
|
when !self.multipart?
|
|
1901
1900
|
body.decoded
|
|
1902
1901
|
else
|
|
1903
|
-
raise NoMethodError, '
|
|
1902
|
+
raise NoMethodError, 'This message cannot be decoded as _entire_ message, try calling #decoded on the various fields and body or parts if it is a multipart message.'
|
|
1904
1903
|
end
|
|
1905
1904
|
end
|
|
1906
1905
|
|
|
@@ -1970,12 +1969,12 @@ module Mail
|
|
|
1970
1969
|
end
|
|
1971
1970
|
|
|
1972
1971
|
def text?
|
|
1973
|
-
has_content_type? ?
|
|
1972
|
+
has_content_type? ? /^text$/i.match?(main_type) : false
|
|
1974
1973
|
end
|
|
1975
1974
|
|
|
1976
1975
|
private
|
|
1977
1976
|
|
|
1978
|
-
HEADER_SEPARATOR = /#{
|
|
1977
|
+
HEADER_SEPARATOR = /#{Constants::LAX_CRLF}#{Constants::LAX_CRLF}/
|
|
1979
1978
|
|
|
1980
1979
|
# 2.1. General Description
|
|
1981
1980
|
# A message consists of header fields (collectively called "the header
|
|
@@ -1984,9 +1983,6 @@ module Mail
|
|
|
1984
1983
|
# this standard. The body is simply a sequence of characters that
|
|
1985
1984
|
# follows the header and is separated from the header by an empty line
|
|
1986
1985
|
# (i.e., a line with nothing preceding the CRLF).
|
|
1987
|
-
#
|
|
1988
|
-
# Additionally, I allow for the case where someone might have put whitespace
|
|
1989
|
-
# on the "gap line"
|
|
1990
1986
|
def parse_message
|
|
1991
1987
|
header_part, body_part = raw_source.lstrip.split(HEADER_SEPARATOR, 2)
|
|
1992
1988
|
self.header = header_part
|
|
@@ -1994,8 +1990,7 @@ module Mail
|
|
|
1994
1990
|
end
|
|
1995
1991
|
|
|
1996
1992
|
def raw_source=(value)
|
|
1997
|
-
|
|
1998
|
-
@raw_source = ::Mail::Utilities.to_crlf(value)
|
|
1993
|
+
@raw_source = value
|
|
1999
1994
|
end
|
|
2000
1995
|
|
|
2001
1996
|
# see comments to body=. We take data and process it lazily
|
|
@@ -2007,11 +2002,9 @@ module Mail
|
|
|
2007
2002
|
@body_raw = nil
|
|
2008
2003
|
add_encoding_to_body
|
|
2009
2004
|
when @body && @body.multipart?
|
|
2010
|
-
|
|
2011
|
-
add_encoding_to_body
|
|
2005
|
+
self.text_part = value
|
|
2012
2006
|
else
|
|
2013
2007
|
@body_raw = value
|
|
2014
|
-
# process_body_raw
|
|
2015
2008
|
end
|
|
2016
2009
|
end
|
|
2017
2010
|
|
|
@@ -2026,7 +2019,7 @@ module Mail
|
|
|
2026
2019
|
|
|
2027
2020
|
def set_envelope_header
|
|
2028
2021
|
raw_string = raw_source.to_s
|
|
2029
|
-
if match_data =
|
|
2022
|
+
if match_data = raw_string.match(/\AFrom\s+([^:\s]#{Constants::TEXT}*)#{Constants::LAX_CRLF}/m)
|
|
2030
2023
|
set_envelope(match_data[1])
|
|
2031
2024
|
self.raw_source = raw_string.sub(match_data[0], "")
|
|
2032
2025
|
end
|
|
@@ -2036,6 +2029,13 @@ module Mail
|
|
|
2036
2029
|
body.split!(boundary)
|
|
2037
2030
|
end
|
|
2038
2031
|
|
|
2032
|
+
def allowed_encodings
|
|
2033
|
+
case mime_type
|
|
2034
|
+
when 'message/rfc822'
|
|
2035
|
+
[Encodings::SevenBit, Encodings::EightBit, Encodings::Binary]
|
|
2036
|
+
end
|
|
2037
|
+
end
|
|
2038
|
+
|
|
2039
2039
|
def add_encoding_to_body
|
|
2040
2040
|
if has_content_transfer_encoding?
|
|
2041
2041
|
@body.encoding = content_transfer_encoding
|
|
@@ -2043,11 +2043,13 @@ module Mail
|
|
|
2043
2043
|
end
|
|
2044
2044
|
|
|
2045
2045
|
def identify_and_set_transfer_encoding
|
|
2046
|
-
|
|
2047
|
-
|
|
2046
|
+
if body
|
|
2047
|
+
if body.multipart?
|
|
2048
|
+
self.content_transfer_encoding = @transport_encoding
|
|
2048
2049
|
else
|
|
2049
|
-
|
|
2050
|
+
self.content_transfer_encoding = body.negotiate_best_encoding(@transport_encoding, allowed_encodings).to_s
|
|
2050
2051
|
end
|
|
2052
|
+
end
|
|
2051
2053
|
end
|
|
2052
2054
|
|
|
2053
2055
|
def add_required_fields
|
|
@@ -2066,7 +2068,6 @@ module Mail
|
|
|
2066
2068
|
|
|
2067
2069
|
def add_multipart_alternate_header
|
|
2068
2070
|
header['content-type'] = ContentTypeField.with_boundary('multipart/alternative').value
|
|
2069
|
-
header['content_type'].parameters[:charset] = @charset
|
|
2070
2071
|
body.boundary = boundary
|
|
2071
2072
|
end
|
|
2072
2073
|
|
|
@@ -2074,7 +2075,6 @@ module Mail
|
|
|
2074
2075
|
unless body.boundary && boundary
|
|
2075
2076
|
header['content-type'] = 'multipart/mixed' unless header['content-type']
|
|
2076
2077
|
header['content-type'].parameters[:boundary] = ContentTypeField.generate_boundary
|
|
2077
|
-
header['content_type'].parameters[:charset] = @charset
|
|
2078
2078
|
body.boundary = boundary
|
|
2079
2079
|
end
|
|
2080
2080
|
end
|
|
@@ -2082,7 +2082,6 @@ module Mail
|
|
|
2082
2082
|
def add_multipart_mixed_header
|
|
2083
2083
|
unless header['content-type']
|
|
2084
2084
|
header['content-type'] = ContentTypeField.with_boundary('multipart/mixed').value
|
|
2085
|
-
header['content_type'].parameters[:charset] = @charset
|
|
2086
2085
|
body.boundary = boundary
|
|
2087
2086
|
end
|
|
2088
2087
|
end
|
|
@@ -2099,7 +2098,7 @@ module Mail
|
|
|
2099
2098
|
body_content = nil
|
|
2100
2099
|
|
|
2101
2100
|
passed_in_options.each_pair do |k,v|
|
|
2102
|
-
k = underscoreize(k).to_sym if k.class == String
|
|
2101
|
+
k = Utilities.underscoreize(k).to_sym if k.class == String
|
|
2103
2102
|
if k == :headers
|
|
2104
2103
|
self.headers(v)
|
|
2105
2104
|
elsif k == :body
|
|
@@ -2130,10 +2129,10 @@ module Mail
|
|
|
2130
2129
|
content_disp_name = header[:content_disposition].filename rescue nil
|
|
2131
2130
|
content_loc_name = header[:content_location].location rescue nil
|
|
2132
2131
|
case
|
|
2133
|
-
when content_type && content_type_name
|
|
2134
|
-
filename = content_type_name
|
|
2135
2132
|
when content_disposition && content_disp_name
|
|
2136
2133
|
filename = content_disp_name
|
|
2134
|
+
when content_type && content_type_name
|
|
2135
|
+
filename = content_type_name
|
|
2137
2136
|
when content_location && content_loc_name
|
|
2138
2137
|
filename = content_loc_name
|
|
2139
2138
|
else
|