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.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +91 -32
  3. data/lib/mail/attachments_list.rb +3 -1
  4. data/lib/mail/body.rb +28 -28
  5. data/lib/mail/encodings/quoted_printable.rb +1 -1
  6. data/lib/mail/encodings/unix_to_unix.rb +1 -1
  7. data/lib/mail/encodings.rb +2 -2
  8. data/lib/mail/field.rb +65 -35
  9. data/lib/mail/field_list.rb +1 -1
  10. data/lib/mail/fields/bcc_field.rb +0 -1
  11. data/lib/mail/fields/cc_field.rb +0 -1
  12. data/lib/mail/fields/comments_field.rb +0 -1
  13. data/lib/mail/fields/common_address_field.rb +9 -17
  14. data/lib/mail/fields/common_date_field.rb +0 -2
  15. data/lib/mail/fields/common_message_id_field.rb +0 -1
  16. data/lib/mail/fields/content_description_field.rb +0 -1
  17. data/lib/mail/fields/content_disposition_field.rb +0 -2
  18. data/lib/mail/fields/content_id_field.rb +0 -1
  19. data/lib/mail/fields/content_location_field.rb +0 -1
  20. data/lib/mail/fields/content_transfer_encoding_field.rb +0 -1
  21. data/lib/mail/fields/content_type_field.rb +5 -6
  22. data/lib/mail/fields/date_field.rb +0 -1
  23. data/lib/mail/fields/from_field.rb +0 -1
  24. data/lib/mail/fields/in_reply_to_field.rb +0 -1
  25. data/lib/mail/fields/keywords_field.rb +0 -1
  26. data/lib/mail/fields/message_id_field.rb +0 -1
  27. data/lib/mail/fields/mime_version_field.rb +1 -2
  28. data/lib/mail/fields/named_structured_field.rb +0 -1
  29. data/lib/mail/fields/named_unstructured_field.rb +0 -1
  30. data/lib/mail/fields/optional_field.rb +0 -1
  31. data/lib/mail/fields/received_field.rb +0 -1
  32. data/lib/mail/fields/references_field.rb +0 -1
  33. data/lib/mail/fields/reply_to_field.rb +0 -1
  34. data/lib/mail/fields/resent_bcc_field.rb +0 -1
  35. data/lib/mail/fields/resent_cc_field.rb +0 -1
  36. data/lib/mail/fields/resent_date_field.rb +0 -1
  37. data/lib/mail/fields/resent_from_field.rb +0 -1
  38. data/lib/mail/fields/resent_message_id_field.rb +0 -1
  39. data/lib/mail/fields/resent_sender_field.rb +0 -1
  40. data/lib/mail/fields/resent_to_field.rb +0 -1
  41. data/lib/mail/fields/return_path_field.rb +0 -1
  42. data/lib/mail/fields/sender_field.rb +0 -1
  43. data/lib/mail/fields/structured_field.rb +0 -1
  44. data/lib/mail/fields/subject_field.rb +0 -1
  45. data/lib/mail/fields/to_field.rb +0 -1
  46. data/lib/mail/fields/unstructured_field.rb +0 -1
  47. data/lib/mail/fields.rb +9 -0
  48. data/lib/mail/header.rb +1 -1
  49. data/lib/mail/mail.rb +32 -27
  50. data/lib/mail/message.rb +23 -20
  51. data/lib/mail/multibyte/chars.rb +1 -1
  52. data/lib/mail/multibyte/unicode.rb +1 -1
  53. data/lib/mail/network/delivery_methods/file_delivery.rb +2 -2
  54. data/lib/mail/network/delivery_methods/smtp.rb +77 -42
  55. data/lib/mail/network/delivery_methods/smtp_connection.rb +7 -7
  56. data/lib/mail/network/delivery_methods/test_mailer.rb +4 -4
  57. data/lib/mail/network/retriever_methods/base.rb +5 -5
  58. data/lib/mail/network/retriever_methods/imap.rb +6 -3
  59. data/lib/mail/network/retriever_methods/pop3.rb +20 -20
  60. data/lib/mail/parsers/address_lists_parser.rb +8 -5
  61. data/lib/mail/parsers/address_lists_parser.rl +4 -0
  62. data/lib/mail/parsers/content_disposition_parser.rb +15 -12
  63. data/lib/mail/parsers/content_disposition_parser.rl +4 -0
  64. data/lib/mail/parsers/content_location_parser.rb +9 -6
  65. data/lib/mail/parsers/content_location_parser.rl +5 -1
  66. data/lib/mail/parsers/content_transfer_encoding_parser.rb +8 -5
  67. data/lib/mail/parsers/content_transfer_encoding_parser.rl +4 -0
  68. data/lib/mail/parsers/content_type_parser.rb +15 -12
  69. data/lib/mail/parsers/content_type_parser.rl +4 -0
  70. data/lib/mail/parsers/date_time_parser.rb +8 -5
  71. data/lib/mail/parsers/date_time_parser.rl +4 -0
  72. data/lib/mail/parsers/envelope_from_parser.rb +8 -5
  73. data/lib/mail/parsers/envelope_from_parser.rl +4 -0
  74. data/lib/mail/parsers/message_ids_parser.rb +8 -5
  75. data/lib/mail/parsers/message_ids_parser.rl +4 -0
  76. data/lib/mail/parsers/mime_version_parser.rb +8 -5
  77. data/lib/mail/parsers/mime_version_parser.rl +4 -0
  78. data/lib/mail/parsers/phrase_lists_parser.rb +8 -5
  79. data/lib/mail/parsers/phrase_lists_parser.rl +4 -0
  80. data/lib/mail/parsers/received_parser.rb +8 -5
  81. data/lib/mail/parsers/received_parser.rl +4 -0
  82. data/lib/mail/part.rb +19 -19
  83. data/lib/mail/smtp_envelope.rb +1 -1
  84. data/lib/mail/utilities.rb +11 -7
  85. data/lib/mail/version.rb +1 -1
  86. data/lib/mail.rb +2 -5
  87. metadata +17 -4
  88. data/lib/mail/check_delivery_params.rb +0 -65
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa5b2d445e65e58dc7c1716cd6f2eebd4f2397548eb1aa1d9230222df09f6aa3
4
- data.tar.gz: cae304c28819a9903baf718616f8bb94e2ea860b0b2db43bfb3a3e0f9f12eaac
3
+ metadata.gz: 19bd6b0f4442e909c23a9b7da4aecd758bc7f13f49f55b0d38cbcea5d18a91bf
4
+ data.tar.gz: 30187e6fef5ff7d5aaa6e1608bac3f74748946b6aa84f63bc0152b14f8ec0f70
5
5
  SHA512:
