mail 2.7.1 → 2.9.1

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +135 -59
  3. data/lib/mail/attachments_list.rb +5 -6
  4. data/lib/mail/body.rb +51 -74
  5. data/lib/mail/constants.rb +27 -5
  6. data/lib/mail/elements/address.rb +27 -27
  7. data/lib/mail/elements/address_list.rb +1 -1
  8. data/lib/mail/elements/content_disposition_element.rb +1 -1
  9. data/lib/mail/elements/content_location_element.rb +1 -1
  10. data/lib/mail/elements/content_transfer_encoding_element.rb +1 -1
  11. data/lib/mail/elements/content_type_element.rb +8 -4
  12. data/lib/mail/elements/date_time_element.rb +1 -1
  13. data/lib/mail/elements/envelope_from_element.rb +13 -7
  14. data/lib/mail/elements/message_ids_element.rb +14 -5
  15. data/lib/mail/elements/mime_version_element.rb +1 -1
  16. data/lib/mail/elements/phrase_list.rb +7 -2
  17. data/lib/mail/elements/received_element.rb +20 -6
  18. data/lib/mail/encodings/7bit.rb +5 -0
  19. data/lib/mail/encodings/base64.rb +2 -2
  20. data/lib/mail/encodings/quoted_printable.rb +2 -2
  21. data/lib/mail/encodings/unix_to_unix.rb +1 -1
  22. data/lib/mail/encodings.rb +32 -61
  23. data/lib/mail/envelope.rb +11 -14
  24. data/lib/mail/field.rb +100 -86
  25. data/lib/mail/field_list.rb +61 -8
  26. data/lib/mail/fields/bcc_field.rb +33 -52
  27. data/lib/mail/fields/cc_field.rb +27 -49
  28. data/lib/mail/fields/comments_field.rb +26 -37
  29. data/lib/mail/fields/common_address_field.rb +162 -0
  30. data/lib/mail/fields/common_date_field.rb +56 -0
  31. data/lib/mail/fields/common_field.rb +77 -0
  32. data/lib/mail/fields/common_message_id_field.rb +41 -0
  33. data/lib/mail/fields/content_description_field.rb +6 -14
  34. data/lib/mail/fields/content_disposition_field.rb +11 -38
  35. data/lib/mail/fields/content_id_field.rb +23 -51
  36. data/lib/mail/fields/content_location_field.rb +10 -25
  37. data/lib/mail/fields/content_transfer_encoding_field.rb +30 -31
  38. data/lib/mail/fields/content_type_field.rb +49 -75
  39. data/lib/mail/fields/date_field.rb +22 -51
  40. data/lib/mail/fields/from_field.rb +27 -49
  41. data/lib/mail/fields/in_reply_to_field.rb +37 -49
  42. data/lib/mail/fields/keywords_field.rb +17 -31
  43. data/lib/mail/fields/message_id_field.rb +24 -71
  44. data/lib/mail/fields/mime_version_field.rb +18 -30
  45. data/lib/mail/fields/named_structured_field.rb +10 -0
  46. data/lib/mail/fields/named_unstructured_field.rb +10 -0
  47. data/lib/mail/fields/optional_field.rb +5 -7
  48. data/lib/mail/fields/{common/parameter_hash.rb → parameter_hash.rb} +12 -10
  49. data/lib/mail/fields/received_field.rb +42 -57
  50. data/lib/mail/fields/references_field.rb +34 -49
  51. data/lib/mail/fields/reply_to_field.rb +27 -49
  52. data/lib/mail/fields/resent_bcc_field.rb +27 -49
  53. data/lib/mail/fields/resent_cc_field.rb +27 -49
  54. data/lib/mail/fields/resent_date_field.rb +4 -29
  55. data/lib/mail/fields/resent_from_field.rb +27 -49
  56. data/lib/mail/fields/resent_message_id_field.rb +4 -29
  57. data/lib/mail/fields/resent_sender_field.rb +26 -56
  58. data/lib/mail/fields/resent_to_field.rb +27 -49
  59. data/lib/mail/fields/return_path_field.rb +49 -54
  60. data/lib/mail/fields/sender_field.rb +33 -55
  61. data/lib/mail/fields/structured_field.rb +2 -30
  62. data/lib/mail/fields/subject_field.rb +8 -11
  63. data/lib/mail/fields/to_field.rb +27 -49
  64. data/lib/mail/fields/unstructured_field.rb +15 -48
  65. data/lib/mail/fields.rb +9 -0
  66. data/lib/mail/header.rb +69 -110
  67. data/lib/mail/mail.rb +32 -27
  68. data/lib/mail/matchers/attachment_matchers.rb +15 -0
  69. data/lib/mail/message.rb +67 -78
  70. data/lib/mail/multibyte/chars.rb +9 -167
  71. data/lib/mail/multibyte/unicode.rb +1 -1
  72. data/lib/mail/multibyte/utils.rb +26 -43
  73. data/lib/mail/multibyte.rb +1 -11
  74. data/lib/mail/network/delivery_methods/exim.rb +5 -4
  75. data/lib/mail/network/delivery_methods/file_delivery.rb +13 -12
  76. data/lib/mail/network/delivery_methods/logger_delivery.rb +2 -5
  77. data/lib/mail/network/delivery_methods/sendmail.rb +27 -35
  78. data/lib/mail/network/delivery_methods/smtp.rb +81 -30
  79. data/lib/mail/network/delivery_methods/smtp_connection.rb +10 -19
  80. data/lib/mail/network/delivery_methods/test_mailer.rb +8 -6
  81. data/lib/mail/network/retriever_methods/base.rb +13 -13
  82. data/lib/mail/network/retriever_methods/imap.rb +8 -5
  83. data/lib/mail/network/retriever_methods/pop3.rb +22 -22
  84. data/lib/mail/network/retriever_methods/test_retriever.rb +2 -1
  85. data/lib/mail/parsers/address_lists_parser.rb +33073 -33064
  86. data/lib/mail/parsers/address_lists_parser.rl +11 -0
  87. data/lib/mail/parsers/content_disposition_parser.rb +837 -828
  88. data/lib/mail/parsers/content_disposition_parser.rl +11 -0
  89. data/lib/mail/parsers/content_location_parser.rb +773 -764
  90. data/lib/mail/parsers/content_location_parser.rl +12 -1
  91. data/lib/mail/parsers/content_transfer_encoding_parser.rb +477 -468
  92. data/lib/mail/parsers/content_transfer_encoding_parser.rl +11 -0
  93. data/lib/mail/parsers/content_type_parser.rb +974 -965
  94. data/lib/mail/parsers/content_type_parser.rl +11 -0
  95. data/lib/mail/parsers/date_time_parser.rb +841 -832
  96. data/lib/mail/parsers/date_time_parser.rl +11 -0
  97. data/lib/mail/parsers/envelope_from_parser.rb +3627 -3530
  98. data/lib/mail/parsers/envelope_from_parser.rl +11 -0
  99. data/lib/mail/parsers/message_ids_parser.rb +5110 -2800
  100. data/lib/mail/parsers/message_ids_parser.rl +16 -1
  101. data/lib/mail/parsers/mime_version_parser.rb +466 -457
  102. data/lib/mail/parsers/mime_version_parser.rl +11 -0
  103. data/lib/mail/parsers/phrase_lists_parser.rb +839 -830
  104. data/lib/mail/parsers/phrase_lists_parser.rl +12 -1
  105. data/lib/mail/parsers/received_parser.rb +8692 -8683
  106. data/lib/mail/parsers/received_parser.rl +11 -0
  107. data/lib/mail/parsers/rfc5322.rl +28 -13
  108. data/lib/mail/parsers.rb +11 -17
  109. data/lib/mail/part.rb +24 -28
  110. data/lib/mail/parts_list.rb +57 -0
  111. data/lib/mail/smtp_envelope.rb +57 -0
  112. data/lib/mail/utilities.rb +321 -69
  113. data/lib/mail/version.rb +1 -1
  114. data/lib/mail/yaml.rb +30 -0
  115. data/lib/mail.rb +2 -22
  116. metadata +83 -19
  117. data/lib/mail/check_delivery_params.rb +0 -60
  118. data/lib/mail/core_extensions/smtp.rb +0 -28
  119. data/lib/mail/core_extensions/string.rb +0 -17
  120. data/lib/mail/fields/common/address_container.rb +0 -17
  121. data/lib/mail/fields/common/common_address.rb +0 -161
  122. data/lib/mail/fields/common/common_date.rb +0 -36
  123. data/lib/mail/fields/common/common_field.rb +0 -52
  124. data/lib/mail/fields/common/common_message_id.rb +0 -49
  125. data/lib/mail/version_specific/ruby_1_8.rb +0 -163
  126. data/lib/mail/version_specific/ruby_1_9.rb +0 -278
@@ -1,27 +1,27 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
3
  require 'mail/parsers/address_lists_parser'
4
+ require 'mail/constants'
5
+ require 'mail/utilities'
4
6
 
5
7
  module Mail
8
+ # Mail::Address handles all email addresses in Mail. It takes an email address string
9
+ # and parses it, breaking it down into its component parts and allowing you to get the
10
+ # address, comments, display name, name, local part, domain part and fully formatted
11
+ # address.
12
+ #
13
+ # Mail::Address requires a correctly formatted email address per RFC2822 or RFC822. It
14
+ # handles all obsolete versions including obsolete domain routing on the local part.
15
+ #
16
+ # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
17
+ # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
18
+ # a.address #=> 'mikel@test.lindsaar.net'
19
+ # a.display_name #=> 'Mikel Lindsaar'
20
+ # a.local #=> 'mikel'
21
+ # a.domain #=> 'test.lindsaar.net'
22
+ # a.comments #=> ['My email address']
23
+ # a.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
6
24
  class Address
7
- include Mail::Utilities
8
-
9
- # Mail::Address handles all email addresses in Mail. It takes an email address string
10
- # and parses it, breaking it down into its component parts and allowing you to get the
11
- # address, comments, display name, name, local part, domain part and fully formatted
12
- # address.
13
- #
14
- # Mail::Address requires a correctly formatted email address per RFC2822 or RFC822. It
15
- # handles all obsolete versions including obsolete domain routing on the local part.
16
- #
17
- # a = Address.new('Mikel Lindsaar (My email address) <mikel@test.lindsaar.net>')
18
- # a.format #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
19
- # a.address #=> 'mikel@test.lindsaar.net'
20
- # a.display_name #=> 'Mikel Lindsaar'
21
- # a.local #=> 'mikel'
22
- # a.domain #=> 'test.lindsaar.net'
23
- # a.comments #=> ['My email address']
24
- # a.to_s #=> 'Mikel Lindsaar <mikel@test.lindsaar.net> (My email address)'
25
25
  def initialize(value = nil)
26
26
  if value.nil?
27
27
  @parsed = false
@@ -47,11 +47,11 @@ module Mail
47
47
  def format(output_type = :decode)
48
48
  parse unless @parsed
49
49
  if @data.nil?
50
- EMPTY
50
+ Constants::EMPTY
51
51
  elsif name = display_name(output_type)
52
- [quote_phrase(name), "<#{address(output_type)}>", format_comments].compact.join(SPACE)
52
+ [Utilities.quote_phrase(name), "<#{address(output_type)}>", format_comments].compact.join(Constants::SPACE)
53
53
  elsif a = address(output_type)
54
- [a, format_comments].compact.join(SPACE)
54
+ [a, format_comments].compact.join(Constants::SPACE)
55
55
  else
56
56
  raw
57
57
  end
@@ -135,7 +135,7 @@ module Mail
135
135
  if comments.nil? || comments.none?
136
136
  nil
137
137
  else
138
- comments.map { |c| c.squeeze(SPACE) }
138
+ comments.map { |c| c.squeeze(Constants::SPACE) }
139
139
  end
140
140
  end
141
141
 
@@ -198,7 +198,7 @@ module Mail
198
198
  def strip_all_comments(string)
199
199
  unless Utilities.blank?(comments)
200
200
  comments.each do |comment|
201
- string = string.gsub("(#{comment})", EMPTY)
201
+ string = string.gsub("(#{comment})", Constants::EMPTY)
202
202
  end
203
203
  end
204
204
  string.strip
@@ -208,7 +208,7 @@ module Mail
208
208
  unless Utilities.blank?(comments)
209
209
  comments.each do |comment|
210
210
  if @data.domain && @data.domain.include?("(#{comment})")
211
- value = value.gsub("(#{comment})", EMPTY)
211
+ value = value.gsub("(#{comment})", Constants::EMPTY)
212
212
  end
213
213
  end
214
214
  end
@@ -228,15 +228,15 @@ module Mail
228
228
  if display_name
229
229
  str = display_name
230
230
  elsif comments
231
- str = "(#{comments.join(SPACE).squeeze(SPACE)})"
231
+ str = "(#{comments.join(Constants::SPACE).squeeze(Constants::SPACE)})"
232
232
  end
233
233
 
234
- unparen(str) unless Utilities.blank?(str)
234
+ Utilities.unparen(str) unless Utilities.blank?(str)
235
235
  end
236
236
 
237
237
  def format_comments
238
238
  if comments
239
- comment_text = comments.map {|c| escape_paren(c) }.join(SPACE).squeeze(SPACE)
239
+ comment_text = comments.map {|c| Utilities.escape_paren(c) }.join(Constants::SPACE).squeeze(Constants::SPACE)
240
240
  @format_comments ||= "(#{comment_text})"
241
241
  else
242
242
  nil
@@ -3,7 +3,7 @@
3
3
  require 'mail/parsers/address_lists_parser'
4
4
 
5
5
  module Mail
6
- class AddressList # :nodoc:
6
+ class AddressList #:nodoc:
7
7
  attr_reader :addresses, :group_names
8
8
 
9
9
  # Mail::AddressList is the class that parses To, From and other address fields from
@@ -3,7 +3,7 @@
3
3
  require 'mail/parsers/content_disposition_parser'
4
4
 
5
5
  module Mail
6
- class ContentDispositionElement # :nodoc:
6
+ class ContentDispositionElement #:nodoc:
7
7
  attr_reader :disposition_type, :parameters
8
8
 
9
9
  def initialize(string)
@@ -3,7 +3,7 @@
3
3
  require 'mail/parsers/content_location_parser'
4
4
 
5
5
  module Mail
6
- class ContentLocationElement # :nodoc:
6
+ class ContentLocationElement #:nodoc:
7
7
  attr_reader :location
8
8
 
9
9
  def initialize(string)
@@ -3,7 +3,7 @@
3
3
  require 'mail/parsers/content_transfer_encoding_parser'
4
4
 
5
5
  module Mail
6
- class ContentTransferEncodingElement
6
+ class ContentTransferEncodingElement #:nodoc:
7
7
  attr_reader :encoding
8
8
 
9
9
  def initialize(string)
@@ -3,7 +3,7 @@
3
3
  require 'mail/parsers/content_type_parser'
4
4
 
5
5
  module Mail
6
- class ContentTypeElement # :nodoc:
6
+ class ContentTypeElement #:nodoc:
7
7
  attr_reader :main_type, :sub_type, :parameters
8
8
 
9
9
  def initialize(string)
@@ -14,8 +14,12 @@ module Mail
14
14
  end
15
15
 
16
16
  private
17
- def cleaned(string)
18
- string =~ /(.+);\s*$/ ? $1 : string
19
- end
17
+ def cleaned(string)
18
+ if string =~ /;\s*$/
19
+ $`
20
+ else
21
+ string
22
+ end
23
+ end
20
24
  end
21
25
  end
@@ -3,7 +3,7 @@
3
3
  require 'mail/parsers/date_time_parser'
4
4
 
5
5
  module Mail
6
- class DateTimeElement # :nodoc:
6
+ class DateTimeElement #:nodoc:
7
7
  attr_reader :date_string, :time_string
8
8
 
9
9
  def initialize(string)
@@ -4,13 +4,13 @@ require 'mail/parsers/envelope_from_parser'
4
4
  require 'date'
5
5
 
6
6
  module Mail
7
- class EnvelopeFromElement
7
+ class EnvelopeFromElement #:nodoc:
8
8
  attr_reader :date_time, :address
9
9
 
10
10
  def initialize(string)
11
11
  envelope_from = Mail::Parsers::EnvelopeFromParser.parse(string)
12
12
  @address = envelope_from.address
13
- @date_time = ::DateTime.parse(envelope_from.ctime_date)
13
+ @date_time = ::DateTime.parse(envelope_from.ctime_date) if envelope_from.ctime_date
14
14
  end
15
15
 
16
16
  # RFC 4155:
@@ -19,15 +19,21 @@ module Mail
19
19
  # traditional UNIX 'ctime' output sans timezone (note that the
20
20
  # use of UTC precludes the need for a timezone indicator);
21
21
  def formatted_date_time
22
- if date_time.respond_to?(:ctime)
23
- date_time.ctime
24
- else
25
- date_time.strftime '%a %b %e %T %Y'
22
+ if date_time
23
+ if date_time.respond_to?(:ctime)
24
+ date_time.ctime
25
+ else
26
+ date_time.strftime '%a %b %e %T %Y'
27
+ end
26
28
  end
27
29
  end
28
30
 
29
31
  def to_s
30
- "#{address} #{formatted_date_time}"
32
+ if date_time
33
+ "#{address} #{formatted_date_time}"
34
+ else
35
+ address
36
+ end
31
37
  end
32
38
  end
33
39
  end
@@ -1,13 +1,18 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
3
  require 'mail/parsers/message_ids_parser'
4
+ require 'mail/utilities'
4
5
 
5
6
  module Mail
6
- class MessageIdsElement
7
+ class MessageIdsElement #:nodoc:
8
+ def self.parse(string)
9
+ new(string).tap(&:message_ids)
10
+ end
11
+
7
12
  attr_reader :message_ids
8
13
 
9
14
  def initialize(string)
10
- @message_ids = Mail::Parsers::MessageIdsParser.parse(string).message_ids.map { |msg_id| clean_msg_id(msg_id) }
15
+ @message_ids = parse(string)
11
16
  end
12
17
 
13
18
  def message_id
@@ -15,8 +20,12 @@ module Mail
15
20
  end
16
21
 
17
22
  private
18
- def clean_msg_id(val)
19
- val =~ /.*<(.*)>.*/ ? $1 : val
20
- end
23
+ def parse(string)
24
+ if Utilities.blank? string
25
+ []
26
+ else
27
+ Mail::Parsers::MessageIdsParser.parse(string).message_ids
28
+ end
29
+ end
21
30
  end
22
31
  end
@@ -3,7 +3,7 @@
3
3
  require 'mail/parsers/mime_version_parser'
4
4
 
5
5
  module Mail
6
- class MimeVersionElement
6
+ class MimeVersionElement #:nodoc:
7
7
  attr_reader :major, :minor
8
8
 
9
9
  def initialize(string)
@@ -4,11 +4,16 @@ require 'mail/parsers/phrase_lists_parser'
4
4
  require 'mail/utilities'
5
5
 
6
6
  module Mail
7
- class PhraseList
7
+ class PhraseList #:nodoc:
8
8
  attr_reader :phrases
9
9
 
10
10
  def initialize(string)
11
- @phrases = Mail::Parsers::PhraseListsParser.parse(string).phrases.map { |p| Mail::Utilities.unquote(p) }
11
+ @phrases =
12
+ if Utilities.blank? string
13
+ []
14
+ else
15
+ Mail::Parsers::PhraseListsParser.parse(string).phrases.map { |p| Mail::Utilities.unquote(p) }
16
+ end
12
17
  end
13
18
  end
14
19
  end
@@ -1,21 +1,35 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
3
  require 'mail/parsers/received_parser'
4
+ require 'mail/utilities'
4
5
  require 'date'
5
6
 
6
7
  module Mail
7
- class ReceivedElement
8
- include Mail::Utilities
9
- attr_reader :date_time, :info
8
+ class ReceivedElement #:nodoc:
9
+ attr_reader :info, :date_time
10
10
 
11
11
  def initialize(string)
12
- received = Mail::Parsers::ReceivedParser.parse(string)
13
- @date_time = ::DateTime.parse("#{received.date} #{received.time}")
14
- @info = received.info
12
+ if Utilities.blank? string
13
+ @date_time = nil
14
+ @info = nil
15
+ else
16
+ received = Mail::Parsers::ReceivedParser.parse(string)
17
+ @date_time = datetime_for(received)
18
+ @info = received.info
19
+ end
15
20
  end
16
21
 
17
22
  def to_s(*args)
18
23
  "#{info}; #{date_time.to_s(*args)}"
19
24
  end
25
+
26
+ private
27
+ def datetime_for(received)
28
+ ::DateTime.parse("#{received.date} #{received.time}")
29
+ rescue ArgumentError => e
30
+ raise e unless e.message == 'invalid date'
31
+ warn "WARNING: Invalid date field for received element (#{received.date} #{received.time}): #{e.class}: #{e.message}"
32
+ nil
33
+ end
20
34
  end
21
35
  end
@@ -17,6 +17,11 @@ module Mail
17
17
  def self.encode(str)
18
18
  ::Mail::Utilities.binary_unsafe_to_crlf str
19
19
  end
20
+
21
+ # Per RFC 2045 2.7. 7bit Data, No octets with decimal values greater than 127 are allowed.
22
+ def self.compatible_input?(str)
23
+ str.ascii_only? && super
24
+ end
20
25
  end
21
26
  end
22
27
  end
@@ -16,11 +16,11 @@ module Mail
16
16
  end
17
17
 
18
18
  def self.decode(str)
19
- RubyVer.decode_base64(str)
19
+ Utilities.decode_base64(str)
20
20
  end
21
21
 
22
22
  def self.encode(str)
23
- ::Mail::Utilities.binary_unsafe_to_crlf(RubyVer.encode_base64(str))
23
+ ::Mail::Utilities.binary_unsafe_to_crlf(Utilities.encode_base64(str))
24
24
  end
25
25
 
26
26
  # 3 bytes in -> 4 bytes out
@@ -16,11 +16,11 @@ 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
- 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)
23
- [str].pack("M")
23
+ ::Mail::Utilities.to_crlf [::Mail::Utilities.to_lf(str)].pack("M")
24
24
  end
25
25
 
26
26
  def self.cost(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)
@@ -52,7 +52,7 @@ module Mail
52
52
 
53
53
  def Encodings.transcode_charset(str, from_charset, to_charset = 'UTF-8')
54
54
  if from_charset
55
- RubyVer.transcode_charset str, from_charset, to_charset
55
+ Utilities.transcode_charset str, from_charset, to_charset
56
56
  else
57
57
  str
58
58
  end
@@ -65,20 +65,19 @@ module Mail
65
65
  # param_encode_language 'jp'
66
66
  # end
67
67
  #
68
- # The character set used for encoding will either be the value of $KCODE for
69
- # Ruby < 1.9 or the encoding on the string passed in.
68
+ # The character set used for encoding will be the encoding on the string passed in.
70
69
  #
71
70
  # Example:
72
71
  #
73
72
  # Mail::Encodings.param_encode("This is fun") #=> "us-ascii'en'This%20is%20fun"
74
73
  def Encodings.param_encode(str)
75
74
  case
76
- when str.ascii_only? && str =~ TOKEN_UNSAFE
75
+ when str.ascii_only? && TOKEN_UNSAFE.match?(str)
77
76
  %Q{"#{str}"}
78
77
  when str.ascii_only?
79
78
  str
80
79
  else
81
- RubyVer.param_encode(str)
80
+ Utilities.param_encode(str)
82
81
  end
83
82
  end
84
83
 
@@ -92,15 +91,15 @@ module Mail
92
91
  # str.encoding #=> 'ISO-8859-1' ## Only on Ruby 1.9
93
92
  # str #=> "This is fun"
94
93
  def Encodings.param_decode(str, encoding)
95
- RubyVer.param_decode(str, encoding)
94
+ Utilities.param_decode(str, encoding)
96
95
  end
97
96
 
98
97
  # Decodes or encodes a string as needed for either Base64 or QP encoding types in
99
98
  # the =?<encoding>?[QB]?<string>?=" format.
100
99
  #
101
100
  # The output type needs to be :decode to decode the input string or :encode to
102
- # encode the input string. The character set used for encoding will either be
103
- # the value of $KCODE for Ruby < 1.9 or the encoding on the string passed in.
101
+ # encode the input string. The character set used for encoding will be the
102
+ # encoding on the string passed in.
104
103
  #
105
104
  # On encoding, will only send out Base64 encoded strings.
106
105
  def Encodings.decode_encode(str, output_type)
@@ -111,7 +110,7 @@ module Mail
111
110
  if str.ascii_only?
112
111
  str
113
112
  else
114
- Encodings.b_value_encode(str, find_encoding(str))
113
+ Encodings.b_value_encode(str, str.encoding)
115
114
  end
116
115
  end
117
116
  end
@@ -122,7 +121,7 @@ module Mail
122
121
  # String has to be of the format =?<encoding>?[QB]?<string>?=
123
122
  def Encodings.value_decode(str)
124
123
  # Optimization: If there's no encoded-words in the string, just return it
125
- return str unless str =~ ENCODED_VALUE
124
+ return str unless ENCODED_VALUE.match?(str)
126
125
 
127
126
  lines = collapse_adjacent_encodings(str)
128
127
 
@@ -145,13 +144,8 @@ module Mail
145
144
  output
146
145
  elsif to_encoding
147
146
  begin
148
- if RUBY_VERSION >= '1.9'
149
- output.encode(to_encoding)
150
- else
151
- require 'iconv'
152
- Iconv.iconv(to_encoding, 'UTF-8', output).first
153
- end
154
- rescue Iconv::IllegalSequence, Iconv::InvalidEncoding, Errno::EINVAL
147
+ output.encode(to_encoding)
148
+ rescue Errno::EINVAL
155
149
  # the 'from' parameter specifies a charset other than what the text
156
150
  # actually is...not much we can do in this case but just return the
157
151
  # unconverted text.
@@ -176,42 +170,23 @@ module Mail
176
170
  def Encodings.encode_non_usascii(address, charset)
177
171
  return address if address.ascii_only? or charset.nil?
178
172
 
179
- # With KCODE=u we can't use regexps on other encodings. Go ASCII.
180
- with_ascii_kcode do
181
- # Encode all strings embedded inside of quotes
182
- address = address.gsub(/("[^"]*[^\/]")/) { |s| Encodings.b_value_encode(unquote(s), charset) }
183
-
184
- # Then loop through all remaining items and encode as needed
185
- tokens = address.split(/\s/)
186
-
187
- map_with_index(tokens) do |word, i|
188
- if word.ascii_only?
189
- word
190
- else
191
- previous_non_ascii = i>0 && tokens[i-1] && !tokens[i-1].ascii_only?
192
- if previous_non_ascii #why are we adding an extra space here?
193
- word = " #{word}"
194
- end
195
- Encodings.b_value_encode(word, charset)
196
- end
197
- end.join(' ')
198
- end
199
- end
173
+ # Encode all strings embedded inside of quotes
174
+ address = address.gsub(/("[^"]*[^\/]")/) { |s| Encodings.b_value_encode(unquote(s), charset) }
175
+
176
+ # Then loop through all remaining items and encode as needed
177
+ tokens = address.split(/\s/)
200
178
 
201
- if RUBY_VERSION < '1.9'
202
- # With KCODE=u we can't use regexps on other encodings. Go ASCII.
203
- def Encodings.with_ascii_kcode #:nodoc:
204
- if $KCODE
205
- $KCODE, original_kcode = '', $KCODE
179
+ map_with_index(tokens) do |word, i|
180
+ if word.ascii_only?
181
+ word
182
+ else
183
+ previous_non_ascii = i>0 && tokens[i-1] && !tokens[i-1].ascii_only?
184
+ if previous_non_ascii #why are we adding an extra space here?
185
+ word = " #{word}"
186
+ end
187
+ Encodings.b_value_encode(word, charset)
206
188
  end
207
- yield
208
- ensure
209
- $KCODE = original_kcode if original_kcode
210
- end
211
- else
212
- def Encodings.with_ascii_kcode #:nodoc:
213
- yield
214
- end
189
+ end.join(' ')
215
190
  end
216
191
 
217
192
  # Encode a string with Base64 Encoding and returns it ready to be inserted
@@ -226,7 +201,7 @@ module Mail
226
201
  string
227
202
  else
228
203
  Encodings.each_base64_chunk_byterange(string, 60).map do |chunk|
229
- str, encoding = RubyVer.b_value_encode(chunk, encoding)
204
+ str, encoding = Utilities.b_value_encode(chunk, encoding)
230
205
  "=?#{encoding}?B?#{str.chomp}?="
231
206
  end.join(" ")
232
207
  end
@@ -241,7 +216,7 @@ module Mail
241
216
  # #=> "=?UTF-8?Q?This_is_=E3=81=82_string?="
242
217
  def Encodings.q_value_encode(encoded_str, encoding = nil)
243
218
  return encoded_str if encoded_str.to_s.ascii_only?
244
- string, encoding = RubyVer.q_value_encode(encoded_str, encoding)
219
+ string, encoding = Utilities.q_value_encode(encoded_str, encoding)
245
220
  string.gsub!("=\r\n", '') # We already have limited the string to the length we want
246
221
  map_lines(string) do |str|
247
222
  "=?#{encoding}?Q?#{str.chomp.gsub(/ /, '_')}?="
@@ -257,7 +232,7 @@ module Mail
257
232
  # Encodings.b_value_decode("=?UTF-8?B?VGhpcyBpcyDjgYIgc3RyaW5n?=")
258
233
  # #=> 'This is あ string'
259
234
  def Encodings.b_value_decode(str)
260
- RubyVer.b_value_decode(str)
235
+ Utilities.b_value_decode(str)
261
236
  end
262
237
 
263
238
  # Decodes a Quoted-Printable string from the "=?UTF-8?Q?This_is_=E3=81=82_string?=" format
@@ -267,11 +242,7 @@ module Mail
267
242
  # Encodings.q_value_decode("=?UTF-8?Q?This_is_=E3=81=82_string?=")
268
243
  # #=> 'This is あ string'
269
244
  def Encodings.q_value_decode(str)
270
- RubyVer.q_value_decode(str)
271
- end
272
-
273
- def Encodings.find_encoding(str)
274
- RUBY_VERSION >= '1.9' ? str.encoding : $KCODE
245
+ Utilities.q_value_decode(str)
275
246
  end
276
247
 
277
248
  # Gets the encoding type (Q or B) from the string.
@@ -329,7 +300,7 @@ module Mail
329
300
  charsize = chr.bytesize
330
301
 
331
302
  if chunksize + charsize > max_bytesize_per_chunk
332
- yield RubyVer.string_byteslice(str, offset, chunksize)
303
+ yield Utilities.string_byteslice(str, offset, chunksize)
333
304
  offset += chunksize
334
305
  chunksize = charsize
335
306
  else
@@ -337,7 +308,7 @@ module Mail
337
308
  end
338
309
  end
339
310
 
340
- yield RubyVer.string_byteslice(str, offset, chunksize)
311
+ yield Utilities.string_byteslice(str, offset, chunksize)
341
312
  end
342
313
  end
343
314
  end
data/lib/mail/envelope.rb CHANGED
@@ -1,31 +1,28 @@
1
1
  # encoding: utf-8
2
2
  # frozen_string_literal: true
3
- #
3
+ #
4
4
  # = Mail Envelope
5
- #
5
+ #
6
6
  # The Envelope class provides a field for the first line in an
7
7
  # mbox file, that looks like "From mikel@test.lindsaar.net DATETIME"
8
- #
8
+ #
9
9
  # This envelope class reads that line, and turns it into an
10
10
  # Envelope.from and Envelope.date for your use.
11
+
11
12
  module Mail
12
- class Envelope < StructuredField
13
-
14
- def initialize(*args)
15
- super(FIELD_NAME, args.last.to_s)
16
- end
17
-
13
+ class Envelope < NamedStructuredField
14
+ NAME = 'Envelope-From'
15
+
18
16
  def element
19
17
  @element ||= Mail::EnvelopeFromElement.new(value)
20
18
  end
21
-
22
- def date
23
- ::DateTime.parse("#{element.date_time}")
24
- end
25
19
 
26
20
  def from
27
21
  element.address
28
22
  end
29
-
23
+
24
+ def date
25
+ element.date_time
26
+ end
30
27
  end
31
28
  end