mail 2.8.0 → 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 +4 -4
- data/README.md +91 -32
- data/lib/mail/attachments_list.rb +3 -1
- data/lib/mail/body.rb +28 -28
- data/lib/mail/encodings/quoted_printable.rb +1 -1
- data/lib/mail/encodings/unix_to_unix.rb +1 -1
- data/lib/mail/encodings.rb +2 -2
- data/lib/mail/field.rb +65 -35
- data/lib/mail/field_list.rb +1 -1
- data/lib/mail/fields/bcc_field.rb +0 -1
- data/lib/mail/fields/cc_field.rb +0 -1
- data/lib/mail/fields/comments_field.rb +0 -1
- data/lib/mail/fields/common_address_field.rb +9 -17
- data/lib/mail/fields/common_date_field.rb +0 -2
- data/lib/mail/fields/common_message_id_field.rb +0 -1
- data/lib/mail/fields/content_description_field.rb +0 -1
- data/lib/mail/fields/content_disposition_field.rb +0 -2
- data/lib/mail/fields/content_id_field.rb +0 -1
- data/lib/mail/fields/content_location_field.rb +0 -1
- data/lib/mail/fields/content_transfer_encoding_field.rb +0 -1
- data/lib/mail/fields/content_type_field.rb +5 -6
- data/lib/mail/fields/date_field.rb +0 -1
- data/lib/mail/fields/from_field.rb +0 -1
- data/lib/mail/fields/in_reply_to_field.rb +0 -1
- data/lib/mail/fields/keywords_field.rb +0 -1
- data/lib/mail/fields/message_id_field.rb +0 -1
- data/lib/mail/fields/mime_version_field.rb +1 -2
- data/lib/mail/fields/named_structured_field.rb +0 -1
- data/lib/mail/fields/named_unstructured_field.rb +0 -1
- data/lib/mail/fields/optional_field.rb +0 -1
- data/lib/mail/fields/received_field.rb +0 -1
- data/lib/mail/fields/references_field.rb +0 -1
- data/lib/mail/fields/reply_to_field.rb +0 -1
- data/lib/mail/fields/resent_bcc_field.rb +0 -1
- data/lib/mail/fields/resent_cc_field.rb +0 -1
- data/lib/mail/fields/resent_date_field.rb +0 -1
- data/lib/mail/fields/resent_from_field.rb +0 -1
- data/lib/mail/fields/resent_message_id_field.rb +0 -1
- data/lib/mail/fields/resent_sender_field.rb +0 -1
- data/lib/mail/fields/resent_to_field.rb +0 -1
- data/lib/mail/fields/return_path_field.rb +0 -1
- data/lib/mail/fields/sender_field.rb +0 -1
- data/lib/mail/fields/structured_field.rb +0 -1
- data/lib/mail/fields/subject_field.rb +0 -1
- data/lib/mail/fields/to_field.rb +0 -1
- data/lib/mail/fields/unstructured_field.rb +0 -1
- data/lib/mail/fields.rb +9 -0
- data/lib/mail/header.rb +1 -1
- data/lib/mail/mail.rb +32 -27
- data/lib/mail/message.rb +23 -20
- data/lib/mail/multibyte/chars.rb +1 -1
- data/lib/mail/multibyte/unicode.rb +1 -1
- data/lib/mail/network/delivery_methods/file_delivery.rb +2 -2
- data/lib/mail/network/delivery_methods/smtp.rb +77 -42
- data/lib/mail/network/delivery_methods/smtp_connection.rb +7 -7
- data/lib/mail/network/delivery_methods/test_mailer.rb +4 -4
- data/lib/mail/network/retriever_methods/base.rb +5 -5
- data/lib/mail/network/retriever_methods/imap.rb +6 -3
- data/lib/mail/network/retriever_methods/pop3.rb +20 -20
- data/lib/mail/parsers/address_lists_parser.rb +8 -5
- data/lib/mail/parsers/address_lists_parser.rl +4 -0
- data/lib/mail/parsers/content_disposition_parser.rb +15 -12
- data/lib/mail/parsers/content_disposition_parser.rl +4 -0
- data/lib/mail/parsers/content_location_parser.rb +9 -6
- data/lib/mail/parsers/content_location_parser.rl +5 -1
- data/lib/mail/parsers/content_transfer_encoding_parser.rb +8 -5
- data/lib/mail/parsers/content_transfer_encoding_parser.rl +4 -0
- data/lib/mail/parsers/content_type_parser.rb +15 -12
- data/lib/mail/parsers/content_type_parser.rl +4 -0
- data/lib/mail/parsers/date_time_parser.rb +8 -5
- data/lib/mail/parsers/date_time_parser.rl +4 -0
- data/lib/mail/parsers/envelope_from_parser.rb +8 -5
- data/lib/mail/parsers/envelope_from_parser.rl +4 -0
- data/lib/mail/parsers/message_ids_parser.rb +8 -5
- data/lib/mail/parsers/message_ids_parser.rl +4 -0
- data/lib/mail/parsers/mime_version_parser.rb +8 -5
- data/lib/mail/parsers/mime_version_parser.rl +4 -0
- data/lib/mail/parsers/phrase_lists_parser.rb +8 -5
- data/lib/mail/parsers/phrase_lists_parser.rl +4 -0
- data/lib/mail/parsers/received_parser.rb +8 -5
- data/lib/mail/parsers/received_parser.rl +4 -0
- data/lib/mail/part.rb +19 -19
- data/lib/mail/smtp_envelope.rb +1 -1
- data/lib/mail/utilities.rb +11 -7
- data/lib/mail/version.rb +1 -1
- data/lib/mail.rb +2 -5
- metadata +17 -4
- data/lib/mail/check_delivery_params.rb +0 -65
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 19bd6b0f4442e909c23a9b7da4aecd758bc7f13f49f55b0d38cbcea5d18a91bf
|
|
4
|
+
data.tar.gz: 30187e6fef5ff7d5aaa6e1608bac3f74748946b6aa84f63bc0152b14f8ec0f70
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d0fca43599584febff0aee7cc250a9280005080a9274024fa011b99ab27e4d40ebf72161c60d7115641d844d560f34b87e07994b485c6c0ae2cbd102cd04b11
|
|
7
|
+
data.tar.gz: 47735a46f1117a0d9709a3b72db5030ea71c645418a60b8fb62637777c9cdd687079fca33f77dfc4388aa5f8d4136768a555890d1f88768b351b81aaea9ab486
|
data/README.md
CHANGED
|
@@ -42,12 +42,26 @@ our documentation, add new features—up to you! Thank you for pitching in.
|
|
|
42
42
|
* [Encodings](#encodings)
|
|
43
43
|
* [Contributing](#contributing)
|
|
44
44
|
* [Usage](#usage)
|
|
45
|
-
* [Excerpts from TREC
|
|
45
|
+
* [Excerpts from TREC Spam Corpus 2005](#excerpts-from-trec-spam-corpus-2005)
|
|
46
46
|
* [License](#license)
|
|
47
47
|
|
|
48
48
|
## Compatibility
|
|
49
49
|
|
|
50
|
-
Mail
|
|
50
|
+
Mail is tested against:
|
|
51
|
+
|
|
52
|
+
* Ruby: 2.5
|
|
53
|
+
* Ruby: 2.6
|
|
54
|
+
* Ruby: 2.7
|
|
55
|
+
* Ruby: 3.0
|
|
56
|
+
* Ruby: 3.1
|
|
57
|
+
* Ruby: 3.2
|
|
58
|
+
* JRuby: 9.2
|
|
59
|
+
* JRuby: 9.3
|
|
60
|
+
* JRuby: 9.4
|
|
61
|
+
* JRuby: stable
|
|
62
|
+
* JRuby: head
|
|
63
|
+
* Truffleruby: stable
|
|
64
|
+
* Truffleruby: head
|
|
51
65
|
|
|
52
66
|
As new versions of Ruby are released, Mail will be compatible with support for the "preview" and all "normal maintenance", "security maintenance" and the two most recent "end of life" versions listed at the [Ruby Maintenance Branches](https://www.ruby-lang.org/en/downloads/branches/) page. Pull requests to assist in adding support for new preview releases are more than welcome.
|
|
53
67
|
|
|
@@ -403,18 +417,21 @@ simple as possible.... (asking a lot from a mail library)
|
|
|
403
417
|
|
|
404
418
|
```ruby
|
|
405
419
|
mail = Mail.deliver do
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
420
|
+
part :content_type => "multipart/mixed" do |p1|
|
|
421
|
+
p1.part :content_type => "multipart/related" do |p2|
|
|
422
|
+
p2.part :content_type => "multipart/alternative",
|
|
423
|
+
:content_disposition => "inline" do |p3|
|
|
424
|
+
p3.part :content_type => "text/plain; charset=utf-8",
|
|
425
|
+
:body => "Here is the attachment you wanted\n"
|
|
426
|
+
p3.part :content_type => "text/html; charset=utf-8",
|
|
427
|
+
:body => "<h1>Funky Title</h1><p>Here is the attachment you wanted</p>\n"
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
add_file '/path/to/myfile.pdf'
|
|
417
431
|
end
|
|
432
|
+
from "Mikel Lindsaar <mikel@test.lindsaar.net.au>"
|
|
433
|
+
to "nicolas@test.lindsaar.net.au"
|
|
434
|
+
subject "First multipart email sent with Mail"
|
|
418
435
|
end
|
|
419
436
|
```
|
|
420
437
|
|
|
@@ -425,34 +442,76 @@ so desire...
|
|
|
425
442
|
```
|
|
426
443
|
puts mail.to_s #=>
|
|
427
444
|
|
|
428
|
-
|
|
445
|
+
Date: Tue, 26 Apr 2022 20:12:07 +0200
|
|
429
446
|
From: Mikel Lindsaar <mikel@test.lindsaar.net.au>
|
|
447
|
+
To: nicolas@test.lindsaar.net.au
|
|
448
|
+
Message-ID: <626835f736e19_10873fdfa3c2ffd4947a3@sender.at.mail>
|
|
430
449
|
Subject: First multipart email sent with Mail
|
|
450
|
+
MIME-Version: 1.0
|
|
451
|
+
Content-Type: multipart/mixed;
|
|
452
|
+
boundary=\"--==_mimepart_626835f733867_10873fdfa3c2ffd494636\";
|
|
453
|
+
charset=UTF-8
|
|
454
|
+
Content-Transfer-Encoding: 7bit
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
----==_mimepart_626835f733867_10873fdfa3c2ffd494636
|
|
458
|
+
Content-Type: multipart/mixed;
|
|
459
|
+
boundary=\"--==_mimepart_626835f73382a_10873fdfa3c2ffd494518\";
|
|
460
|
+
charset=UTF-8
|
|
461
|
+
Content-Transfer-Encoding: 7bit
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
----==_mimepart_626835f73382a_10873fdfa3c2ffd494518
|
|
465
|
+
Content-Type: multipart/related;
|
|
466
|
+
boundary=\"--==_mimepart_626835f7337f5_10873fdfa3c2ffd494438\";
|
|
467
|
+
charset=UTF-8
|
|
468
|
+
Content-Transfer-Encoding: 7bit
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
----==_mimepart_626835f7337f5_10873fdfa3c2ffd494438
|
|
431
472
|
Content-Type: multipart/alternative;
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
473
|
+
boundary=\"--==_mimepart_626835f733702_10873fdfa3c2ffd494376\";
|
|
474
|
+
charset=UTF-8
|
|
475
|
+
Content-Transfer-Encoding: 7bit
|
|
476
|
+
Content-Disposition: inline
|
|
477
|
+
Content-ID: <626835f738373_10873fdfa3c2ffd49488b@sender.at.mail>
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
----==_mimepart_626835f733702_10873fdfa3c2ffd494376
|
|
481
|
+
Content-Type: text/plain;
|
|
482
|
+
charset=utf-8
|
|
436
483
|
Content-Transfer-Encoding: 7bit
|
|
437
484
|
|
|
485
|
+
Here is the attachment you wanted
|
|
438
486
|
|
|
439
|
-
----==
|
|
440
|
-
Content-
|
|
441
|
-
|
|
442
|
-
Mime-Version: 1.0
|
|
443
|
-
Content-Type: text/plain
|
|
487
|
+
----==_mimepart_626835f733702_10873fdfa3c2ffd494376
|
|
488
|
+
Content-Type: text/html;
|
|
489
|
+
charset=utf-8
|
|
444
490
|
Content-Transfer-Encoding: 7bit
|
|
445
491
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
492
|
+
<h1>Funky Title</h1><p>Here is the attachment you wanted</p>
|
|
493
|
+
|
|
494
|
+
----==_mimepart_626835f733702_10873fdfa3c2ffd494376--
|
|
495
|
+
|
|
496
|
+
----==_mimepart_626835f7337f5_10873fdfa3c2ffd494438--
|
|
497
|
+
|
|
498
|
+
----==_mimepart_626835f73382a_10873fdfa3c2ffd494518--
|
|
499
|
+
|
|
500
|
+
----==_mimepart_626835f733867_10873fdfa3c2ffd494636
|
|
501
|
+
Content-Type: text/plain;
|
|
502
|
+
charset=UTF-8;
|
|
503
|
+
filename=myfile.txt
|
|
452
504
|
Content-Transfer-Encoding: 7bit
|
|
505
|
+
Content-Disposition: attachment;
|
|
506
|
+
filename=myfile.txt
|
|
507
|
+
Content-ID: <6
|
|
508
|
+
26835f7386ab_10873fdfa3c2ffd4949b8@sender.at.mail>
|
|
509
|
+
|
|
510
|
+
Hallo,
|
|
511
|
+
Test
|
|
512
|
+
End
|
|
453
513
|
|
|
454
|
-
|
|
455
|
-
----==_mimepart_4a914f0c911be_6f0f1ab8026659--
|
|
514
|
+
----==_mimepart_626835f733867_10873fdfa3c2ffd494636--
|
|
456
515
|
```
|
|
457
516
|
|
|
458
517
|
Mail inserts the content transfer encoding, the mime version,
|
|
@@ -602,7 +661,7 @@ Mail.defaults do
|
|
|
602
661
|
delivery_method :test # in practice you'd do this in spec_helper.rb
|
|
603
662
|
end
|
|
604
663
|
|
|
605
|
-
describe "sending an email" do
|
|
664
|
+
RSpec.describe "sending an email" do
|
|
606
665
|
include Mail::Matchers
|
|
607
666
|
|
|
608
667
|
before(:each) do
|
|
@@ -7,7 +7,9 @@ module Mail
|
|
|
7
7
|
@content_disposition_type = 'attachment'
|
|
8
8
|
parts_list.map { |p|
|
|
9
9
|
if p.mime_type == 'message/rfc822'
|
|
10
|
-
|
|
10
|
+
parts = []
|
|
11
|
+
parts << p if p.attachment?
|
|
12
|
+
parts.concat Mail.new(p.body.encoded).attachments
|
|
11
13
|
elsif p.parts.empty?
|
|
12
14
|
p if p.attachment?
|
|
13
15
|
else
|
data/lib/mail/body.rb
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
module Mail
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
# = Body
|
|
6
|
-
#
|
|
6
|
+
#
|
|
7
7
|
# The body is where the text of the email is stored. Mail treats the body
|
|
8
8
|
# as a single object. The body itself has no information about boundaries
|
|
9
9
|
# used in the MIME standard, it just looks at its content as either a single
|
|
10
10
|
# block of text, or (if it is a multipart message) as an array of blocks of text.
|
|
11
|
-
#
|
|
11
|
+
#
|
|
12
12
|
# A body has to be told to split itself up into a multipart message by calling
|
|
13
13
|
# #split with the correct boundary. This is because the body object has no way
|
|
14
14
|
# of knowing what the correct boundary is for itself (there could be many
|
|
15
15
|
# boundaries in a body in the case of a nested MIME text).
|
|
16
|
-
#
|
|
16
|
+
#
|
|
17
17
|
# Once split is called, Mail::Body will slice itself up on this boundary,
|
|
18
18
|
# assigning anything that appears before the first part to the preamble, and
|
|
19
19
|
# anything that appears after the closing boundary to the epilogue, then
|
|
20
20
|
# each part gets initialized into a Mail::Part object.
|
|
21
|
-
#
|
|
21
|
+
#
|
|
22
22
|
# The boundary that is used to split up the Body is also stored in the Body
|
|
23
|
-
# object for use on encoding itself back out to a string. You can
|
|
23
|
+
# object for use on encoding itself back out to a string. You can
|
|
24
24
|
# overwrite this if it needs to be changed.
|
|
25
|
-
#
|
|
25
|
+
#
|
|
26
26
|
# On encoding, the body will return the preamble, then each part joined by
|
|
27
27
|
# the boundary, followed by a closing boundary string and then the epilogue.
|
|
28
28
|
class Body
|
|
@@ -39,9 +39,9 @@ module Mail
|
|
|
39
39
|
else
|
|
40
40
|
# Do join first incase we have been given an Array in Ruby 1.9
|
|
41
41
|
if string.respond_to?(:join)
|
|
42
|
-
@raw_source =
|
|
42
|
+
@raw_source = string.join('')
|
|
43
43
|
elsif string.respond_to?(:to_s)
|
|
44
|
-
@raw_source =
|
|
44
|
+
@raw_source = string.to_s
|
|
45
45
|
else
|
|
46
46
|
raise "You can only assign a string or an object that responds_to? :join or :to_s to a body."
|
|
47
47
|
end
|
|
@@ -57,15 +57,15 @@ module Mail
|
|
|
57
57
|
|
|
58
58
|
# Matches this body with another body. Also matches the decoded value of this
|
|
59
59
|
# body with a string.
|
|
60
|
-
#
|
|
60
|
+
#
|
|
61
61
|
# Examples:
|
|
62
|
-
#
|
|
62
|
+
#
|
|
63
63
|
# body = Mail::Body.new('The body')
|
|
64
64
|
# body == body #=> true
|
|
65
|
-
#
|
|
65
|
+
#
|
|
66
66
|
# body = Mail::Body.new('The body')
|
|
67
67
|
# body == 'The body' #=> true
|
|
68
|
-
#
|
|
68
|
+
#
|
|
69
69
|
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
70
70
|
# body.encoding = 'base64'
|
|
71
71
|
# body == "The body" #=> true
|
|
@@ -76,28 +76,28 @@ module Mail
|
|
|
76
76
|
super
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
# Accepts a string and performs a regular expression against the decoded text
|
|
81
|
-
#
|
|
81
|
+
#
|
|
82
82
|
# Examples:
|
|
83
|
-
#
|
|
83
|
+
#
|
|
84
84
|
# body = Mail::Body.new('The body')
|
|
85
85
|
# body =~ /The/ #=> 0
|
|
86
|
-
#
|
|
86
|
+
#
|
|
87
87
|
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
88
88
|
# body.encoding = 'base64'
|
|
89
89
|
# body =~ /The/ #=> 0
|
|
90
90
|
def =~(regexp)
|
|
91
91
|
self.decoded =~ regexp
|
|
92
92
|
end
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
# Accepts a string and performs a regular expression against the decoded text
|
|
95
|
-
#
|
|
95
|
+
#
|
|
96
96
|
# Examples:
|
|
97
|
-
#
|
|
97
|
+
#
|
|
98
98
|
# body = Mail::Body.new('The body')
|
|
99
99
|
# body.match(/The/) #=> #<MatchData "The">
|
|
100
|
-
#
|
|
100
|
+
#
|
|
101
101
|
# body = Mail::Body.new("VGhlIGJvZHk=\n")
|
|
102
102
|
# body.encoding = 'base64'
|
|
103
103
|
# body.match(/The/) #=> #<MatchData "The">
|
|
@@ -125,7 +125,7 @@ module Mail
|
|
|
125
125
|
def set_sort_order(order)
|
|
126
126
|
@part_sort_order = order
|
|
127
127
|
end
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
# Allows you to sort the parts according to the default sort order, or the sort order you
|
|
130
130
|
# set with :set_sort_order.
|
|
131
131
|
#
|
|
@@ -137,7 +137,7 @@ module Mail
|
|
|
137
137
|
end
|
|
138
138
|
@parts.sort!(@part_sort_order)
|
|
139
139
|
end
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
def negotiate_best_encoding(message_encoding, allowed_encodings = nil)
|
|
142
142
|
Mail::Encodings::TransferEncoding.negotiate(message_encoding, encoding, raw_source, allowed_encodings)
|
|
143
143
|
end
|
|
@@ -164,7 +164,7 @@ module Mail
|
|
|
164
164
|
# Cannot decode, so skip normalization
|
|
165
165
|
raw_source
|
|
166
166
|
else
|
|
167
|
-
# Decode then encode to normalize and allow transforming
|
|
167
|
+
# Decode then encode to normalize and allow transforming
|
|
168
168
|
# from base64 to Q-P and vice versa
|
|
169
169
|
decoded = dec.decode(raw_source)
|
|
170
170
|
if defined?(Encoding) && charset && charset != "US-ASCII"
|
|
@@ -183,7 +183,7 @@ module Mail
|
|
|
183
183
|
Encodings.get_encoding(encoding).decode(raw_source)
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
|
-
|
|
186
|
+
|
|
187
187
|
def to_s
|
|
188
188
|
decoded
|
|
189
189
|
end
|
|
@@ -272,7 +272,7 @@ module Mail
|
|
|
272
272
|
parts_regex = /
|
|
273
273
|
(?: # non-capturing group
|
|
274
274
|
\A | # start of string OR
|
|
275
|
-
\r
|
|
275
|
+
\r?\n # line break with optional CR
|
|
276
276
|
)
|
|
277
277
|
(
|
|
278
278
|
--#{Regexp.escape(boundary || "")} # boundary delimiter
|
|
@@ -289,11 +289,11 @@ module Mail
|
|
|
289
289
|
end
|
|
290
290
|
parts.map(&:first)
|
|
291
291
|
end
|
|
292
|
-
|
|
292
|
+
|
|
293
293
|
def crlf_boundary
|
|
294
294
|
"\r\n--#{boundary}\r\n"
|
|
295
295
|
end
|
|
296
|
-
|
|
296
|
+
|
|
297
297
|
def end_boundary
|
|
298
298
|
"\r\n--#{boundary}--\r\n"
|
|
299
299
|
end
|
|
@@ -16,7 +16,7 @@ module Mail
|
|
|
16
16
|
# Decode the string from Quoted-Printable. Cope with hard line breaks
|
|
17
17
|
# that were incorrectly encoded as hex instead of literal CRLF.
|
|
18
18
|
def self.decode(str)
|
|
19
|
-
::Mail::Utilities.to_lf ::Mail::Utilities.to_crlf(str).gsub(/(?:=0D=0A|=0D|=0A)\r\n/, "\r\n").
|
|
19
|
+
::Mail::Utilities.to_lf ::Mail::Utilities.to_crlf(str).gsub(/(?:=0D=0A|=0D|=0A)\r\n/, "\r\n").unpack1("M*")
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def self.encode(str)
|
data/lib/mail/encodings.rb
CHANGED
|
@@ -72,7 +72,7 @@ module Mail
|
|
|
72
72
|
# Mail::Encodings.param_encode("This is fun") #=> "us-ascii'en'This%20is%20fun"
|
|
73
73
|
def Encodings.param_encode(str)
|
|
74
74
|
case
|
|
75
|
-
when str.ascii_only? && str
|
|
75
|
+
when str.ascii_only? && TOKEN_UNSAFE.match?(str)
|
|
76
76
|
%Q{"#{str}"}
|
|
77
77
|
when str.ascii_only?
|
|
78
78
|
str
|
|
@@ -121,7 +121,7 @@ module Mail
|
|
|
121
121
|
# String has to be of the format =?<encoding>?[QB]?<string>?=
|
|
122
122
|
def Encodings.value_decode(str)
|
|
123
123
|
# Optimization: If there's no encoded-words in the string, just return it
|
|
124
|
-
return str unless str
|
|
124
|
+
return str unless ENCODED_VALUE.match?(str)
|
|
125
125
|
|
|
126
126
|
lines = collapse_adjacent_encodings(str)
|
|
127
127
|
|
data/lib/mail/field.rb
CHANGED
|
@@ -36,40 +36,68 @@ module Mail
|
|
|
36
36
|
KNOWN_FIELDS = STRUCTURED_FIELDS + ['comments', 'subject']
|
|
37
37
|
|
|
38
38
|
FIELDS_MAP = {
|
|
39
|
-
"to" => ToField,
|
|
40
|
-
"cc" => CcField,
|
|
41
|
-
"bcc" => BccField,
|
|
42
|
-
"message-id" => MessageIdField,
|
|
43
|
-
"in-reply-to" => InReplyToField,
|
|
44
|
-
"references" => ReferencesField,
|
|
45
|
-
"subject" => SubjectField,
|
|
46
|
-
"comments" => CommentsField,
|
|
47
|
-
"keywords" => KeywordsField,
|
|
48
|
-
"date" => DateField,
|
|
49
|
-
"from" => FromField,
|
|
50
|
-
"sender" => SenderField,
|
|
51
|
-
"reply-to" => ReplyToField,
|
|
52
|
-
"resent-date" => ResentDateField,
|
|
53
|
-
"resent-from" => ResentFromField,
|
|
54
|
-
"resent-sender" =>
|
|
55
|
-
"resent-to" => ResentToField,
|
|
56
|
-
"resent-cc" => ResentCcField,
|
|
57
|
-
"resent-bcc" => ResentBccField,
|
|
58
|
-
"resent-message-id" => ResentMessageIdField,
|
|
59
|
-
"return-path" => ReturnPathField,
|
|
60
|
-
"received" => ReceivedField,
|
|
61
|
-
"mime-version" => MimeVersionField,
|
|
62
|
-
"content-transfer-encoding" => ContentTransferEncodingField,
|
|
63
|
-
"content-description" => ContentDescriptionField,
|
|
64
|
-
"content-disposition" => ContentDispositionField,
|
|
65
|
-
"content-type" => ContentTypeField,
|
|
66
|
-
"content-id" => ContentIdField,
|
|
67
|
-
"content-location" => ContentLocationField,
|
|
39
|
+
"to" => "ToField",
|
|
40
|
+
"cc" => "CcField",
|
|
41
|
+
"bcc" => "BccField",
|
|
42
|
+
"message-id" => "MessageIdField",
|
|
43
|
+
"in-reply-to" => "InReplyToField",
|
|
44
|
+
"references" => "ReferencesField",
|
|
45
|
+
"subject" => "SubjectField",
|
|
46
|
+
"comments" => "CommentsField",
|
|
47
|
+
"keywords" => "KeywordsField",
|
|
48
|
+
"date" => "DateField",
|
|
49
|
+
"from" => "FromField",
|
|
50
|
+
"sender" => "SenderField",
|
|
51
|
+
"reply-to" => "ReplyToField",
|
|
52
|
+
"resent-date" => "ResentDateField",
|
|
53
|
+
"resent-from" => "ResentFromField",
|
|
54
|
+
"resent-sender" => "ResentSenderField",
|
|
55
|
+
"resent-to" => "ResentToField",
|
|
56
|
+
"resent-cc" => "ResentCcField",
|
|
57
|
+
"resent-bcc" => "ResentBccField",
|
|
58
|
+
"resent-message-id" => "ResentMessageIdField",
|
|
59
|
+
"return-path" => "ReturnPathField",
|
|
60
|
+
"received" => "ReceivedField",
|
|
61
|
+
"mime-version" => "MimeVersionField",
|
|
62
|
+
"content-transfer-encoding" => "ContentTransferEncodingField",
|
|
63
|
+
"content-description" => "ContentDescriptionField",
|
|
64
|
+
"content-disposition" => "ContentDispositionField",
|
|
65
|
+
"content-type" => "ContentTypeField",
|
|
66
|
+
"content-id" => "ContentIdField",
|
|
67
|
+
"content-location" => "ContentLocationField",
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
FIELD_NAME_MAP =
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
FIELD_NAME_MAP = {
|
|
71
|
+
"to" => "To",
|
|
72
|
+
"cc" => "Cc",
|
|
73
|
+
"bcc" => "Bcc",
|
|
74
|
+
"message-id" => "Message-ID",
|
|
75
|
+
"in-reply-to" => "In-Reply-To",
|
|
76
|
+
"references" => "References",
|
|
77
|
+
"subject" => "Subject",
|
|
78
|
+
"comments" => "Comments",
|
|
79
|
+
"keywords" => "Keywords",
|
|
80
|
+
"date" => "Date",
|
|
81
|
+
"from" => "From",
|
|
82
|
+
"sender" => "Sender",
|
|
83
|
+
"reply-to" => "Reply-To",
|
|
84
|
+
"resent-date" => "Resent-Date",
|
|
85
|
+
"resent-from" => "Resent-From",
|
|
86
|
+
"resent-sender" => "Resent-Sender",
|
|
87
|
+
"resent-to" => "Resent-To",
|
|
88
|
+
"resent-cc" => "Resent-Cc",
|
|
89
|
+
"resent-bcc" => "Resent-Bcc",
|
|
90
|
+
"resent-message-id" => "Resent-Message-ID",
|
|
91
|
+
"return-path" => "Return-Path",
|
|
92
|
+
"received" => "Received",
|
|
93
|
+
"mime-version" => "MIME-Version",
|
|
94
|
+
"content-transfer-encoding" => "Content-Transfer-Encoding",
|
|
95
|
+
"content-description" => "Content-Description",
|
|
96
|
+
"content-disposition" => "Content-Disposition",
|
|
97
|
+
"content-type" => "Content-Type",
|
|
98
|
+
"content-id" => "Content-ID",
|
|
99
|
+
"content-location" => "Content-Location",
|
|
100
|
+
}
|
|
73
101
|
|
|
74
102
|
# Generic Field Exception
|
|
75
103
|
class FieldError < StandardError
|
|
@@ -130,7 +158,7 @@ module Mail
|
|
|
130
158
|
if raw_field.index(Constants::COLON)
|
|
131
159
|
name, value = raw_field.split(Constants::COLON, 2)
|
|
132
160
|
name.rstrip!
|
|
133
|
-
if
|
|
161
|
+
if /\A#{Constants::FIELD_NAME}\z/.match?(name)
|
|
134
162
|
[ name.rstrip, value.strip ]
|
|
135
163
|
else
|
|
136
164
|
Kernel.warn "WARNING: Ignoring unparsable header #{raw_field.inspect}: invalid header name syntax: #{name.inspect}"
|
|
@@ -145,7 +173,8 @@ module Mail
|
|
|
145
173
|
end
|
|
146
174
|
|
|
147
175
|
def field_class_for(name) #:nodoc:
|
|
148
|
-
FIELDS_MAP[name.to_s.downcase]
|
|
176
|
+
class_name = FIELDS_MAP[name.to_s.downcase]
|
|
177
|
+
Mail.const_get(class_name) if class_name
|
|
149
178
|
end
|
|
150
179
|
end
|
|
151
180
|
|
|
@@ -176,7 +205,8 @@ module Mail
|
|
|
176
205
|
@unparsed_value = value
|
|
177
206
|
@charset = charset
|
|
178
207
|
end
|
|
179
|
-
|
|
208
|
+
klass = self.class.field_class_for(@name)
|
|
209
|
+
@name = klass ? klass::NAME : @name
|
|
180
210
|
end
|
|
181
211
|
|
|
182
212
|
def field=(field)
|
data/lib/mail/field_list.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
module Mail
|
|
4
4
|
|
|
5
|
-
# Field List class provides an enhanced array that keeps a list of
|
|
5
|
+
# Field List class provides an enhanced array that keeps a list of
|
|
6
6
|
# email fields in order. And allows you to insert new fields without
|
|
7
7
|
# having to worry about the order they will appear in.
|
|
8
8
|
class FieldList < Array
|
data/lib/mail/fields/cc_field.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
# frozen_string_literal: true
|
|
3
|
-
require 'mail/fields/named_structured_field'
|
|
4
3
|
|
|
5
4
|
module Mail
|
|
6
5
|
class AddressContainer < Array #:nodoc:
|
|
@@ -118,22 +117,15 @@ module Mail
|
|
|
118
117
|
end
|
|
119
118
|
|
|
120
119
|
private
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
else
|
|
133
|
-
def utf8_if_needed(val, val_charset)
|
|
134
|
-
if val_charset =~ /\AUTF-?8\z/i
|
|
135
|
-
val
|
|
136
|
-
end
|
|
120
|
+
|
|
121
|
+
# Pass through UTF-8 addresses
|
|
122
|
+
def utf8_if_needed(val, val_charset)
|
|
123
|
+
if /\AUTF-?8\z/i.match?(val_charset)
|
|
124
|
+
val
|
|
125
|
+
elsif val.encoding == Encoding::UTF_8
|
|
126
|
+
val
|
|
127
|
+
elsif (utf8 = val.dup.force_encoding(Encoding::UTF_8)).valid_encoding?
|
|
128
|
+
utf8
|
|
137
129
|
end
|
|
138
130
|
end
|
|
139
131
|
|