net-imap 0.4.17 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,13 +14,6 @@ module Net
14
14
  # receive a SequenceSet as an argument, for example IMAP#search, IMAP#fetch,
15
15
  # and IMAP#store.
16
16
  #
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
17
  # == Creating sequence sets
25
18
  #
26
19
  # SequenceSet.new with no arguments creates an empty sequence set. Note
@@ -37,7 +30,8 @@ module Net
37
30
  #
38
31
  # SequenceSet.new may receive a single optional argument: a non-zero 32 bit
39
32
  # unsigned integer, a range, a <tt>sequence-set</tt> formatted string,
40
- # another sequence set, or an enumerable containing any of these.
33
+ # another sequence set, a Set (containing only numbers or <tt>*</tt>), or an
34
+ # Array containing any of these (array inputs may be nested).
41
35
  #
42
36
  # set = Net::IMAP::SequenceSet.new(1)
43
37
  # set.valid_string #=> "1"
@@ -289,8 +283,7 @@ module Net
289
283
  private_constant :STAR_INT, :STARS
290
284
 
291
285
  COERCIBLE = ->{ _1.respond_to? :to_sequence_set }
292
- ENUMABLE = ->{ _1.respond_to?(:each) && _1.respond_to?(:empty?) }
293
- private_constant :COERCIBLE, :ENUMABLE
286
+ private_constant :COERCIBLE
294
287
 
295
288
  class << self
296
289
 
@@ -1272,7 +1265,8 @@ module Net
1272
1265
  when *STARS, Integer, Range then [input_to_tuple(obj)]
1273
1266
  when String then str_to_tuples obj
1274
1267
  when SequenceSet then obj.tuples
1275
- when ENUMABLE then obj.flat_map { input_to_tuples _1 }
1268
+ when Set then obj.map { [to_tuple_int(_1)] * 2 }
1269
+ when Array then obj.flat_map { input_to_tuples _1 }
1276
1270
  when nil then []
1277
1271
  else
1278
1272
  raise DataFormatError,
@@ -1285,8 +1279,7 @@ module Net
1285
1279
  # String, Set, Array, or... any type of object.
1286
1280
  def input_try_convert(input)
1287
1281
  SequenceSet.try_convert(input) ||
1288
- # Integer.try_convert(input) || # ruby 3.1+
1289
- input.respond_to?(:to_int) && Integer(input.to_int) ||
1282
+ Integer.try_convert(input) ||
1290
1283
  String.try_convert(input) ||
1291
1284
  input
1292
1285
  end
@@ -1416,12 +1409,11 @@ module Net
1416
1409
  end
1417
1410
 
1418
1411
  def nz_number(num)
1419
- case num
1420
- when Integer, /\A[1-9]\d*\z/ then num = Integer(num)
1421
- else raise DataFormatError, "%p is not a valid nz-number" % [num]
1422
- end
1423
- NumValidator.ensure_nz_number(num)
1424
- num
1412
+ String === num && !/\A[1-9]\d*\z/.match?(num) and
1413
+ raise DataFormatError, "%p is not a valid nz-number" % [num]
1414
+ NumValidator.ensure_nz_number Integer num
1415
+ rescue TypeError # To catch errors from Integer()
1416
+ raise DataFormatError, $!.message
1425
1417
  end
1426
1418
 
1427
1419
  # intentionally defined after the class implementation
data/lib/net/imap.rb CHANGED
@@ -719,7 +719,7 @@ module Net
719
719
  # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
720
720
  #
721
721
  class IMAP < Protocol
722
- VERSION = "0.4.17"
722
+ VERSION = "0.5.0"
723
723
 
724
724
  # Aliases for supported capabilities, to be used with the #enable command.
