imapcli 3.0.1 → 3.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf3da9229783f1c5eff9461b6062e36ae8d51eac5ce818a980425c25d9c5e431
4
- data.tar.gz: b2a6c6476a95644f7a4a97e2f7da6120858d2057afca64372a69424a1e6f036e
3
+ metadata.gz: b57f2a82c06e43ef1d25ef4876ca78a746e01e2c985977ddb8f4789728992f5c
4
+ data.tar.gz: 7623524c875de285af386fcf521ec59893e1022ee5e09284d4aa30950eba2786
5
5
  SHA512:
6
- metadata.gz: 7df011d6f9e64d4cfc387227e2eba187f921f4a80618fb12055ed616e357a9c8b80d3c129072768a453f3d63d4f221bd7b87c691cb1b73b7133dc6962f6fad03
7
- data.tar.gz: 66fe3edbe82ce039b7d38e9f6f1836220adef5e71f6d8b268409daa838a6b1976252bac8d01514ef400ae645f2bf8b6c3e0f00bbd71f4f8b945d05d6715034a0
6
+ metadata.gz: 76857de95667a5d6ea600244cd48c54cc91257da559ed1968273822e1cc1fc08bb7e5e94955fd0b7a9f1b21b7514d970e1aa342941e640c78f279a702b706fcd
7
+ data.tar.gz: eabd2e90a25f8f8a2939208505d87dfd40828bee5db598810df9d1c6d186cd984f5b093f90ca89254276fbbeb20289fc6c94922345bdbb6006ea099f47bf02c9
data/CHANGELOG.md CHANGED
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Version 3.1.0 (2026-02-11)][v3.0.1]
9
+
10
+ ### CHanged
11
+
12
+ - Increase resilience against IMAP errors. Added an option `--[no-]skip-errors`, which
13
+ is enabled by default, but can be disabled to error out on IMAP folder errors.
14
+
8
15
  ## [Version 3.0.1 (2025-06-29)][v3.0.1]
9
16
 
10
17
  ### Changed
data/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM ruby:3.5-rc AS builder
1
+ FROM ruby:4 AS builder
2
2
  WORKDIR /imapcli
3
3
  COPY Gemfile Gemfile.lock imapcli.gemspec .
4
4
  COPY lib/imapcli/version.rb lib/imapcli/version.rb
@@ -9,7 +9,7 @@ RUN apt-get update -qq && \
9
9
  bundle config set --local deployment true && \
10
10
  bundle install
11
11
 
12
- FROM ruby:3.5-rc-slim
12
+ FROM ruby:4-slim
13
13
  LABEL maintainer="bovender@bovender.de"
14
14
  LABEL description="Command-line tool to query IMAP servers, collect stats etc."
15
15
  WORKDIR /imapcli
data/Gemfile.lock CHANGED
@@ -17,14 +17,14 @@ PATH
17
17
  GEM
18
18
  remote: https://rubygems.org/
19
19
  specs:
20
- activesupport (8.0.2)
20
+ activesupport (8.1.2)
21
21
  base64
22
- benchmark (>= 0.3)
23
22
  bigdecimal
24
23
  concurrent-ruby (~> 1.0, >= 1.3.1)
25
24
  connection_pool (>= 2.2.5)
26
25
  drb
27
26
  i18n (>= 1.6, < 2)
27
+ json
28
28
  logger (>= 1.4.2)
29
29
  minitest (>= 5.1)
30
30
  securerandom (>= 0.3)
@@ -32,44 +32,43 @@ GEM
32
32
  uri (>= 0.13.1)
33
33
  ast (2.4.3)
34
34
  base64 (0.3.0)
35
- benchmark (0.4.1)
36
- bigdecimal (3.2.2)
35
+ bigdecimal (4.0.1)
37
36
  coderay (1.1.3)
38
- concurrent-ruby (1.3.5)
39
- connection_pool (2.5.3)
37
+ concurrent-ruby (1.3.6)
38
+ connection_pool (3.0.2)
40
39
  csv (3.3.5)
41
- date (3.4.1)
42
- debug (1.11.0)
40
+ date (3.5.1)
41
+ debug (1.11.1)
43
42
  irb (~> 1.10)
44
43
  reline (>= 0.3.8)
45
44
  descriptive_statistics (2.5.1)
46
45
  diff-lcs (1.6.2)
47
46
  docile (1.4.1)
48
- dotenv (3.1.8)
47
+ dotenv (3.2.0)
49
48
  drb (2.2.3)
50
- erb (5.0.1)
51
- ffi (1.17.2)
52
- ffi (1.17.2-aarch64-linux-gnu)
53
- ffi (1.17.2-aarch64-linux-musl)
54
- ffi (1.17.2-arm-linux-gnu)
55
- ffi (1.17.2-arm-linux-musl)
56
- ffi (1.17.2-arm64-darwin)
57
- ffi (1.17.2-x86-linux-gnu)
58
- ffi (1.17.2-x86-linux-musl)
59
- ffi (1.17.2-x86_64-darwin)
60
- ffi (1.17.2-x86_64-linux-gnu)
61
- ffi (1.17.2-x86_64-linux-musl)
62
- formatador (1.1.0)
49
+ erb (6.0.1)
50
+ ffi (1.17.3)
51
+ ffi (1.17.3-aarch64-linux-gnu)
52
+ ffi (1.17.3-aarch64-linux-musl)
53
+ ffi (1.17.3-arm-linux-gnu)
54
+ ffi (1.17.3-arm-linux-musl)
55
+ ffi (1.17.3-arm64-darwin)
56
+ ffi (1.17.3-x86-linux-gnu)
57
+ ffi (1.17.3-x86-linux-musl)
58
+ ffi (1.17.3-x86_64-darwin)
59
+ ffi (1.17.3-x86_64-linux-gnu)
60
+ ffi (1.17.3-x86_64-linux-musl)
61
+ formatador (1.2.3)
62
+ reline
63
63
  gli (2.22.2)
64
64
  ostruct
65
- guard (2.19.1)
65
+ guard (2.20.1)
66
66
  formatador (>= 0.2.4)
67
67
  listen (>= 2.7, < 4.0)
68
68
  logger (~> 1.6)
69
69
  lumberjack (>= 1.0.12, < 2.0)
70
70
  nenv (~> 0.1)
71
71
  notiffany (~> 0.0)
72
- ostruct (~> 0.6)
73
72
  pry (>= 0.13.0)
74
73
  shellany (~> 0.0)
75
74
  thor (>= 0.18.1)
@@ -78,25 +77,28 @@ GEM
78
77
  guard (~> 2.1)
79
78
  guard-compat (~> 1.1)
80
79
  rspec (>= 2.99.0, < 4.0)
81
- i18n (1.14.7)
80
+ i18n (1.14.8)
82
81
  concurrent-ruby (~> 1.0)
83
- io-console (0.8.0)
84
- irb (1.15.2)
82
+ io-console (0.8.2)
83
+ irb (1.17.0)
85
84
  pp (>= 0.6.0)
85
+ prism (>= 1.3.0)
86
86
  rdoc (>= 4.0.0)
87
87
  reline (>= 0.4.2)
88
- json (2.12.2)
88
+ json (2.18.1)
89
89
  language_server-protocol (3.17.0.5)
90
90
  lint_roller (1.1.0)
91
- listen (3.9.0)
91
+ listen (3.10.0)
92
+ logger
92
93
  rb-fsevent (~> 0.10, >= 0.10.3)
93
94
  rb-inotify (~> 0.9, >= 0.9.10)
94
95
  logger (1.7.0)
95
- lumberjack (1.2.10)
96
+ lumberjack (1.4.2)
96
97
  method_source (1.1.0)
97
- minitest (5.25.5)
98
+ minitest (6.0.1)
99
+ prism (~> 1.5)
98
100
  nenv (0.3.0)
99
- net-imap (0.5.9)
101
+ net-imap (0.6.2)
100
102
  date
101
103
  net-protocol
102
104
  net-protocol (0.2.2)
@@ -104,52 +106,54 @@ GEM
104
106
  notiffany (0.1.3)
105
107
  nenv (~> 0.1)
106
108
  shellany (~> 0.0)
107
- oj (3.16.11)
109
+ oj (3.16.15)
108
110
  bigdecimal (>= 3.0)
109
111
  ostruct (>= 0.2)
110
- ostruct (0.6.2)
112
+ ostruct (0.6.3)
111
113
  parallel (1.27.0)
112
- parser (3.3.8.0)
114
+ parser (3.3.10.1)
113
115
  ast (~> 2.4.1)
114
116
  racc
115
117
  pastel (0.8.0)
116
118
  tty-color (~> 0.5)
117
- pp (0.6.2)
119
+ pp (0.6.3)
118
120
  prettyprint
119
121
  prettyprint (0.2.0)
120
- prism (1.4.0)
121
- pry (0.15.2)
122
+ prism (1.9.0)
123
+ pry (0.16.0)
122
124
  coderay (~> 1.1)
123
125
  method_source (~> 1.0)
124
- psych (5.2.6)
126
+ reline (>= 0.6.0)
127
+ psych (5.3.1)
125
128
  date
126
129
  stringio
127
130
  racc (1.8.1)
128
131
  rainbow (3.1.1)
129
- rake (13.3.0)
132
+ rake (13.3.1)
130
133
  rb-fsevent (0.11.2)
131
134
  rb-inotify (0.11.1)
132
135
  ffi (~> 1.0)
133
- rdoc (6.14.1)
136
+ rdoc (7.2.0)
134
137
  erb
135
138
  psych (>= 4.0.0)
136
- regexp_parser (2.10.0)
137
- reline (0.6.1)
139
+ tsort
140
+ regexp_parser (2.11.3)
141
+ reline (0.6.3)
138
142
  io-console (~> 0.5)
139
- rspec (3.13.1)
143
+ rspec (3.13.2)
140
144
  rspec-core (~> 3.13.0)
141
145
  rspec-expectations (~> 3.13.0)
142
146
  rspec-mocks (~> 3.13.0)
143
- rspec-core (3.13.5)
147
+ rspec-core (3.13.6)
144
148
  rspec-support (~> 3.13.0)
145
149
  rspec-expectations (3.13.5)
146
150
  diff-lcs (>= 1.2.0, < 2.0)
147
151
  rspec-support (~> 3.13.0)
148
- rspec-mocks (3.13.5)
152
+ rspec-mocks (3.13.7)
149
153
  diff-lcs (>= 1.2.0, < 2.0)
150
154
  rspec-support (~> 3.13.0)
151
- rspec-support (3.13.4)
152
- rubocop (1.77.0)
155
+ rspec-support (3.13.7)
156
+ rubocop (1.84.1)
153
157
  json (~> 2.3)
154
158
  language_server-protocol (~> 3.17.0.2)
155
159
  lint_roller (~> 1.1.0)
@@ -157,22 +161,22 @@ GEM
157
161
  parser (>= 3.3.0.2)
158
162
  rainbow (>= 2.2.2, < 4.0)
159
163
  regexp_parser (>= 2.9.3, < 3.0)
160
- rubocop-ast (>= 1.45.1, < 2.0)
164
+ rubocop-ast (>= 1.49.0, < 2.0)
161
165
  ruby-progressbar (~> 1.7)
162
166
  unicode-display_width (>= 2.4.0, < 4.0)
163
- rubocop-ast (1.45.1)
167
+ rubocop-ast (1.49.0)
164
168
  parser (>= 3.3.7.2)
165
- prism (~> 1.4)
166
- rubocop-performance (1.25.0)
169
+ prism (~> 1.7)
170
+ rubocop-performance (1.26.1)
167
171
  lint_roller (~> 1.1)
168
172
  rubocop (>= 1.75.0, < 2.0)
169
- rubocop-ast (>= 1.38.0, < 2.0)
173
+ rubocop-ast (>= 1.47.1, < 2.0)
170
174
  rubocop-rake (0.7.1)
171
175
  lint_roller (~> 1.1)
172
176
  rubocop (>= 1.72.1)
173
- rubocop-rspec (3.6.0)
177
+ rubocop-rspec (3.9.0)
174
178
  lint_roller (~> 1.1)
175
- rubocop (~> 1.72, >= 1.72.1)
179
+ rubocop (~> 1.81)
176
180
  ruby-progressbar (1.13.0)
177
181
  securerandom (0.4.1)
178
182
  shellany (0.0.1)
@@ -180,16 +184,17 @@ GEM
180
184
  docile (~> 1.1)
181
185
  simplecov-html (~> 0.11)
182
186
  simplecov_json_formatter (~> 0.1)
183
- simplecov-html (0.13.1)
187
+ simplecov-html (0.13.2)
184
188
  simplecov_json_formatter (0.1.4)
185
- stringio (3.1.7)
189
+ stringio (3.2.0)
186
190
  strings (0.2.1)
187
191
  strings-ansi (~> 0.2)
188
192
  unicode-display_width (>= 1.5, < 3.0)
189
193
  unicode_utils (~> 1.4)
190
194
  strings-ansi (0.2.0)
191
- thor (1.3.2)
192
- timeout (0.4.3)
195
+ thor (1.5.0)
196
+ timeout (0.6.0)
197
+ tsort (0.2.0)
193
198
  tty-color (0.6.0)
194
199
  tty-cursor (0.7.1)
195
200
  tty-progressbar (0.18.3)
@@ -213,9 +218,9 @@ GEM
213
218
  concurrent-ruby (~> 1.0)
214
219
  unicode-display_width (2.6.0)
215
220
  unicode_utils (1.4.0)
216
- uri (1.0.3)
221
+ uri (1.1.1)
217
222
  wisper (2.0.1)
218
- zeitwerk (2.7.3)
223
+ zeitwerk (2.7.4)
219
224
 
220
225
  PLATFORMS
221
226
  aarch64-linux-gnu
@@ -245,4 +250,4 @@ DEPENDENCIES
245
250
  simplecov
246
251
 
247
252
  BUNDLED WITH
248
- 2.6.9
253
+ 4.0.6
data/README.md CHANGED
@@ -332,10 +332,11 @@ the `Gemfile` for other work that this tool depends on.
332
332
 
333
333
  - [@bovender](https://github.com/bovender)
334
334
  - [@n-rodriguez](https://github.com/n-rodriguez)
335
+ - [@d4nyl0](https://github.com/d4nyl0)
335
336
 
336
337
  ## License
337
338
 
338
- &copy; 2017-2025 Daniel Kraus (@bovender)
339
+ &copy; 2017-2026 Daniel Kraus (@bovender)
339
340
 
340
341
  Licensed under the Apache License, Version 2.0 (the "License");
341
342
  you may not use this file except in compliance with the License.
data/lib/imapcli/cli.rb CHANGED
@@ -69,6 +69,12 @@ module Imapcli
69
69
  c.switch %i[H human],
70
70
  desc: 'Convert byte counts to human-friendly formats',
71
71
  negatable: false
72
+
73
+ c.switch %i[skip-errors],
74
+ desc: 'Skip folders (IMAP mailboxes) that cannot be accessed',
75
+ negatable: true,
76
+ default_value: true
77
+
72
78
  c.flag %i[o sort],
73
79
  desc: 'Ordered (sorted) results',
74
80
  arg_name: 'sort_property',
@@ -85,9 +91,11 @@ module Imapcli
85
91
  raise unless @validator.stats_options_valid?(options, args)
86
92
 
87
93
  progress_bar = nil
94
+ skipped_mailboxes = []
88
95
 
89
96
  head = ['Mailbox', 'Count', 'Total size', 'Min', 'Q1', 'Median', 'Q3', 'Max']
90
- body = @command.stats(args, options) do |n|
97
+
98
+ body = @command.stats(args, options, skipped_mailboxes) do |n|
91
99
  if progress_bar
92
100
  progress_bar.advance
93
101
  else
@@ -98,6 +106,7 @@ module Imapcli
98
106
  )
99
107
  end
100
108
  end
109
+
101
110
  formatted_body = body.map do |row|
102
111
  row[0..1] + row[2..].map { |cell| format_bytes(cell, options[:human]) }
103
112
  end
@@ -130,6 +139,14 @@ module Imapcli
130
139
  @prompt.warn "#{Imapcli::Command.unknown_mailbox_prefix}unknown mailbox"
131
140
  end
132
141
  end
142
+
143
+ unless skipped_mailboxes.empty?
144
+ @prompt.say ""
145
+ @prompt.warn "Skipped #{skipped_mailboxes.length} folder(s) (IMAP mailbox(es)) due to errors:"
146
+ skipped_mailboxes.each do |info|
147
+ @prompt.warn " - #{info[:name]}: #{info[:error]}"
148
+ end
149
+ end
133
150
  end
134
151
  end
135
152
 
@@ -46,7 +46,7 @@ module Imapcli
46
46
  #
47
47
  # If a block is given, it is called with the current mailbox count and the
48
48
  # total mailbox count so that current progress can be computed.
49
- def stats(mailbox_names = [], options = {}) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
49
+ def stats(mailbox_names = [], options = {}, skipped_mailboxes = []) # rubocop:disable Metrics/MethodLength,Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
50
50
  mailbox_names = [mailbox_names] unless mailbox_names.is_a? Array
51
51
  perform do
52
52
  # Map the command line arguments to Imapcli::Mailbox objects
@@ -59,11 +59,14 @@ module Imapcli
59
59
  current_count = 0
60
60
  yield list.length if block_given?
61
61
  total_stats = Stats.new
62
+
63
+ skip_errors = options.fetch(:'skip-errors', true)
64
+
62
65
  list.each do |mailbox|
63
66
  # Since we are working on a flat list of mailboxes, set the maximum
64
67
  # level to 0 when collecting stats.
65
- mailbox.collect_stats(@client, 0) do |stats|
66
- total_stats.add(stats)
68
+ mailbox.collect_stats(@client, 0, skip_errors: skip_errors, skipped_mailboxes: skipped_mailboxes) do |stats|
69
+ total_stats.add(stats) if stats
67
70
  current_count += 1
68
71
  yield current_count if block_given?
69
72
  end
@@ -74,8 +77,8 @@ module Imapcli
74
77
  else
75
78
  sorted_list(list, options)
76
79
  end.map do |mailbox|
77
- stats_to_table(mailbox.full_name, mailbox.stats)
78
- end
80
+ mailbox.stats ? stats_to_table(mailbox.full_name, mailbox.stats) : nil
81
+ end.compact
79
82
  output << stats_to_table('Total', total_stats) if list.length > 1
80
83
  output
81
84
  end
@@ -106,15 +106,30 @@ module Imapcli
106
106
  #
107
107
  # If a block is given, it is called with the Imapcli::Stats object for this
108
108
  # mailbox.
109
- def collect_stats(client, max_level = nil, &block)
109
+ def collect_stats(client, max_level = nil, skip_errors: true, skipped_mailboxes: nil, &block)
110
110
  return if @stats
111
111
 
112
- @stats = Stats.new(client.message_sizes(full_name)) if full_name # proceed only if this is a mailbox of its own
113
- yield @stats if block_given?
112
+ # proceed only if this is a mailbox of its own
113
+ if full_name
114
+ begin
115
+ @stats = Stats.new(client.message_sizes(full_name))
116
+ yield @stats if block_given?
117
+ rescue Net::IMAP::NoResponseError => e
118
+ # Errore IMAP: mailbox non esiste o non è accessibile
119
+ handle_mailbox_error(e, skip_errors, skipped_mailboxes)
120
+ rescue Net::IMAP::ByeResponseError => e
121
+ # Server ha chiuso la connessione
122
+ handle_mailbox_error(e, skip_errors, skipped_mailboxes)
123
+ rescue StandardError => e
124
+ # Altro tipo di errore
125
+ handle_mailbox_error(e, skip_errors, skipped_mailboxes)
126
+ end
127
+ end
128
+
114
129
  return unless max_level.nil? || level < max_level
115
130
 
116
131
  @children.each_value do |child|
117
- child.collect_stats(client, max_level, &block)
132
+ child.collect_stats(client, max_level, skip_errors: skip_errors, skipped_mailboxes: skipped_mailboxes, &block)
118
133
  end
119
134
  end
120
135
 
@@ -175,5 +190,31 @@ module Imapcli
175
190
  end
176
191
  end
177
192
 
193
+ private
194
+
195
+ # Handle errors during stats collection
196
+ def handle_mailbox_error(error, skip_errors, skipped_mailboxes)
197
+ error_message = case error
198
+ when Net::IMAP::NoResponseError
199
+ error.message
200
+ when Net::IMAP::ByeResponseError
201
+ "Server closed connection: #{error.message}"
202
+ else
203
+ "#{error.class}: #{error.message}"
204
+ end
205
+
206
+ if skip_errors
207
+ if skipped_mailboxes.is_a?(Array)
208
+ skipped_mailboxes << {
209
+ name: full_name,
210
+ error: error_message
211
+ }
212
+ end
213
+ nil
214
+ else
215
+ raise error
216
+ end
217
+ end
218
+
178
219
  end
179
220
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Imapcli
4
- VERSION = '3.0.1'
4
+ VERSION = '3.1.0'
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imapcli
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Kraus (bovender)
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-06-29 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activesupport
@@ -226,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
226
  - !ruby/object:Gem::Version
227
227
  version: '0'
228
228
  requirements: []
229
- rubygems_version: 3.6.2
229
+ rubygems_version: 3.6.9
230
230
  specification_version: 4
231
231
  summary: Command-line tool to query IMAP servers
232
232
  test_files: []