imapcli 2.1.0 → 3.0.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: 0736f0dbe2cb473770fb5f92f0f37546b9f26a6e892bbca3c69b072c1f06db9f
4
- data.tar.gz: '0609a383ac74799eb2aade3d52fa0c5c811fc5cb4b253f1607e0b6f2dbe7cf01'
3
+ metadata.gz: cf3da9229783f1c5eff9461b6062e36ae8d51eac5ce818a980425c25d9c5e431
4
+ data.tar.gz: b2a6c6476a95644f7a4a97e2f7da6120858d2057afca64372a69424a1e6f036e
5
5
  SHA512:
6
- metadata.gz: 69d818a1780fda1549bbd83581c2d0abbc4ecda7274cb411bedd450a8365e322153263c1f5b490b03a183e7c8cb02e5d382c82c8628ee43e1c1c1294f6e76afa
7
- data.tar.gz: e664577a0949609bebd90a7bc08b94e4559001fcb7b26429958fe38801acd835089b030cad3d3b1fa09a95ccc51b400f6cb8f66befc4903ebe1cb9b4bb56746d
6
+ metadata.gz: 7df011d6f9e64d4cfc387227e2eba187f921f4a80618fb12055ed616e357a9c8b80d3c129072768a453f3d63d4f221bd7b87c691cb1b73b7133dc6962f6fad03
7
+ data.tar.gz: 66fe3edbe82ce039b7d38e9f6f1836220adef5e71f6d8b268409daa838a6b1976252bac8d01514ef400ae645f2bf8b6c3e0f00bbd71f4f8b945d05d6715034a0
@@ -3,7 +3,7 @@
3
3
  {
4
4
  "name": "Ruby",
5
5
  // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
6
- "image": "mcr.microsoft.com/devcontainers/ruby:1-3.3-bullseye"
6
+ "image": "mcr.microsoft.com/devcontainers/ruby:1-3.4-bullseye"
7
7
 
8
8
  // Features to add to the dev container. More info: https://containers.dev/features.
9
9
  // "features": {},
data/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ 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.0.1 (2025-06-29)][v3.0.1]
9
+
10
+ ### Changed
11
+
12
+ - Updated dependencies.
13
+
14
+ ### Fixed
15
+
16
+ - Docker image now works again for real (finally fixes #10?).
17
+
18
+ ## [Version 3.0.0 (2025-04-21)][v3.0.0]
19
+
20
+ ### Fixed
21
+
22
+ - Docker image now works again (fixes #10).
23
+
24
+ ## [Version 3.0.0 (2025-04-21)][v3.0.0]
25
+
26
+ ### Changed
27
+
28
+ - **BREAKING:** Removed the `-v`/`--verbose` switch which was not functional
29
+ anyway and added a new option `-O`/`--log-output` flag to write IMAP responses
30
+ to a file in JSON format.
31
+
8
32
  ## [Version 2.1.0 (2025-03-16)][v2.1.0]
9
33
 
10
34
  ### Added
@@ -79,6 +103,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
79
103
  - Fix: Docker image.
80
104
  - Fix: Options error message.
81
105
 
106
+ [v3.0.1]: https://github.com/bovender/imapcli/releases/tag/v3.0.1
107
+ [v3.0.0]: https://github.com/bovender/imapcli/releases/tag/v3.0.0
82
108
  [v2.1.0]: https://github.com/bovender/imapcli/releases/tag/v2.1.0
83
109
  [v2.0.1]: https://github.com/bovender/imapcli/releases/tag/v2.0.1
84
110
  [v2.0.0]: https://github.com/bovender/imapcli/releases/tag/v2.0.0
data/Dockerfile CHANGED
@@ -1,18 +1,22 @@
1
- FROM ruby:3.4-alpine
2
- LABEL maintainer="bovender@bovender.de"
3
- LABEL description="Command-line tool to query IMAP servers, collect stats etc."
4
-
5
- WORKDIR /
6
- ADD . /imapcli
7
- RUN apk add --no-cache git build-base && \
1
+ FROM ruby:3.5-rc AS builder
2
+ WORKDIR /imapcli
3
+ COPY Gemfile Gemfile.lock imapcli.gemspec .
4
+ COPY lib/imapcli/version.rb lib/imapcli/version.rb
5
+ RUN apt-get update -qq && \
6
+ apt-get install -y build-essential libc6 && \
8
7
  gem update --system && \
9
- cd imapcli && \
10
8
  bundle config set --local without development test && \
11
9
  bundle config set --local deployment true && \
12
- bundle install && \
13
- apk del build-base && \
14
- rm -rf /var/cache/apk/*
10
+ bundle install
15
11
 
12
+ FROM ruby:3.5-rc-slim
13
+ LABEL maintainer="bovender@bovender.de"
14
+ LABEL description="Command-line tool to query IMAP servers, collect stats etc."
16
15
  WORKDIR /imapcli
16
+ RUN apt-get update -qq && \
17
+ apt-get install -y git && \
18
+ apt-get clean && rm -rf /var/lib/apt/lists/*
19
+ COPY --from=builder /usr/local/bundle /usr/local/bundle
20
+ COPY --from=builder /imapcli/vendor /imapcli/vendor
21
+ COPY . .
17
22
  ENTRYPOINT ["bundle", "exec", "exe/imapcli"]
18
-
data/Gemfile.lock CHANGED
@@ -1,13 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- imapcli (2.0.1)
4
+ imapcli (3.0.1)
5
5
  activesupport (~> 8.0)
6
6
  csv
7
7
  descriptive_statistics (~> 2.5)
8
8
  dotenv (~> 3.1)
9
9
  gli (~> 2.22)
10
10
  net-imap
11
+ oj (~> 3.16)
11
12
  tty-progressbar (~> 0.18)
12
13
  tty-prompt (~> 0.23)
13
14
  tty-table (~> 0.12)
@@ -29,34 +30,35 @@ GEM
29
30
  securerandom (>= 0.3)
30
31
  tzinfo (~> 2.0, >= 2.0.5)
31
32
  uri (>= 0.13.1)
32
- ast (2.4.2)
33
- base64 (0.2.0)
34
- benchmark (0.4.0)
35
- bigdecimal (3.1.9)
33
+ ast (2.4.3)
34
+ base64 (0.3.0)
35
+ benchmark (0.4.1)
36
+ bigdecimal (3.2.2)
36
37
  coderay (1.1.3)
37
38
  concurrent-ruby (1.3.5)
38
- connection_pool (2.5.0)
39
- csv (3.3.2)
39
+ connection_pool (2.5.3)
40
+ csv (3.3.5)
40
41
  date (3.4.1)
41
- debug (1.10.0)
42
+ debug (1.11.0)
42
43
  irb (~> 1.10)
43
44
  reline (>= 0.3.8)
44
45
  descriptive_statistics (2.5.1)
45
- diff-lcs (1.6.0)
46
+ diff-lcs (1.6.2)
46
47
  docile (1.4.1)
47
- dotenv (3.1.7)
48
- drb (2.2.1)
49
- ffi (1.17.1)
50
- ffi (1.17.1-aarch64-linux-gnu)
51
- ffi (1.17.1-aarch64-linux-musl)
52
- ffi (1.17.1-arm-linux-gnu)
53
- ffi (1.17.1-arm-linux-musl)
54
- ffi (1.17.1-arm64-darwin)
55
- ffi (1.17.1-x86-linux-gnu)
56
- ffi (1.17.1-x86-linux-musl)
57
- ffi (1.17.1-x86_64-darwin)
58
- ffi (1.17.1-x86_64-linux-gnu)
59
- ffi (1.17.1-x86_64-linux-musl)
48
+ dotenv (3.1.8)
49
+ 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)
60
62
  formatador (1.1.0)
61
63
  gli (2.22.2)
62
64
  ostruct
@@ -79,22 +81,22 @@ GEM
79
81
  i18n (1.14.7)
80
82
  concurrent-ruby (~> 1.0)
81
83
  io-console (0.8.0)
82
- irb (1.15.1)
84
+ irb (1.15.2)
83
85
  pp (>= 0.6.0)
84
86
  rdoc (>= 4.0.0)
85
87
  reline (>= 0.4.2)
86
- json (2.10.2)
87
- language_server-protocol (3.17.0.4)
88
+ json (2.12.2)
89
+ language_server-protocol (3.17.0.5)
88
90
  lint_roller (1.1.0)
89
91
  listen (3.9.0)
90
92
  rb-fsevent (~> 0.10, >= 0.10.3)
91
93
  rb-inotify (~> 0.9, >= 0.9.10)
92
- logger (1.6.6)
94
+ logger (1.7.0)
93
95
  lumberjack (1.2.10)
94
96
  method_source (1.1.0)
95
97
  minitest (5.25.5)
96
98
  nenv (0.3.0)
97
- net-imap (0.5.6)
99
+ net-imap (0.5.9)
98
100
  date
99
101
  net-protocol
100
102
  net-protocol (0.2.2)
@@ -102,9 +104,12 @@ GEM
102
104
  notiffany (0.1.3)
103
105
  nenv (~> 0.1)
104
106
  shellany (~> 0.0)
105
- ostruct (0.6.1)
106
- parallel (1.26.3)
107
- parser (3.3.7.1)
107
+ oj (3.16.11)
108
+ bigdecimal (>= 3.0)
109
+ ostruct (>= 0.2)
110
+ ostruct (0.6.2)
111
+ parallel (1.27.0)
112
+ parser (3.3.8.0)
108
113
  ast (~> 2.4.1)
109
114
  racc
110
115
  pastel (0.8.0)
@@ -112,37 +117,39 @@ GEM
112
117
  pp (0.6.2)
113
118
  prettyprint
114
119
  prettyprint (0.2.0)
120
+ prism (1.4.0)
115
121
  pry (0.15.2)
116
122
  coderay (~> 1.1)
117
123
  method_source (~> 1.0)
118
- psych (5.2.3)
124
+ psych (5.2.6)
119
125
  date
120
126
  stringio
121
127
  racc (1.8.1)
122
128
  rainbow (3.1.1)
123
- rake (13.2.1)
129
+ rake (13.3.0)
124
130
  rb-fsevent (0.11.2)
125
131
  rb-inotify (0.11.1)
126
132
  ffi (~> 1.0)
127
- rdoc (6.12.0)
133
+ rdoc (6.14.1)
134
+ erb
128
135
  psych (>= 4.0.0)
129
136
  regexp_parser (2.10.0)
130
- reline (0.6.0)
137
+ reline (0.6.1)
131
138
  io-console (~> 0.5)
132
- rspec (3.13.0)
139
+ rspec (3.13.1)
133
140
  rspec-core (~> 3.13.0)
134
141
  rspec-expectations (~> 3.13.0)
135
142
  rspec-mocks (~> 3.13.0)
136
- rspec-core (3.13.3)
143
+ rspec-core (3.13.5)
137
144
  rspec-support (~> 3.13.0)
138
- rspec-expectations (3.13.3)
145
+ rspec-expectations (3.13.5)
139
146
  diff-lcs (>= 1.2.0, < 2.0)
140
147
  rspec-support (~> 3.13.0)
141
- rspec-mocks (3.13.2)
148
+ rspec-mocks (3.13.5)
142
149
  diff-lcs (>= 1.2.0, < 2.0)
143
150
  rspec-support (~> 3.13.0)
144
- rspec-support (3.13.2)
145
- rubocop (1.74.0)
151
+ rspec-support (3.13.4)
152
+ rubocop (1.77.0)
146
153
  json (~> 2.3)
147
154
  language_server-protocol (~> 3.17.0.2)
148
155
  lint_roller (~> 1.1.0)
@@ -150,19 +157,20 @@ GEM
150
157
  parser (>= 3.3.0.2)
151
158
  rainbow (>= 2.2.2, < 4.0)
152
159
  regexp_parser (>= 2.9.3, < 3.0)
153
- rubocop-ast (>= 1.38.0, < 2.0)
160
+ rubocop-ast (>= 1.45.1, < 2.0)
154
161
  ruby-progressbar (~> 1.7)
155
162
  unicode-display_width (>= 2.4.0, < 4.0)
156
- rubocop-ast (1.39.0)
157
- parser (>= 3.3.1.0)
158
- rubocop-performance (1.24.0)
163
+ rubocop-ast (1.45.1)
164
+ parser (>= 3.3.7.2)
165
+ prism (~> 1.4)
166
+ rubocop-performance (1.25.0)
159
167
  lint_roller (~> 1.1)
160
- rubocop (>= 1.72.1, < 2.0)
168
+ rubocop (>= 1.75.0, < 2.0)
161
169
  rubocop-ast (>= 1.38.0, < 2.0)
162
170
  rubocop-rake (0.7.1)
163
171
  lint_roller (~> 1.1)
164
172
  rubocop (>= 1.72.1)
165
- rubocop-rspec (3.5.0)
173
+ rubocop-rspec (3.6.0)
166
174
  lint_roller (~> 1.1)
167
175
  rubocop (~> 1.72, >= 1.72.1)
168
176
  ruby-progressbar (1.13.0)
@@ -174,7 +182,7 @@ GEM
174
182
  simplecov_json_formatter (~> 0.1)
175
183
  simplecov-html (0.13.1)
176
184
  simplecov_json_formatter (0.1.4)
177
- stringio (3.1.5)
185
+ stringio (3.1.7)
178
186
  strings (0.2.1)
179
187
  strings-ansi (~> 0.2)
180
188
  unicode-display_width (>= 1.5, < 3.0)
@@ -207,7 +215,7 @@ GEM
207
215
  unicode_utils (1.4.0)
208
216
  uri (1.0.3)
209
217
  wisper (2.0.1)
210
- zeitwerk (2.7.2)
218
+ zeitwerk (2.7.3)
211
219
 
212
220
  PLATFORMS
213
221
  aarch64-linux-gnu
@@ -237,4 +245,4 @@ DEPENDENCIES
237
245
  simplecov
238
246
 
239
247
  BUNDLED WITH
240
- 2.6.5
248
+ 2.6.9
data/README.md CHANGED
@@ -280,6 +280,17 @@ Use case: Say you have a very large IMAP account, and you would like to know the
280
280
 
281
281
  Use the `--csv` flag.
282
282
 
283
+ ### Writing IMAP responses to file
284
+
285
+ Using the `-O`/`--log-output` flag, you can have `imapcli` write the IMAP responses
286
+ to a file in JSON format:
287
+
288
+ ```bash
289
+ imapcli -s yourserver.example.com -u username -P -O output_file.json stats Inbox
290
+ ```
291
+
292
+ **WARNING:** The output file will be overwritten without notice!
293
+
283
294
  ## Alternative resources
284
295
 
285
296
  While researching command-line tools for IMAP servers, I came across the
data/imapcli.gemspec CHANGED
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_dependency('dotenv', '~> 3.1')
29
29
  s.add_dependency('gli', '~> 2.22')
30
30
  s.add_dependency('net-imap')
31
+ s.add_dependency('oj', '~> 3.16')
31
32
  s.add_dependency('tty-progressbar', '~> 0.18')
32
33
  s.add_dependency('tty-prompt', '~> 0.23')
33
34
  s.add_dependency('tty-table', '~> 0.12')
data/lib/imapcli/cli.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'oj'
4
+
3
5
  module Imapcli
4
6
  class Cli # rubocop:disable Metrics/ClassLength,Style/Documentation
5
7
  extend GLI::App
@@ -31,8 +33,8 @@ module Imapcli
31
33
  desc 'Prompt for password'
32
34
  switch %i[P prompt], negatable: false
33
35
 
34
- desc 'Verbose output (e.g., response values from Rubys Net::IMAP)'
35
- switch %i[v verbose], negatable: false
36
+ desc 'Output responses from Rubys Net::IMAP to file in JSON format. File will be overwritten if it exists!'
37
+ flag %i[O log-output]
36
38
 
37
39
  desc 'Tests if the server is available and log-in succeeds with the credentials'
38
40
  command :check do |c|
@@ -89,7 +91,7 @@ module Imapcli
89
91
  if progress_bar
90
92
  progress_bar.advance
91
93
  else
92
- @prompt.say "info: collecting stats for #{n} folders" if n > 1
94
+ @prompt.warn "info: collecting stats for #{n} folders" if n > 1
93
95
  progress_bar = TTY::ProgressBar.new(
94
96
  'collecting stats... :current/:total (:percent, :eta remaining)',
95
97
  total: n, clear: true
@@ -111,9 +113,9 @@ module Imapcli
111
113
  formatted_body = formatted_body.insert(0, :separator).insert(-2, :separator)
112
114
 
113
115
  if options[:human]
114
- @prompt.say "notice: -H/--human flag present, message sizes are given with SI prefixes"
116
+ @prompt.warn "notice: -H/--human flag present, message sizes are given with SI prefixes"
115
117
  else
116
- @prompt.say "notice: message sizes are given in bytes"
118
+ @prompt.warn "notice: message sizes are given in bytes"
117
119
  end
118
120
 
119
121
  table = TTY::Table.new(head, formatted_body)
@@ -143,27 +145,25 @@ module Imapcli
143
145
  global[:p] = @prompt.mask 'Enter password:' if global[:P]
144
146
  global[:p] ||= ENV.fetch('IMAP_PASS', nil)
145
147
 
146
- client = Imapcli::Client.new(global[:s], global[:u], global[:p])
148
+ @client = Imapcli::Client.new(global[:s], global[:u], global[:p])
147
149
  @prompt.say "server: #{global[:s]}"
148
150
  @prompt.say "user: #{global[:u]}"
149
- raise 'invalid server name' unless client.server_valid?
150
- raise 'invalid user name' unless client.user_valid?
151
+ raise 'invalid server name' unless @client.server_valid?
152
+ raise 'invalid user name' unless @client.user_valid?
151
153
 
152
154
  @prompt.warn 'warning: no password was provided (missing -p/-P option)' unless global[:p]
153
- raise 'unable to connect to server' unless client.connection
155
+ raise 'unable to connect to server' unless @client.connection
154
156
 
155
- @command = Imapcli::Command.new(client)
157
+ @command = Imapcli::Command.new(@client)
156
158
 
157
159
  true
158
160
  end
159
161
 
160
162
  post do |global, _command, _options, _args|
161
163
  @client&.logout
162
- if global[:v]
163
- @prompt.say "\n>>> --verbose switch on, listing server responses <<<"
164
- @client.responses.each do |response|
165
- @prompt.say response
166
- end
164
+ if file_name = global[:o]
165
+ @prompt.warn "notice: writing IMAP responses to #{file_name.dump}"
166
+ File.write(file_name, Oj.dump(@client.responses, mode: :object, indent: 2, escape: :unicode_xss, symbolize_names: false))
167
167
  end
168
168
  end
169
169
 
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+
3
5
  module Imapcli
4
6
  # Wrapper for Net::IMAP
5
7
  class Client # rubocop:disable Metrics/ClassLength
6
8
  attr_accessor :port, :user, :pass
7
- attr_reader :responses
8
9
 
9
10
  ## Initializs the Client class.
10
11
  ##
@@ -17,7 +18,7 @@ module Imapcli
17
18
  self.server = server_with_optional_port
18
19
  @user = user
19
20
  @pass = pass
20
- clear_log
21
+ clear_responses
21
22
  end
22
23
 
23
24
  # Attribute reader for the server domain name
@@ -57,10 +58,15 @@ module Imapcli
57
58
  end
58
59
 
59
60
  # Clears the server response log
60
- def clear_log
61
+ def clear_responses
61
62
  @log = []
62
63
  end
63
64
 
65
+ # Returns the IMAP server response log
66
+ def responses
67
+ @log
68
+ end
69
+
64
70
  # Returns the last response from the server
65
71
  def last_response
66
72
  @log.last
@@ -96,17 +102,17 @@ module Imapcli
96
102
  # Returns the server's greeting (which may reveal the server software name
97
103
  # such as 'Dovecot').
98
104
  def greeting
99
- query_server { connection.greeting.data.text.strip }
105
+ query_server('greeting') { connection.greeting.data.text.strip }
100
106
  end
101
107
 
102
108
  # Returns the server's capabilities.
103
109
  def capability
104
- @capability ||= query_server { connection.capability }
110
+ @capability ||= query_server('capability') { connection.capability }
105
111
  end
106
112
 
107
113
  # Returns the character that is used to separate nested mailbox names.
108
114
  def separator
109
- @separator ||= query_server { connection.list('', '')[0].delim }
115
+ @separator ||= query_server("list('')") { connection.list('', '')[0].delim }
110
116
  end
111
117
 
112
118
  # Returns true if the server supports the IMAP QUOTA extension.
@@ -120,7 +126,7 @@ module Imapcli
120
126
  return unless supports_quota
121
127
 
122
128
  @quota ||= begin
123
- info = query_server { @connection.getquotaroot('INBOX')[1] }
129
+ info = query_server("getquotaroot('INBOX')") { @connection.getquotaroot('INBOX')[1] }
124
130
  percent = info.quota.to_i.positive? ? info.usage.to_i.fdiv(info.quota.to_i) * 100 : nil
125
131
  [info.usage, info.quota, percent]
126
132
  end
@@ -130,8 +136,8 @@ module Imapcli
130
136
  #
131
137
  # The value is currently NOT cached.
132
138
  def messages(mailbox)
133
- query_server { connection.examine(mailbox) }
134
- query_server { connection.search('ALL') }
139
+ query_server("examine('#{mailbox}')") { connection.examine(mailbox) }
140
+ query_server("search('ALL')") { connection.search('ALL') }
135
141
  end
136
142
 
137
143
  # Examines a mailbox and returns statistics about the messages in it.
@@ -149,7 +155,7 @@ module Imapcli
149
155
  if messages.empty?
150
156
  []
151
157
  else
152
- query_server do
158
+ query_server('fetch(...)') do
153
159
  messages.each_slice(1000).map do |some_messages|
154
160
  connection.fetch(some_messages, 'RFC822.SIZE').map do |f|
155
161
  f.attr['RFC822.SIZE']
@@ -168,7 +174,7 @@ module Imapcli
168
174
  #
169
175
  # The value is cached.
170
176
  def mailboxes
171
- @mailboxes ||= query_server { @connection.list('', '*') }
177
+ @mailboxes ||= query_server('list') { @connection.list('', '*') }
172
178
  end
173
179
 
174
180
  # Returns a tree of +Imapcli::Mailbox+ objects.
@@ -188,12 +194,10 @@ module Imapcli
188
194
  private
189
195
 
190
196
  def response_ok?(response)
191
- @log << response
192
197
  response.name == 'OK'
193
198
  end
194
199
 
195
200
  def log_error(error)
196
- @log << error
197
201
  false
198
202
  end
199
203
 
@@ -203,13 +207,31 @@ module Imapcli
203
207
  # error if not. The code that queries the server must be contained in the
204
208
  # +block+, and the +block+'s return value is returned by this function.
205
209
  # The +connection+'s responses are logged.
206
- def query_server
210
+ def query_server(imap_command)
207
211
  raise('no connection to a server') unless connection
208
212
 
209
213
  result = yield
210
- @log << connection.responses
214
+ @log << {
215
+ 'imap_command': imap_command,
216
+ 'imap_response': connection.responses.to_h
217
+ }
211
218
  result
212
219
  end
213
220
 
221
+ # Recursively convert structs in an array of hashes to hashes
222
+ # Inspired by https://stackoverflow.com/a/62804063/270712
223
+ # and rephrased to improve readability a bit
224
+ def to_h_recursively(hash)
225
+ hash.map do |value|
226
+ if value.is_a?(Arry)
227
+ to_h_recursively(value)
228
+ elsif value.is_a?(Struct)
229
+ value.to_h
230
+ else
231
+ value
232
+ end
233
+ end
234
+ end
235
+
214
236
  end
215
237
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Imapcli
4
- VERSION = '2.1.0'
4
+ VERSION = '3.0.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imapcli
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Kraus (bovender)
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-03-16 00:00:00.000000000 Z
10
+ date: 2025-06-29 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activesupport
@@ -94,6 +93,20 @@ dependencies:
94
93
  - - ">="
95
94
  - !ruby/object:Gem::Version
96
95
  version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: oj
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.16'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.16'
97
110
  - !ruby/object:Gem::Dependency
98
111
  name: tty-progressbar
99
112
  requirement: !ruby/object:Gem::Requirement
@@ -150,7 +163,6 @@ dependencies:
150
163
  - - "~>"
151
164
  - !ruby/object:Gem::Version
152
165
  version: 2.7.0
153
- description:
154
166
  email: bovender@bovender.de
155
167
  executables:
156
168
  - imapcli
@@ -195,7 +207,6 @@ homepage: https://github.com/bovender/imapcli
195
207
  licenses:
196
208
  - Apache-2.0
197
209
  metadata: {}
198
- post_install_message:
199
210
  rdoc_options:
200
211
  - "--title"
201
212
  - imapcli
@@ -215,8 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
215
226
  - !ruby/object:Gem::Version
216
227
  version: '0'
217
228
  requirements: []
218
- rubygems_version: 3.5.22
219
- signing_key:
229
+ rubygems_version: 3.6.2
220
230
  specification_version: 4
221
231
  summary: Command-line tool to query IMAP servers
222
232
  test_files: []