net-imap 0.4.12 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of net-imap might be problematic. Click here for more details.

Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -1
  3. data/README.md +10 -4
  4. data/docs/styles.css +75 -14
  5. data/lib/net/imap/authenticators.rb +2 -2
  6. data/lib/net/imap/command_data.rb +61 -48
  7. data/lib/net/imap/config/attr_accessors.rb +75 -0
  8. data/lib/net/imap/config/attr_inheritance.rb +90 -0
  9. data/lib/net/imap/config/attr_type_coercion.rb +61 -0
  10. data/lib/net/imap/config.rb +402 -0
  11. data/lib/net/imap/data_encoding.rb +3 -3
  12. data/lib/net/imap/data_lite.rb +226 -0
  13. data/lib/net/imap/deprecated_client_options.rb +8 -5
  14. data/lib/net/imap/errors.rb +6 -0
  15. data/lib/net/imap/esearch_result.rb +180 -0
  16. data/lib/net/imap/fetch_data.rb +126 -47
  17. data/lib/net/imap/response_data.rb +126 -193
  18. data/lib/net/imap/response_parser/parser_utils.rb +11 -6
  19. data/lib/net/imap/response_parser.rb +159 -21
  20. data/lib/net/imap/sasl/anonymous_authenticator.rb +3 -3
  21. data/lib/net/imap/sasl/authentication_exchange.rb +52 -20
  22. data/lib/net/imap/sasl/authenticators.rb +8 -4
  23. data/lib/net/imap/sasl/client_adapter.rb +77 -26
  24. data/lib/net/imap/sasl/cram_md5_authenticator.rb +4 -4
  25. data/lib/net/imap/sasl/digest_md5_authenticator.rb +218 -56
  26. data/lib/net/imap/sasl/external_authenticator.rb +2 -2
  27. data/lib/net/imap/sasl/gs2_header.rb +7 -7
  28. data/lib/net/imap/sasl/login_authenticator.rb +4 -3
  29. data/lib/net/imap/sasl/oauthbearer_authenticator.rb +6 -6
  30. data/lib/net/imap/sasl/plain_authenticator.rb +7 -7
  31. data/lib/net/imap/sasl/protocol_adapters.rb +60 -4
  32. data/lib/net/imap/sasl/scram_authenticator.rb +8 -8
  33. data/lib/net/imap/sasl.rb +7 -4
  34. data/lib/net/imap/sasl_adapter.rb +0 -1
  35. data/lib/net/imap/search_result.rb +2 -2
  36. data/lib/net/imap/sequence_set.rb +28 -24
  37. data/lib/net/imap/stringprep/nameprep.rb +1 -1
  38. data/lib/net/imap/stringprep/trace.rb +4 -4
  39. data/lib/net/imap/vanished_data.rb +56 -0
  40. data/lib/net/imap.rb +1001 -319
  41. data/net-imap.gemspec +3 -3
  42. data/rakelib/rfcs.rake +2 -0
  43. data/rakelib/string_prep_tables_generator.rb +2 -0
  44. metadata +11 -10
  45. data/.github/dependabot.yml +0 -6
  46. data/.github/workflows/pages.yml +0 -46
  47. data/.github/workflows/push_gem.yml +0 -48
  48. data/.github/workflows/test.yml +0 -31
  49. data/.gitignore +0 -12
  50. data/.mailmap +0 -13
@@ -100,10 +100,10 @@ module Net
100
100
  # data.to_s("SORT") # => "* SORT 2 8 32 128 256 512"
101
101
  # data.to_s(nil) # => "2 8 32 128 256 512"
102
102
  #
103
- # data = Net::IMAP::SearchResult[1, 3, 16, 1024, modseq: 2048].to_s
103
+ # data = Net::IMAP::SearchResult[1, 3, 16, 1024, modseq: 2048]
104
104
  # data.to_s # => "* SEARCH 1 3 16 1024 (MODSEQ 2048)"
105
105
  # data.to_s("SORT") # => "* SORT 1 3 16 1024 (MODSEQ 2048)"
106
- # data.to_s # => "1 3 16 1024 (MODSEQ 2048)"
106
+ # data.to_s(nil) # => "1 3 16 1024 (MODSEQ 2048)"
107
107
  #
108
108
  def to_s(type = "SEARCH")
109
109
  str = +""
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set" unless defined?(::Set)
4
+
3
5
  module Net
4
6
  class IMAP
5
7
 
@@ -14,13 +16,6 @@ module Net
14
16
  # receive a SequenceSet as an argument, for example IMAP#search, IMAP#fetch,
15
17
  # and IMAP#store.
16
18
  #
17
- # == EXPERIMENTAL API
18
- #
19
- # SequenceSet is currently experimental. Only two methods, ::[] and
20
- # #valid_string, are considered stable. Although the API isn't expected to
21
- # change much, any other methods may be removed or changed without
22
- # deprecation.
23
- #
24
19
  # == Creating sequence sets
25
20
  #
26
21
  # SequenceSet.new with no arguments creates an empty sequence set. Note
@@ -37,7 +32,8 @@ module Net
37
32
  #
38
33
  # SequenceSet.new may receive a single optional argument: a non-zero 32 bit
39
34
  # unsigned integer, a range, a <tt>sequence-set</tt> formatted string,
40
- # another sequence set, or an enumerable containing any of these.
35
+ # another sequence set, a Set (containing only numbers or <tt>*</tt>), or an
36
+ # Array containing any of these (array inputs may be nested).
41
37
  #
42
38
  # set = Net::IMAP::SequenceSet.new(1)
43
39
  # set.valid_string #=> "1"
@@ -286,11 +282,7 @@ module Net
286
282
 
287
283
  # valid inputs for "*"
288
284
  STARS = [:*, ?*, -1].freeze
289
- private_constant :STAR_INT, :STARS
290
-
291
- COERCIBLE = ->{ _1.respond_to? :to_sequence_set }
292
- ENUMABLE = ->{ _1.respond_to?(:each) && _1.respond_to?(:empty?) }
293
- private_constant :COERCIBLE, :ENUMABLE
285
+ private_constant :STARS
294
286
 
295
287
  class << self
296
288
 
@@ -304,7 +296,7 @@ module Net
304
296
  # Use ::new to create a mutable or empty SequenceSet.
305
297
  def [](first, *rest)
306
298
  if rest.empty?
307
- if first.is_a?(SequenceSet) && set.frozen? && set.valid?
299
+ if first.is_a?(SequenceSet) && first.frozen? && first.valid?
308
300
  first
309
301
  else
310
302
  new(first).validate.freeze
@@ -325,7 +317,7 @@ module Net
325
317
  # raised.
326
318
  def try_convert(obj)
327
319
  return obj if obj.is_a?(SequenceSet)
328
- return nil unless respond_to?(:to_sequence_set)
320
+ return nil unless obj.respond_to?(:to_sequence_set)
329
321
  obj = obj.to_sequence_set
330
322
  return obj if obj.is_a?(SequenceSet)
331
323
  raise DataFormatError, "invalid object returned from to_sequence_set"
@@ -389,6 +381,10 @@ module Net
389
381
  # Related: #valid_string, #normalized_string, #to_s
390
382
  def string; @string ||= normalized_string if valid? end
391
383
 
384
+ # Returns an array with #normalized_string when valid and an empty array
385
+ # otherwise.
386
+ def deconstruct; valid? ? [normalized_string] : [] end
387
+
392
388
  # Assigns a new string to #string and resets #elements to match. It
393
389
  # cannot be set to an empty string—assign +nil+ or use #clear instead.
394
390
  # The string is validated but not normalized.
@@ -682,6 +678,7 @@ module Net
682
678
  # Unlike #add, #merge, or #union, the new value is appended to #string.
683
679
  # This may result in a #string which has duplicates or is out-of-order.
684
680
  def append(object)
681
+ modifying!
685
682
  tuple = input_to_tuple object
686
683
  entry = tuple_to_str tuple
687
684
  tuple_add tuple
@@ -1271,7 +1268,8 @@ module Net
1271
1268
  when *STARS, Integer, Range then [input_to_tuple(obj)]
1272
1269
  when String then str_to_tuples obj
1273
1270
  when SequenceSet then obj.tuples
1274
- when ENUMABLE then obj.flat_map { input_to_tuples _1 }
1271
+ when Set then obj.map { [to_tuple_int(_1)] * 2 }
1272
+ when Array then obj.flat_map { input_to_tuples _1 }
1275
1273
  when nil then []
1276
1274
  else
1277
1275
  raise DataFormatError,
@@ -1284,8 +1282,7 @@ module Net
1284
1282
  # String, Set, Array, or... any type of object.
1285
1283
  def input_try_convert(input)
1286
1284
  SequenceSet.try_convert(input) ||
1287
- # Integer.try_convert(input) || # ruby 3.1+
1288
- input.respond_to?(:to_int) && Integer(input.to_int) ||
1285
+ Integer.try_convert(input) ||
1289
1286
  String.try_convert(input) ||
1290
1287
  input
1291
1288
  end
@@ -1317,6 +1314,12 @@ module Net
1317
1314
  range.include?(min) || range.include?(max) || (min..max).cover?(range)
1318
1315
  end
1319
1316
 
1317
+ def modifying!
1318
+ if frozen?
1319
+ raise FrozenError, "can't modify frozen #{self.class}: %p" % [self]
1320
+ end
1321
+ end
1322
+
1320
1323
  def tuples_add(tuples) tuples.each do tuple_add _1 end; self end
1321
1324
  def tuples_subtract(tuples) tuples.each do tuple_subtract _1 end; self end
1322
1325
 
@@ -1331,6 +1334,7 @@ module Net
1331
1334
  # ---------??===lower==|--|==|----|===upper===|-- join until upper
1332
1335
  # ---------??===lower==|--|==|--|=====upper===|-- join to upper
1333
1336
  def tuple_add(tuple)
1337
+ modifying!
1334
1338
  min, max = tuple
1335
1339
  lower, lower_idx = tuple_gte_with_index(min - 1)
1336
1340
  if lower.nil? then tuples << tuple
@@ -1367,6 +1371,7 @@ module Net
1367
1371
  # -------??=====lower====|--|====|---|====upper====|-- 7. delete until
1368
1372
  # -------??=====lower====|--|====|--|=====upper====|-- 8. delete and trim
1369
1373
  def tuple_subtract(tuple)
1374
+ modifying!
1370
1375
  min, max = tuple
1371
1376
  lower, idx = tuple_gte_with_index(min)
1372
1377
  if lower.nil? then nil # case 1.
@@ -1407,12 +1412,11 @@ module Net
1407
1412
  end
1408
1413
 
1409
1414
  def nz_number(num)
1410
- case num
1411
- when Integer, /\A[1-9]\d*\z/ then num = Integer(num)
1412
- else raise DataFormatError, "%p is not a valid nz-number" % [num]
1413
- end
1414
- NumValidator.ensure_nz_number(num)
1415
- num
1415
+ String === num && !/\A[1-9]\d*\z/.match?(num) and
1416
+ raise DataFormatError, "%p is not a valid nz-number" % [num]
1417
+ NumValidator.ensure_nz_number Integer num
1418
+ rescue TypeError # To catch errors from Integer()
1419
+ raise DataFormatError, $!.message
1416
1420
  end
1417
1421
 
1418
1422
  # intentionally defined after the class implementation
@@ -4,7 +4,7 @@ module Net
4
4
  class IMAP
5
5
  module StringPrep
6
6
 
7
- # Defined in RFC3491[https://tools.ietf.org/html/rfc3491], the +nameprep+
7
+ # Defined in RFC3491[https://www.rfc-editor.org/rfc/rfc3491], the +nameprep+
8
8
  # profile of "Stringprep" is:
9
9
  # >>>
10
10
  # used by the IDNA protocol for preparing domain names; it is not
@@ -4,11 +4,11 @@ module Net
4
4
  class IMAP
5
5
  module StringPrep
6
6
 
7
- # Defined in RFC-4505[https://tools.ietf.org/html/rfc4505] §3, The +trace+
7
+ # Defined in RFC-4505[https://www.rfc-editor.org/rfc/rfc4505] §3, The +trace+
8
8
  # profile of \StringPrep is used by the +ANONYMOUS+ \SASL mechanism.
9
9
  module Trace
10
10
 
11
- # Defined in RFC-4505[https://tools.ietf.org/html/rfc4505] §3.
11
+ # Defined in RFC-4505[https://www.rfc-editor.org/rfc/rfc4505] §3.
12
12
  STRINGPREP_PROFILE = "trace"
13
13
 
14
14
  # >>>
@@ -23,7 +23,7 @@ module Net
23
23
  # No Unicode normalization is required by this profile.
24
24
  NORMALIZATION = nil
25
25
 
26
- # From RFC-4505[https://tools.ietf.org/html/rfc4505] §3, The "trace"
26
+ # From RFC-4505[https://www.rfc-editor.org/rfc/rfc4505] §3, The "trace"
27
27
  # Profile of "Stringprep":
28
28
  # >>>
29
29
  # Characters from the following tables of [StringPrep] are prohibited:
@@ -47,7 +47,7 @@ module Net
47
47
 
48
48
  module_function
49
49
 
50
- # From RFC-4505[https://tools.ietf.org/html/rfc4505] §3, The "trace"
50
+ # From RFC-4505[https://www.rfc-editor.org/rfc/rfc4505] §3, The "trace"
51
51
  # Profile of "Stringprep":
52
52
  # >>>
53
53
  # The character repertoire of this profile is Unicode 3.2 [Unicode].
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Net
4
+ class IMAP < Protocol
5
+
6
+ # Net::IMAP::VanishedData represents the contents of a +VANISHED+ response,
7
+ # which is described by the
8
+ # {QRESYNC}[https://www.rfc-editor.org/rfc/rfc7162.html] extension.
9
+ # [{RFC7162 §3.2.10}[https://www.rfc-editor.org/rfc/rfc7162.html#section-3.2.10]].
10
+ #
11
+ # +VANISHED+ responses replace +EXPUNGE+ responses when either the
12
+ # {QRESYNC}[https://www.rfc-editor.org/rfc/rfc7162.html] or the
13
+ # {UIDONLY}[https://www.rfc-editor.org/rfc/rfc9586.html] extension has been
14
+ # enabled.
15
+ class VanishedData < Data.define(:uids, :earlier)
16
+
17
+ # Returns a new VanishedData object.
18
+ #
19
+ # * +uids+ will be converted by SequenceSet.[].
20
+ # * +earlier+ will be converted to +true+ or +false+
21
+ def initialize(uids:, earlier:)
22
+ uids = SequenceSet[uids]
23
+ earlier = !!earlier
24
+ super
25
+ end
26
+
27
+ ##
28
+ # :attr_reader: uids
29
+ #
30
+ # SequenceSet of UIDs that have been permanently removed from the mailbox.
31
+
32
+ ##
33
+ # :attr_reader: earlier
34
+ #
35
+ # +true+ when the response was caused by Net::IMAP#uid_fetch with
36
+ # <tt>vanished: true</tt> or Net::IMAP#select/Net::IMAP#examine with
37
+ # <tt>qresync: true</tt>.
38
+ #
39
+ # +false+ when the response is used to announce message removals within an
40
+ # already selected mailbox.
41
+
42
+ # rdoc doesn't handle attr aliases nicely. :(
43
+ alias earlier? earlier # :nodoc:
44
+ ##
45
+ # :attr_reader: earlier?
46
+ #
47
+ # Alias for #earlier.
48
+
49
+ # Returns an Array of all of the UIDs in #uids.
50
+ #
51
+ # See SequenceSet#numbers.
52
+ def to_a; uids.numbers end
53
+
54
+ end
55
+ end
56
+ end