6
- metadata.gz: b72cc59bc03570e9f5347d796e38b6d4365143a7122e7353559314e82b2523479fb5adf90fce65d1d8a5c7e95a97964b2118c082de5b6bb535f663bf4056fa8f
7
- data.tar.gz: 64157d336e45117c5e32db4a599ccf97e3b8b6aa2c761b4d5923f18b6b506ee8a20795ce5e9e8494c4d39c7c4784e2317da7674d89ffc75cb5fd6d19f5473073
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 Span Corpus 2005](#excerpts-from-trec-span-corpus-2005)
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 supports Ruby 2.5+, including JRuby and TruffleRuby.
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
- to 'nicolas@test.lindsaar.net.au'
407
- from 'Mikel Lindsaar <mikel@test.lindsaar.net.au>'
408
- subject 'First multipart email sent with Mail'
409
-
410
- text_part do
411
- body 'This is plain text'
412
- end
413
-
414
- html_part do
415
- content_type 'text/html; charset=UTF-8'
416
- body '<h1>This is HTML</h1>'
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
- To: nicolas@test.lindsaar.net.au
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
- boundary=--==_mimepart_4a914f0c911be_6f0f1ab8026659
433
- Message-ID: <4a914f12ac7e_6f0f1ab80267d1@baci.local.mail>
434
- Date: Mon, 24 Aug 2009 00:15:46 +1000
435
- Mime-Version: 1.0
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
- ----==_mimepart_4a914f0c911be_6f0f1ab8026659
440
- Content-ID: <4a914f12c8c4_6f0f1ab80268d6@baci.local.mail>
441
- Date: Mon, 24 Aug 2009 00:15:46 +1000
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
- This is plain text
447
- ----==_mimepart_4a914f0c911be_6f0f1ab8026659
448
- Content-Type: text/html; charset=UTF-8
449
- Content-ID: <4a914f12cf86_6f0f1ab802692c@baci.local.mail>
450
- Date: Mon, 24 Aug 2009 00:15:46 +1000
451
- Mime-Version: 1.0
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
- <h1>This is HTML</h1>
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
- Mail.new(p.body.encoded).attachments
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 = ::Mail::Utilities.to_crlf(string.join(''))
42
+ @raw_source = string.join('')
43
43
  elsif string.respond_to?(:to_s)
44
- @raw_source = ::Mail::Utilities.to_crlf(string.to_s)
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\n # line break
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").unpack("M*").first
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)
@@ -5,7 +5,7 @@ module Mail
5
5
  NAME = "x-uuencode"
