net-imap 0.4.1 → 0.4.4

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.

Potentially problematic release.


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

data/lib/net/imap.rb CHANGED
@@ -662,7 +662,7 @@ module Net
662
662
  # * {IMAP URLAUTH Authorization Mechanism Registry}[https://www.iana.org/assignments/urlauth-authorization-mechanism-registry/urlauth-authorization-mechanism-registry.xhtml]
663
663
  #
664
664
  class IMAP < Protocol
665
- VERSION = "0.4.1"
665
+ VERSION = "0.4.4"
666
666
 
667
667
  # Aliases for supported capabilities, to be used with the #enable command.
668
668
  ENABLE_ALIASES = {
@@ -1045,7 +1045,7 @@ module Net
1045
1045
  # ===== Capabilities
1046
1046
  #
1047
1047
  # The server's capabilities must include +ID+
1048
- # [RFC2971[https://tools.ietf.org/html/rfc2971]]
1048
+ # [RFC2971[https://tools.ietf.org/html/rfc2971]].
1049
1049
  def id(client_id=nil)
1050
1050
  synchronize do
1051
1051
  send_command("ID", ClientID.new(client_id))
@@ -1058,7 +1058,7 @@ module Net
1058
1058
  #
1059
1059
  # This allows the server to send unsolicited untagged EXPUNGE #responses,
1060
1060
  # but does not execute any client request. \IMAP servers are permitted to
1061
- # send unsolicited untagged responses at any time, except for `EXPUNGE`.
1061
+ # send unsolicited untagged responses at any time, except for +EXPUNGE+:
1062
1062
  #
1063
1063
  # * +EXPUNGE+ can only be sent while a command is in progress.
1064
1064
  # * +EXPUNGE+ must _not_ be sent during #fetch, #store, or #search.
@@ -1143,10 +1143,7 @@ module Net
1143
1143
  end
1144
1144
 
1145
1145
  # :call-seq:
1146
- # authenticate(mechanism, *,
1147
- # sasl_ir: true,
1148
- # registry: Net::IMAP::SASL.authenticators,
1149
- # **, &) -> ok_resp
1146
+ # authenticate(mechanism, *, sasl_ir: true, registry: Net::IMAP::SASL.authenticators, **, &) -> ok_resp
1150
1147
  #
1151
1148
  # Sends an {AUTHENTICATE command [IMAP4rev1 §6.2.2]}[https://www.rfc-editor.org/rfc/rfc3501#section-6.2.2]
1152
1149
  # to authenticate the client. If successful, the connection enters the
@@ -1330,7 +1327,7 @@ module Net
1330
1327
  # the server may return an untagged "NO" response with a "UIDNOTSTICKY"
1331
1328
  # response code indicating that the mailstore does not support persistent
1332
1329
  # UIDs:
1333
- # @responses["NO"].last.code.name == "UIDNOTSTICKY"
1330
+ # imap.responses("NO", &:last)&.code&.name == "UIDNOTSTICKY"
1334
1331
  def select(mailbox)
1335
1332
  synchronize do
1336
1333
  @responses.clear
@@ -1420,10 +1417,10 @@ module Net
1420
1417
  # to the client. +refname+ provides a context (for instance, a base
1421
1418
  # directory in a directory-based mailbox hierarchy). +mailbox+ specifies a
1422
1419
  # mailbox or (via wildcards) mailboxes under that context. Two wildcards
1423
- # may be used in +mailbox+: '*', which matches all characters *including*
1424
- # the hierarchy delimiter (for instance, '/' on a UNIX-hosted
1425
- # directory-based mailbox hierarchy); and '%', which matches all characters
1426
- # *except* the hierarchy delimiter.
1420
+ # may be used in +mailbox+: <tt>"*"</tt>, which matches all characters
1421
+ # *including* the hierarchy delimiter (for instance, "/" on a UNIX-hosted
1422
+ # directory-based mailbox hierarchy); and <tt>"%"</tt>, which matches all
1423
+ # characters *except* the hierarchy delimiter.
1427
1424
  #
1428
1425
  # If +refname+ is empty, +mailbox+ is used directly to determine
1429
1426
  # which mailboxes to match. If +mailbox+ is empty, the root
@@ -1471,16 +1468,16 @@ module Net
1471
1468
  # servers, then folder creation (and listing, moving, etc) can lead to
1472
1469
  # errors.
1473
1470
  #
1474
- # From RFC2342:
1475
- #
1476
- # Although typically a server will support only a single Personal
1471
+ # From RFC2342[https://tools.ietf.org/html/rfc2342]:
1472
+ # >>>
1473
+ # <em>Although typically a server will support only a single Personal
1477
1474
  # Namespace, and a single Other User's Namespace, circumstances exist
1478
1475
  # where there MAY be multiples of these, and a client MUST be prepared
1479
1476
  # for them. If a client is configured such that it is required to create
1480
1477
  # a certain mailbox, there can be circumstances where it is unclear which
1481
1478
  # Personal Namespaces it should create the mailbox in. In these
1482
1479
  # situations a client SHOULD let the user select which namespaces to
1483
- # create the mailbox in.
1480
+ # create the mailbox in.</em>
1484
1481
  #
1485
1482
  # Related: #list, Namespaces, Namespace
1486
1483
  #
@@ -1668,9 +1665,9 @@ module Net
1668
1665
  # or more attributes whose statuses are to be requested. Supported
1669
1666
  # attributes include:
1670
1667
  #
1671
- # MESSAGES:: the number of messages in the mailbox.
1672
- # RECENT:: the number of recent messages in the mailbox.
1673
- # UNSEEN:: the number of unseen messages in the mailbox.
1668
+ # MESSAGES:: the number of messages in the mailbox.
1669
+ # RECENT:: the number of recent messages in the mailbox.
1670
+ # UNSEEN:: the number of unseen messages in the mailbox.
1674
1671
  #
1675
1672
  # The return value is a hash of attributes. For example:
1676
1673
  #
@@ -1935,11 +1932,11 @@ module Net
1935
1932
  # to alter data associated with messages in the mailbox, in particular their
1936
1933
  # flags. The +set+ parameter is a number, an array of numbers, or a Range
1937
1934
  # object. Each number is a message sequence number. +attr+ is the name of a
1938
- # data item to store: 'FLAGS' will replace the message's flag list with the
1939
- # provided one, '+FLAGS' will add the provided flags, and '-FLAGS' will
1940
- # remove them. +flags+ is a list of flags.
1935
+ # data item to store: <tt>"FLAGS"</tt> will replace the message's flag list
1936
+ # with the provided one, <tt>"+FLAGS"</tt> will add the provided flags, and
1937
+ # <tt>"-FLAGS"</tt> will remove them. +flags+ is a list of flags.
1941
1938
  #
1942
- # The return value is an array of FetchData
1939
+ # The return value is an array of FetchData.
1943
1940
  #
1944
1941
  # Related: #uid_store
1945
1942
  #
@@ -2191,7 +2188,7 @@ module Net
2191
2188
  .join(' ')
2192
2189
  synchronize do
2193
2190
  send_command("ENABLE #{capabilities}")
2194
- result = clear_responses("ENABLED").last
2191
+ result = clear_responses("ENABLED").last || []
2195
2192
  @utf8_strings ||= result.include? "UTF8=ACCEPT"
2196
2193
  @utf8_strings ||= result.include? "IMAP4REV2"
2197
2194
  result
@@ -2522,7 +2519,8 @@ module Net
2522
2519
  when /\A(?:BAD)\z/ni
2523
2520
  raise BadResponseError, resp
2524
2521
  else
2525
- raise UnknownResponseError, resp
2522
+ disconnect
2523
+ raise InvalidResponseError, "invalid tagged resp: %p" % [resp.raw.chomp]
2526
2524
  end
2527
2525
  end
2528
2526
 
@@ -2644,7 +2642,7 @@ module Net
2644
2642
  else
2645
2643
  send_command(cmd, *keys)
2646
2644
  end
2647
- clear_responses("SEARCH").last
2645
+ clear_responses("SEARCH").last || []
2648
2646
  end
2649
2647
  end
2650
2648
 
@@ -2693,7 +2691,7 @@ module Net
2693
2691
  normalize_searching_criteria(search_keys)
2694
2692
  synchronize do
2695
2693
  send_command(cmd, sort_keys, charset, *search_keys)
2696
- clear_responses("SORT").last
2694
+ clear_responses("SORT").last || []
2697
2695
  end
2698
2696
  end
2699
2697
 
@@ -2706,7 +2704,7 @@ module Net
2706
2704
  normalize_searching_criteria(search_keys)
2707
2705
  synchronize do
2708
2706
  send_command(cmd, algorithm, charset, *search_keys)
2709
- clear_responses("THREAD").last
2707
+ clear_responses("THREAD").last || []
2710
2708
  end
2711
2709
  end
2712
2710
 
data/net-imap.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  name = File.basename(__FILE__, ".gemspec")
4
4
  version = ["lib", Array.new(name.count("-"), "..").join("/")].find do |dir|
5
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
5
+ break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb"), :encoding=> 'utf-8') do |line|
6
6
  /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
7
7
  end rescue nil
8
8
  end
@@ -25,7 +25,8 @@ Gem::Specification.new do |spec|
25
25
  # Specify which files should be added to the gem when it is released.
26
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
27
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28
- `git ls-files -z 2>/dev/null`.split("\x0").reject { |f| f.match(%r{^(bin|test|spec|features|rfcs)/}) }
28
+ `git ls-files -z 2>/dev/null`.split("\x0")
29
+ .reject {|f| f.match(%r{^(bin|test|spec|benchmarks|features|rfcs)/}) }
29
30
  end
30
31
  spec.bindir = "exe"
31
32
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ PARSER_TEST_FIXTURES = FileList.new "test/net/imap/fixtures/response_parser/*.yml"
4
+ CLOBBER.include "benchmarks/parser.yml"
5
+ CLEAN.include "benchmarks/Gemfile-*"
6
+
7
+ BENCHMARK_INIT = <<RUBY
8
+ require "yaml"
9
+ require "net/imap"
10
+
11
+ def load_response(file, name)
12
+ YAML.unsafe_load_file(file).dig(:tests, name, :response)
13
+ .force_encoding "ASCII-8BIT" \\
14
+ or abort "ERRORO: missing %p fixture data in %p" % [name, file]
15
+ end
16
+
17
+ parser = Net::IMAP::ResponseParser.new
18
+ RUBY
19
+
20
+ PER_BENCHMARK_PRELUDE = <<RUBY
21
+ response = load_response(%p,
22
+ %p)
23
+ RUBY
24
+
25
+ file "benchmarks/parser.yml" => PARSER_TEST_FIXTURES do |t|
26
+ require "yaml"
27
+ require "pathname"
28
+ require "net/imap"
29
+
30
+ path = Pathname.new(__dir__) / "../test/net/imap/fixtures/response_parser"
31
+ files = path.glob("*.yml")
32
+ tests = files.flat_map {|file|
33
+ file.read
34
+ .gsub(%r{([-:]) !ruby/struct:\S+}) { $1 }
35
+ .then {
36
+ YAML.safe_load(_1, filename: file,
37
+ permitted_classes: [Symbol, Regexp], aliases: true)
38
+ }
39
+ .fetch(:tests)
40
+ .select {|test_name, test|
41
+ :parser_assert_equal == test.fetch(:test_type) {
42
+ test.key?(:expected) ? :parser_assert_equal : :parser_pending
43
+ }
44
+ }
45
+ .map {|test_name, _|
46
+ [file.relative_path_from(__dir__).to_s, test_name.to_s]
47
+ }
48
+ }
49
+
50
+ benchmarks = tests.map {|file, fixture_name|
51
+ {"name" => fixture_name.delete_prefix("test_"),
52
+ "prelude" => PER_BENCHMARK_PRELUDE % [file, fixture_name],
53
+ "script" => "parser.parse(response)"}
54
+ }
55
+ .sort_by { _1["name"] }
56
+
57
+ YAML.dump({"prelude" => BENCHMARK_INIT, "benchmark" => benchmarks})
58
+ .then { File.write t.name, _1 }
59
+ end
60
+
61
+ namespace :benchmarks do
62
+ desc "Generate benchmarks from fixture data"
63
+ task :generate => "benchmarks/parser.yml"
64
+
65
+ desc "run the parser benchmarks comparing multiple gem versions"
66
+ task :compare => :generate do |task, args|
67
+ cd Pathname.new(__dir__) + ".."
68
+ current = `git describe --tags --dirty`.chomp
69
+ current = "dev" if current.empty?
70
+ versions = args.to_a
71
+ if versions.empty?
72
+ latest = %x{git describe --tags --abbrev=0 --match 'v*.*.*'}.chomp
73
+ versions = latest.empty? ? [] : [latest.delete_prefix("v")]
74
+ end
75
+ versions = versions.to_h { [_1, "Gemfile-v#{_1}"] }
76
+ cd "benchmarks" do
77
+ versions.each do |version, gemfile|
78
+ File.write gemfile, <<~RUBY
79
+ # frozen_string_literal: true
80
+ source "https://rubygems.org"
81
+ gem "net-imap", #{version.dump}
82
+ RUBY
83
+ end
84
+ versions = {current => "../Gemfile" , **versions}.map {
85
+ "%s::/usr/bin/env BUNDLE_GEMFILE=%s ruby" % _1
86
+ }.join(";")
87
+
88
+ extra = ENV.fetch("BENCHMARK_ARGS", "").shellsplit
89
+
90
+ sh("benchmark-driver",
91
+ "--bundler",
92
+ "-e", versions,
93
+ "parser.yml",
94
+ *extra)
95
+ end
96
+ end
97
+
98
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-imap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shugo Maeda
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-10-09 00:00:00.000000000 Z
12
+ date: 2023-11-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: net-protocol
@@ -83,10 +83,6 @@ files:
83
83
  - LICENSE.txt
84
84
  - README.md
85
85
  - Rakefile
86
- - benchmarks/generate_parser_benchmarks
87
- - benchmarks/parser.yml
88
- - benchmarks/stringprep.yml
89
- - benchmarks/table-regexps.yml
90
86
  - docs/styles.css
91
87
  - lib/net/imap.rb
92
88
  - lib/net/imap/authenticators.rb
@@ -123,6 +119,7 @@ files:
123
119
  - lib/net/imap/stringprep/tables.rb
124
120
  - lib/net/imap/stringprep/trace.rb
125
121
  - net-imap.gemspec
122
+ - rakelib/benchmarks.rake
126
123
  - rakelib/rdoc.rake
127
124
  - rakelib/rfcs.rake
128
125
  - rakelib/saslprep.rake
@@ -1,52 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "yaml"
4
- require "pathname"
5
- require "net/imap"
6
-
7
- path = Pathname.new(__dir__) / "../test/net/imap/fixtures/response_parser"
8
- files = path.glob("*.yml")
9
- tests = files.flat_map {|file|
10
- file.to_s
11
- .then { YAML.unsafe_load_file _1 }
12
- .fetch(:tests)
13
- .select {|test_name, test|
14
- :parser_assert_equal == test.fetch(:test_type) {
15
- test.key?(:expected) ? :parser_assert_equal : :parser_pending
16
- }
17
- }
18
- .map {|test_name, _|
19
- [
20
- file.relative_path_from(__dir__).to_s,
21
- test_name.to_s,
22
- ]
23
- }
24
- }
25
-
26
- init = <<RUBY
27
- require "yaml"
28
- require "net/imap"
29
-
30
- def load_response(file, name)
31
- YAML.unsafe_load_file(file).dig(:tests, name, :response)
32
- .force_encoding "ASCII-8BIT" \\
33
- or abort "ERRORO: missing %p fixture data in %p" % [name, file]
34
- end
35
-
36
- parser = Net::IMAP::ResponseParser.new
37
- RUBY
38
-
39
- prelude = <<RUBY
40
- response = load_response(%p,
41
- %p)
42
- RUBY
43
- script = "parser.parse(response)"
44
-
45
- benchmarks = tests.map {|file, fixture_name|
46
- name = fixture_name.delete_prefix("test_")
47
- {name:, prelude: prelude % [file, fixture_name], script:}
48
- .transform_keys(&:to_s)
49
- }
50
- .sort_by { _1["name"] }
51
-
52
- puts YAML.dump({"prelude" => init, "benchmark" => benchmarks})