725
725
  ENABLE_ALIASES = {
@@ -946,9 +946,6 @@ module Net
946
946
  @sock = tcp_socket(@host, @port)
947
947
  start_tls_session if ssl_ctx
948
948
  start_imap_connection
949
-
950
- # DEPRECATED: to remove in next version
951
- @client_thread = Thread.current
952
949
  end
953
950
 
954
951
  # Returns true after the TLS negotiation has completed and the remote
@@ -956,11 +953,6 @@ module Net
956
953
  # but peer verification was disabled.
957
954
  def tls_verified?; @tls_verified end
958
955
 
959
- def client_thread # :nodoc:
960
- warn "Net::IMAP#client_thread is deprecated and will be removed soon."
961
- @client_thread
962
- end
963
-
964
956
  # Disconnects from the server.
965
957
  #
966
958
  # Related: #logout, #logout!
@@ -1244,6 +1236,9 @@ module Net
1244
1236
  # +SASL-IR+ capability, below). Defaults to the #config value for
1245
1237
  # {sasl_ir}[rdoc-ref:Config#sasl_ir], which defaults to +true+.
1246
1238
  #
1239
+ # The +registry+ kwarg can be used to select the mechanism implementation
1240
+ # from a custom registry. See SASL.authenticator and SASL::Authenticators.
1241
+ #
1247
1242
  # All other arguments are forwarded to the registered SASL authenticator for
1248
1243
  # the requested mechanism. <em>The documentation for each individual
1249
1244
  # mechanism must be consulted for its specific parameters.</em>
@@ -1338,29 +1333,9 @@ module Net
1338
1333
  # Previously cached #capabilities will be cleared when this method
1339
1334
  # completes. If the TaggedResponse to #authenticate includes updated
1340
1335
  # capabilities, they will be cached.
1341
- def authenticate(mechanism, *creds,
1342
- sasl_ir: config.sasl_ir,
1343
- **props, &callback)
1344
- mechanism = mechanism.to_s.tr("_", "-").upcase
1345
- authenticator = SASL.authenticator(mechanism, *creds, **props, &callback)
1346
- cmdargs = ["AUTHENTICATE", mechanism]
1347
- if sasl_ir && capable?("SASL-IR") && auth_capable?(mechanism) &&
1348
- authenticator.respond_to?(:initial_response?) &&
1349
- authenticator.initial_response?
1350
- response = authenticator.process(nil)
1351
- cmdargs << (response.empty? ? "=" : [response].pack("m0"))
1352
- end
1353
- result = send_command_with_continuations(*cmdargs) {|data|
1354
- challenge = data.unpack1("m")
1355
- response = authenticator.process challenge
1356
- [response].pack("m0")
1357
- }
1358
- if authenticator.respond_to?(:done?) && !authenticator.done?
1359
- logout!
1360
- raise SASL::AuthenticationIncomplete, result
1361
- end
1362
- @capabilities = capabilities_from_resp_code result
1363
- result
1336
+ def authenticate(*args, sasl_ir: config.sasl_ir, **props, &callback)
1337
+ sasl_adapter.authenticate(*args, sasl_ir: sasl_ir, **props, &callback)
1338
+ .tap { @capabilities = capabilities_from_resp_code _1 }
1364
1339
  end
1365
1340
 
1366
1341
  # Sends a {LOGIN command [IMAP4rev1 §6.2.3]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.3]
@@ -1380,13 +1355,9 @@ module Net
1380
1355
  # ===== Capabilities
1381
1356
  #
1382
1357
  # An IMAP client MUST NOT call #login when the server advertises the
1383
- # +LOGINDISABLED+ capability.
1384
- #
1385
- # if imap.capability? "LOGINDISABLED"
1386
- # raise "Remote server has disabled the login command"
1387
- # else
1388
- # imap.login username, password
1389
- # end
1358
+ # +LOGINDISABLED+ capability. By default, Net::IMAP will raise a
1359
+ # LoginDisabledError when that capability is present. See
1360
+ # Config#enforce_logindisabled.
1390
1361
  #
1391
1362
  # Server capabilities may change after #starttls, #login, and #authenticate.
1392
1363
  # Cached capabilities _must_ be invalidated after this method completes.
@@ -1394,6 +1365,9 @@ module Net
1394
1365
  # ResponseCode.
1395
1366
  #
1396
1367
  def login(user, password)
1368
+ if enforce_logindisabled? && capability?("LOGINDISABLED")
1369
+ raise LoginDisabledError
1370
+ end
1397
1371
  send_command("LOGIN", user, password)
1398
1372
  .tap { @capabilities = capabilities_from_resp_code _1 }
1399
1373
  end
@@ -1950,7 +1924,7 @@ module Net
1950
1924
  # [RFC4315[https://www.rfc-editor.org/rfc/rfc4315.html]].
1951
1925
  def uid_expunge(uid_set)
1952
1926
  synchronize do
1953
- send_command("UID EXPUNGE", MessageSet.new(uid_set))
1927
+ send_command("UID EXPUNGE", SequenceSet.new(uid_set))
1954
1928
  clear_responses("EXPUNGE")
1955
1929
  end
1956
1930
  end
@@ -2608,7 +2582,7 @@ module Net
2608
2582
  when :raise
2609
2583
  raise ArgumentError, RESPONSES_DEPRECATION_MSG
2610
2584
  when :warn
2611
- warn(RESPONSES_DEPRECATION_MSG, uplevel: 1)
2585
+ warn(RESPONSES_DEPRECATION_MSG, uplevel: 1, category: :deprecated)
2612
2586
  when :frozen_dup
2613
2587
  synchronize {
2614
2588
  responses = @responses.transform_values(&:freeze)
@@ -2957,6 +2931,14 @@ module Net
2957
2931
  end
2958
2932
  end
2959
2933
 
2934
+ def enforce_logindisabled?
2935
+ if config.enforce_logindisabled == :when_capabilities_cached
2936
+ capabilities_cached?
2937
+ else
2938
+ config.enforce_logindisabled
2939
+ end
2940
+ end
2941
+
2960
2942
  def search_internal(cmd, keys, charset)
2961
2943
  if keys.instance_of?(String)
2962
2944
  keys = [RawData.new(keys)]
@@ -2990,9 +2972,9 @@ module Net
2990
2972
  synchronize do
2991
2973
  clear_responses("FETCH")
2992
2974
  if mod
2993
- send_command(cmd, MessageSet.new(set), attr, mod)
2975
+ send_command(cmd, SequenceSet.new(set), attr, mod)
2994
2976
  else
2995
- send_command(cmd, MessageSet.new(set), attr)
2977
+ send_command(cmd, SequenceSet.new(set), attr)
2996
2978
  end
2997
2979
  clear_responses("FETCH")
2998
2980
  end
@@ -3000,7 +2982,7 @@ module Net
3000
2982
 
3001
2983
  def store_internal(cmd, set, attr, flags, unchangedsince: nil)
3002
2984
  attr = RawData.new(attr) if attr.instance_of?(String)
3003
- args = [MessageSet.new(set)]
2985
+ args = [SequenceSet.new(set)]
3004
2986
  args << ["UNCHANGEDSINCE", Integer(unchangedsince)] if unchangedsince
3005
2987
  args << attr << flags
3006
2988
  synchronize do
@@ -3011,7 +2993,7 @@ module Net
3011
2993
  end
3012
2994
 
3013
2995
  def copy_internal(cmd, set, mailbox)
3014
- send_command(cmd, MessageSet.new(set), mailbox)
2996
+ send_command(cmd, SequenceSet.new(set), mailbox)
3015
2997
  end
3016
2998
 
3017
2999
  def sort_internal(cmd, sort_keys, search_keys, charset)
@@ -3042,7 +3024,7 @@ module Net
3042
3024
  keys.collect! do |i|
3043
3025
  case i
3044
3026
  when -1, Range, Array
3045
- MessageSet.new(i)
3027
+ SequenceSet.new(i)
3046
3028
  else
3047
3029
  i
3048
3030
  end
data/net-imap.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.summary = %q{Ruby client api for Internet Message Access Protocol}
17
17
  spec.description = %q{Ruby client api for Internet Message Access Protocol}
18
18
  spec.homepage = "https://github.com/ruby/net-imap"
19
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7.3")
19
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
20
20
  spec.licenses = ["Ruby", "BSD-2-Clause"]
21
21
 
22
22
  spec.metadata["homepage_uri"] = spec.homepage
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-imap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.17
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
8
8
  - nicholas a. evans
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2024-10-13 00:00:00.000000000 Z
12
+ date: 2024-10-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-protocol
@@ -110,7 +110,7 @@ metadata:
110
110
  homepage_uri: https://github.com/ruby/net-imap
111
111
  source_code_uri: https://github.com/ruby/net-imap
112
112
  changelog_uri: https://github.com/ruby/net-imap/releases
113
- post_install_message:
113
+ post_install_message:
114
114
  rdoc_options: []
115
115
  require_paths:
116
116
  - lib
@@ -118,7 +118,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
118
118
  requirements:
119
119
  - - ">="
120
120
  - !ruby/object:Gem::Version
121
- version: 2.7.3
121
+ version: 3.1.0
122
122
  required_rubygems_version: !ruby/object:Gem::Requirement
123
123
  requirements:
124
124
  - - ">="
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  version: '0'
127
127
  requirements: []
128
128
  rubygems_version: 3.5.16
129
- signing_key:
129
+ signing_key:
130
130
  specification_version: 4
131
131
  summary: Ruby client api for Internet Message Access Protocol
132
132
  test_files: []