6
6
 
7
7
  def self.decode(str)
8
- str.sub(/\Abegin \d+ [^\n]*\n/, '').unpack('u').first
8
+ str.sub(/\Abegin \d+ [^\n]*\n/, '').unpack1('u')
9
9
  end
10
10
 
11
11
  def self.encode(str)
@@ -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 =~ TOKEN_UNSAFE
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 =~ ENCODED_VALUE
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" => 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,
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 = FIELDS_MAP.inject({}) do |map, (field, field_klass)|
71
- map.update(field => field_klass::NAME)
72
- end
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 name =~ /\A#{Constants::FIELD_NAME}\z/
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
- @name = FIELD_NAME_MAP[@name.to_s.downcase] || @name
208
+ klass = self.class.field_class_for(@name)
209
+ @name = klass ? klass::NAME : @name
180
210
  end
181
211
 
182
212
  def field=(field)
@@ -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
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/fields/common_address_field'
4
3
 
5
4
  module Mail
6
5
  # = Blind Carbon Copy Field
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/fields/common_address_field'
4
3
 
5
4
  module Mail
6
5
  # = Carbon Copy Field
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/fields/named_unstructured_field'
4
3
 
5
4
  module Mail
6
5
  # = Comments Field
@@ -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
- if 'string'.respond_to?(:encoding)
122
- # Pass through UTF-8 addresses
123
- def utf8_if_needed(val, val_charset)
124
- if val_charset =~ /\AUTF-?8\z/i
125
- val
126
- elsif val.encoding == Encoding::UTF_8
127
- val
128
- elsif (utf8 = val.dup.force_encoding(Encoding::UTF_8)).valid_encoding?
129
- utf8
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
 
@@ -1,5 +1,3 @@
1
- require 'mail/fields/named_structured_field'
2
- require 'mail/elements/date_time_element'
3
1
  require 'mail/utilities'
4
2
 
5
3
  module Mail
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/fields/named_structured_field'
4
3
  require 'mail/utilities'
5
4
 
6
5
  module Mail
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/fields/named_unstructured_field'
4
3
 
5
4
  module Mail
6
5
  class ContentDescriptionField < NamedUnstructuredField #:nodoc:
@@ -1,7 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/fields/named_structured_field'
4
- require 'mail/fields/parameter_hash'
5
3
 
6
4
  module Mail
7
5
  class ContentDispositionField < NamedStructuredField #:nodoc:
@@ -1,6 +1,5 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- require 'mail/fields/named_structured_field'
4
3
  require 'mail/utilities'
5
4
 
6
5
  module Mail
@@ -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 ContentLocationField < NamedStructuredField #:nodoc:
@@ -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 ContentTransferEncodingField < NamedStructuredField #:nodoc: