imapcli 3.0.1 → 3.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf3da9229783f1c5eff9461b6062e36ae8d51eac5ce818a980425c25d9c5e431
4
- data.tar.gz: b2a6c6476a95644f7a4a97e2f7da6120858d2057afca64372a69424a1e6f036e
3
+ metadata.gz: 999e2cc80315c73b7bdd43fbc8c78f903a066b03a63be0722ebdcb0add825de1
4
+ data.tar.gz: 6b9ea5ec31aaa152013a9684b5b661e02c9200f7f3992a7167ddfb23e4878536
5
5
  SHA512:
6
- metadata.gz: 7df011d6f9e64d4cfc387227e2eba187f921f4a80618fb12055ed616e357a9c8b80d3c129072768a453f3d63d4f221bd7b87c691cb1b73b7133dc6962f6fad03
7
- data.tar.gz: 66fe3edbe82ce039b7d38e9f6f1836220adef5e71f6d8b268409daa838a6b1976252bac8d01514ef400ae645f2bf8b6c3e0f00bbd71f4f8b945d05d6715034a0
6
+ metadata.gz: e02093dec376ad768df5085aedc7c17b9dd2553d76be2123d3e5d4f44aed8be90ea9717feb50eb53d14c35db44159ad8a2a2f8a6c788121b8a8c5a9f597f8f89
7
+ data.tar.gz: 680b4e19da0fb808512709ac6181dc32328df4c1e032a4eccaa65587adf060e60878dee0e99f294783396fecd2f333cc4a9145987e1e455a980a01964498550b
data/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ 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.1 (2027-07-14)][v3.1.1]
9
+
10
+ ### Changed
11
+
12
+ - Updated gems to include several security updates.
13
+
14
+ ## [Version 3.1.0 (2026-02-11)][v3.1.0]
15
+
16
+ ### Changed
17
+
18
+ - Increase resilience against IMAP errors. Added an option `--[no-]skip-errors`, which
19
+ is enabled by default, but can be disabled to error out on IMAP folder errors.
20
+
8
21
  ## [Version 3.0.1 (2025-06-29)][v3.0.1]
9
22
 
10
23
  ### Changed
@@ -103,6 +116,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
103
116
  - Fix: Docker image.
104
117
  - Fix: Options error message.
105
118
 
119
+ [v3.1.1]: https://github.com/bovender/imapcli/releases/tag/v3.1.1
120
+ [v3.1.0]: https://github.com/bovender/imapcli/releases/tag/v3.1.0
106
121
  [v3.0.1]: https://github.com/bovender/imapcli/releases/tag/v3.0.1
107
122
  [v3.0.0]: https://github.com/bovender/imapcli/releases/tag/v3.0.0
108
123
  [v2.1.0]: https://github.com/bovender/imapcli/releases/tag/v2.1.0
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
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- imapcli (3.0.1)
4
+ imapcli (3.1.0)
5
5
  activesupport (~> 8.0)
6
6
  csv
7
7
  descriptive_statistics (~> 2.5)
@@ -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.3)
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,42 @@ 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.1.2)
37
36
  coderay (1.1.3)
38
- concurrent-ruby (1.3.5)
39
- connection_pool (2.5.3)
37
+ concurrent-ruby (1.3.7)
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
- docile (1.4.1)
48
- dotenv (3.1.8)
46
+ dotenv (3.2.0)
49
47
  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)
48
+ erb (6.0.4)
49
+ ffi (1.17.4)
50
+ ffi (1.17.4-aarch64-linux-gnu)
51
+ ffi (1.17.4-aarch64-linux-musl)
52
+ ffi (1.17.4-arm-linux-gnu)
53
+ ffi (1.17.4-arm-linux-musl)
54
+ ffi (1.17.4-arm64-darwin)
55
+ ffi (1.17.4-x86-linux-gnu)
56
+ ffi (1.17.4-x86-linux-musl)
57
+ ffi (1.17.4-x86_64-darwin)
58
+ ffi (1.17.4-x86_64-linux-gnu)
59
+ ffi (1.17.4-x86_64-linux-musl)
60
+ formatador (1.2.3)
61
+ reline
63
62
  gli (2.22.2)
64
63
  ostruct
65
- guard (2.19.1)
64
+ guard (2.20.1)
66
65
  formatador (>= 0.2.4)
67
66
  listen (>= 2.7, < 4.0)
68
67
  logger (~> 1.6)
69
68
  lumberjack (>= 1.0.12, < 2.0)
70
69
  nenv (~> 0.1)
71
70
  notiffany (~> 0.0)
72
- ostruct (~> 0.6)
73
71
  pry (>= 0.13.0)
74
72
  shellany (~> 0.0)
75
73
  thor (>= 0.18.1)
@@ -78,25 +76,29 @@ GEM
78
76
  guard (~> 2.1)
79
77
  guard-compat (~> 1.1)
80
78
  rspec (>= 2.99.0, < 4.0)
81
- i18n (1.14.7)
79
+ i18n (1.15.2)
82
80
  concurrent-ruby (~> 1.0)
83
- io-console (0.8.0)
84
- irb (1.15.2)
81
+ io-console (0.8.2)
82
+ irb (1.18.0)
85
83
  pp (>= 0.6.0)
84
+ prism (>= 1.3.0)
86
85
  rdoc (>= 4.0.0)
87
86
  reline (>= 0.4.2)
88
- json (2.12.2)
89
- language_server-protocol (3.17.0.5)
87
+ json (2.21.1)
88
+ language_server-protocol (3.17.0.6)
90
89
  lint_roller (1.1.0)
91
- listen (3.9.0)
90
+ listen (3.10.0)
91
+ logger
92
92
  rb-fsevent (~> 0.10, >= 0.10.3)
93
93
  rb-inotify (~> 0.9, >= 0.9.10)
94
94
  logger (1.7.0)
95
- lumberjack (1.2.10)
95
+ lumberjack (1.4.2)
96
96
  method_source (1.1.0)
97
- minitest (5.25.5)
97
+ minitest (6.0.6)
98
+ drb (~> 2.0)
99
+ prism (~> 1.5)
98
100
  nenv (0.3.0)
99
- net-imap (0.5.9)
101
+ net-imap (0.6.4.1)
100
102
  date
101
103
  net-protocol
102
104
  net-protocol (0.2.2)
@@ -104,92 +106,92 @@ 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.17.4)
108
110
  bigdecimal (>= 3.0)
109
111
  ostruct (>= 0.2)
110
- ostruct (0.6.2)
111
- parallel (1.27.0)
112
- parser (3.3.8.0)
112
+ ostruct (0.6.3)
113
+ parallel (2.1.0)
114
+ parser (3.3.11.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.4)
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)
125
- date
126
- stringio
126
+ reline (>= 0.6.0)
127
127
  racc (1.8.1)
128
128
  rainbow (3.1.1)
129
- rake (13.3.0)
129
+ rake (13.4.2)
130
130
  rb-fsevent (0.11.2)
131
131
  rb-inotify (0.11.1)
132
132
  ffi (~> 1.0)
133
- rdoc (6.14.1)
133
+ rbs (4.0.3)
134
+ logger
135
+ prism (>= 1.6.0)
136
+ tsort
137
+ rdoc (8.0.0)
134
138
  erb
135
- psych (>= 4.0.0)
136
- regexp_parser (2.10.0)
137
- reline (0.6.1)
139
+ prism (>= 1.6.0)
140
+ rbs (>= 4.0.0)
141
+ tsort
142
+ regexp_parser (2.12.0)
143
+ reline (0.6.3)
138
144
  io-console (~> 0.5)
139
- rspec (3.13.1)
145
+ rspec (3.13.2)
140
146
  rspec-core (~> 3.13.0)
141
147
  rspec-expectations (~> 3.13.0)
142
148
  rspec-mocks (~> 3.13.0)
143
- rspec-core (3.13.5)
149
+ rspec-core (3.13.6)
144
150
  rspec-support (~> 3.13.0)
145
151
  rspec-expectations (3.13.5)
146
152
  diff-lcs (>= 1.2.0, < 2.0)
147
153
  rspec-support (~> 3.13.0)
148
- rspec-mocks (3.13.5)
154
+ rspec-mocks (3.13.8)
149
155
  diff-lcs (>= 1.2.0, < 2.0)
150
156
  rspec-support (~> 3.13.0)
151
- rspec-support (3.13.4)
152
- rubocop (1.77.0)
157
+ rspec-support (3.13.7)
158
+ rubocop (1.88.2)
153
159
  json (~> 2.3)
154
160
  language_server-protocol (~> 3.17.0.2)
155
161
  lint_roller (~> 1.1.0)
156
- parallel (~> 1.10)
162
+ parallel (>= 1.10)
157
163
  parser (>= 3.3.0.2)
158
164
  rainbow (>= 2.2.2, < 4.0)
159
165
  regexp_parser (>= 2.9.3, < 3.0)
160
- rubocop-ast (>= 1.45.1, < 2.0)
166
+ rubocop-ast (>= 1.49.0, < 2.0)
161
167
  ruby-progressbar (~> 1.7)
162
168
  unicode-display_width (>= 2.4.0, < 4.0)
163
- rubocop-ast (1.45.1)
169
+ rubocop-ast (1.50.0)
164
170
  parser (>= 3.3.7.2)
165
- prism (~> 1.4)
166
- rubocop-performance (1.25.0)
171
+ prism (~> 1.7)
172
+ rubocop-performance (1.26.1)
167
173
  lint_roller (~> 1.1)
168
174
  rubocop (>= 1.75.0, < 2.0)
169
- rubocop-ast (>= 1.38.0, < 2.0)
175
+ rubocop-ast (>= 1.47.1, < 2.0)
170
176
  rubocop-rake (0.7.1)
171
177
  lint_roller (~> 1.1)
172
178
  rubocop (>= 1.72.1)
173
- rubocop-rspec (3.6.0)
179
+ rubocop-rspec (3.10.2)
174
180
  lint_roller (~> 1.1)
175
- rubocop (~> 1.72, >= 1.72.1)
181
+ regexp_parser (>= 2.0)
182
+ rubocop (~> 1.86, >= 1.86.2)
176
183
  ruby-progressbar (1.13.0)
177
184
  securerandom (0.4.1)
178
185
  shellany (0.0.1)
179
- simplecov (0.22.0)
180
- docile (~> 1.1)
181
- simplecov-html (~> 0.11)
182
- simplecov_json_formatter (~> 0.1)
183
- simplecov-html (0.13.1)
184
- simplecov_json_formatter (0.1.4)
185
- stringio (3.1.7)
186
+ simplecov (1.0.1)
186
187
  strings (0.2.1)
187
188
  strings-ansi (~> 0.2)
188
189
  unicode-display_width (>= 1.5, < 3.0)
189
190
  unicode_utils (~> 1.4)
190
191
  strings-ansi (0.2.0)
191
- thor (1.3.2)
192
- timeout (0.4.3)
192
+ thor (1.5.0)
193
+ timeout (0.6.1)
194
+ tsort (0.2.0)
193
195
  tty-color (0.6.0)
194
196
  tty-cursor (0.7.1)
195
197
  tty-progressbar (0.18.3)
@@ -213,9 +215,9 @@ GEM
213
215
  concurrent-ruby (~> 1.0)
214
216
  unicode-display_width (2.6.0)
215
217
  unicode_utils (1.4.0)
216
- uri (1.0.3)
218
+ uri (1.1.1)
217
219
  wisper (2.0.1)
218
- zeitwerk (2.7.3)
220
+ zeitwerk (2.7.5)
219
221
 
220
222
  PLATFORMS
221
223
  aarch64-linux-gnu
@@ -245,4 +247,4 @@ DEPENDENCIES
245
247
  simplecov
246
248
 
247
249
  BUNDLED WITH
248
- 2.6.9
250
+ 4.0.10
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.1'
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.1
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: 4.0.16
230
230
  specification_version: 4
231
231
  summary: Command-line tool to query IMAP servers
232
232
  test_files: []