mail 2.8.1 → 2.9.0.beta1

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 (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +76 -31
  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 +22 -19
  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/sendmail.rb +2 -48
  55. data/lib/mail/network/delivery_methods/smtp.rb +77 -42
  56. data/lib/mail/network/delivery_methods/smtp_connection.rb +7 -7
  57. data/lib/mail/network/delivery_methods/test_mailer.rb +4 -4
  58. data/lib/mail/network/retriever_methods/base.rb +5 -5
  59. data/lib/mail/network/retriever_methods/imap.rb +6 -3
  60. data/lib/mail/network/retriever_methods/pop3.rb +20 -20
  61. data/lib/mail/parsers/address_lists_parser.rb +8 -5
  62. data/lib/mail/parsers/address_lists_parser.rl +4 -0
  63. data/lib/mail/parsers/content_disposition_parser.rb +15 -12
  64. data/lib/mail/parsers/content_disposition_parser.rl +4 -0
  65. data/lib/mail/parsers/content_location_parser.rb +9 -6
  66. data/lib/mail/parsers/content_location_parser.rl +5 -1
  67. data/lib/mail/parsers/content_transfer_encoding_parser.rb +8 -5
  68. data/lib/mail/parsers/content_transfer_encoding_parser.rl +4 -0
  69. data/lib/mail/parsers/content_type_parser.rb +15 -12
  70. data/lib/mail/parsers/content_type_parser.rl +4 -0
  71. data/lib/mail/parsers/date_time_parser.rb +8 -5
  72. data/lib/mail/parsers/date_time_parser.rl +4 -0
  73. data/lib/mail/parsers/envelope_from_parser.rb +8 -5
  74. data/lib/mail/parsers/envelope_from_parser.rl +4 -0
  75. data/lib/mail/parsers/message_ids_parser.rb +8 -5
  76. data/lib/mail/parsers/message_ids_parser.rl +4 -0
  77. data/lib/mail/parsers/mime_version_parser.rb +8 -5
  78. data/lib/mail/parsers/mime_version_parser.rl +4 -0
  79. data/lib/mail/parsers/phrase_lists_parser.rb +8 -5
  80. data/lib/mail/parsers/phrase_lists_parser.rl +4 -0
  81. data/lib/mail/parsers/received_parser.rb +8 -5
  82. data/lib/mail/parsers/received_parser.rl +4 -0
  83. data/lib/mail/part.rb +19 -19
  84. data/lib/mail/smtp_envelope.rb +1 -1
  85. data/lib/mail/utilities.rb +5 -5
  86. data/lib/mail/version.rb +3 -3
  87. data/lib/mail.rb +2 -5
  88. metadata +3 -4
  89. data/lib/mail/check_delivery_params.rb +0 -65
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea4015fe2858f6c1b123e04d4d407169567b1aeea1155b7b145fe75d9d3781b5
4
- data.tar.gz: 20cdb386c2f878560b9f61ab63b4f0c264c9f9115af5c835b8c66f49486cb274
3
+ metadata.gz: b7d3d2a36ffc97d1a84f842a67d70c095c6b2533a31913dc5d9ba5d54730fbd4
4
+ data.tar.gz: 6f734ec59136e640ce168eecfc9b8b8a1f5800e7de58ccb1fe0549ad2b9f1954
5
5
  SHA512:
6
- metadata.gz: b2eb55bc6f51b2d93e6d6abed5bb74876b3f96fd1eea00105047b3a211007b2b906ac89bcd1bed52603c211c595d439b6642bd897943decbcc9ac541f88e2049
7
- data.tar.gz: 063dd68ef655b93d96412bdcf66ab6f191eaf0bfbafa10730ecfa99a447eb3d2a4469d6d1de67ae144bbaada65eaec4c7d8dbb5fe04509146dc1434a5c557fff
6
+ metadata.gz: 8f221754abf53c21e94c4c728e0b6a9fac5fdae869aea44167bd3fc43cce5e7f635c722bf477d1f54c9e0e01826be5b36321ea1f6b03ac4a922be0595976a519
7
+ data.tar.gz: aefd3c33fb35d873c8c8765ed1c89f890be4b4bdd9f8480f2df9ed743df2884506430d08c1ae7404fda483d6411b459cf382782210ee842baaec7cfed1c47ac2
data/README.md CHANGED
@@ -42,7 +42,7 @@ 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
@@ -417,18 +417,21 @@ simple as possible.... (asking a lot from a mail library)
417
417
 
418
418
  ```ruby
419
419
  mail = Mail.deliver do
420
- to 'nicolas@test.lindsaar.net.au'
421
- from 'Mikel Lindsaar <mikel@test.lindsaar.net.au>'
422
- subject 'First multipart email sent with Mail'
423
-
424
- text_part do
425
- body 'This is plain text'
426
- end
427
-
428
- html_part do
429
- content_type 'text/html; charset=UTF-8'
430
- 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'
431
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"
432
435
  end
433
436
  ```
434
437
 
@@ -439,34 +442,76 @@ so desire...
439
442
  ```
440
443
  puts mail.to_s #=>
441
444
 
442
- To: nicolas@test.lindsaar.net.au
445
+ Date: Tue, 26 Apr 2022 20:12:07 +0200
443
446
  From: Mikel Lindsaar <mikel@test.lindsaar.net.au>
447
+ To: nicolas@test.lindsaar.net.au
448
+ Message-ID: <626835f736e19_10873fdfa3c2ffd4947a3@sender.at.mail>
444
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
445
472
  Content-Type: multipart/alternative;
446
- boundary=--==_mimepart_4a914f0c911be_6f0f1ab8026659
447
- Message-ID: <4a914f12ac7e_6f0f1ab80267d1@baci.local.mail>
448
- Date: Mon, 24 Aug 2009 00:15:46 +1000
449
- 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
450
483
  Content-Transfer-Encoding: 7bit
451
484
 
485
+ Here is the attachment you wanted
452
486
 
453
- ----==_mimepart_4a914f0c911be_6f0f1ab8026659
454
- Content-ID: <4a914f12c8c4_6f0f1ab80268d6@baci.local.mail>
455
- Date: Mon, 24 Aug 2009 00:15:46 +1000
456
- Mime-Version: 1.0
457
- Content-Type: text/plain
487
+ ----==_mimepart_626835f733702_10873fdfa3c2ffd494376
488
+ Content-Type: text/html;
489
+ charset=utf-8
458
490
  Content-Transfer-Encoding: 7bit
459
491
 
460
- This is plain text
461
- ----==_mimepart_4a914f0c911be_6f0f1ab8026659
462
- Content-Type: text/html; charset=UTF-8
463
- Content-ID: <4a914f12cf86_6f0f1ab802692c@baci.local.mail>
464
- Date: Mon, 24 Aug 2009 00:15:46 +1000
465
- 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
466
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
467
513
 
468
- <h1>This is HTML</h1>
469
- ----==_mimepart_4a914f0c911be_6f0f1ab8026659--
514
+ ----==_mimepart_626835f733867_10873fdfa3c2ffd494636--
470
515
  ```
471
516
 
472
517
  Mail inserts the content transfer encoding, the mime version,
@@ -616,7 +661,7 @@ Mail.defaults do
616
661
  delivery_method :test # in practice you'd do this in spec_helper.rb
617
662
  end
618
663
 
619
- describe "sending an email" do
664
+ RSpec.describe "sending an email" do
620
665
  include Mail::Matchers
621
666
 
622
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: