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 +4 -4
- data/.devcontainer/devcontainer.json +1 -1
- data/CHANGELOG.md +26 -0
- data/Dockerfile +16 -12
- data/Gemfile.lock +57 -49
- data/README.md +11 -0
- data/imapcli.gemspec +1 -0
- data/lib/imapcli/cli.rb +15 -15
- data/lib/imapcli/client.rb +37 -15
- data/lib/imapcli/version.rb +1 -1
- metadata +17 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf3da9229783f1c5eff9461b6062e36ae8d51eac5ce818a980425c25d9c5e431
|
4
|
+
data.tar.gz: b2a6c6476a95644f7a4a97e2f7da6120858d2057afca64372a69424a1e6f036e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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 (
|
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.
|
33
|
-
base64 (0.
|
34
|
-
benchmark (0.4.
|
35
|
-
bigdecimal (3.
|
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.
|
39
|
-
csv (3.3.
|
39
|
+
connection_pool (2.5.3)
|
40
|
+
csv (3.3.5)
|
40
41
|
date (3.4.1)
|
41
|
-
debug (1.
|
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.
|
46
|
+
diff-lcs (1.6.2)
|
46
47
|
docile (1.4.1)
|
47
|
-
dotenv (3.1.
|
48
|
-
drb (2.2.
|
49
|
-
|
50
|
-
ffi (1.17.
|
51
|
-
ffi (1.17.
|
52
|
-
ffi (1.17.
|
53
|
-
ffi (1.17.
|
54
|
-
ffi (1.17.
|
55
|
-
ffi (1.17.
|
56
|
-
ffi (1.17.
|
57
|
-
ffi (1.17.
|
58
|
-
ffi (1.17.
|
59
|
-
ffi (1.17.
|
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.
|
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.
|
87
|
-
language_server-protocol (3.17.0.
|
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.
|
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.
|
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
|
-
|
106
|
-
|
107
|
-
|
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.
|
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.
|
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.
|
133
|
+
rdoc (6.14.1)
|
134
|
+
erb
|
128
135
|
psych (>= 4.0.0)
|
129
136
|
regexp_parser (2.10.0)
|
130
|
-
reline (0.6.
|
137
|
+
reline (0.6.1)
|
131
138
|
io-console (~> 0.5)
|
132
|
-
rspec (3.13.
|
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.
|
143
|
+
rspec-core (3.13.5)
|
137
144
|
rspec-support (~> 3.13.0)
|
138
|
-
rspec-expectations (3.13.
|
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.
|
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.
|
145
|
-
rubocop (1.
|
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.
|
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.
|
157
|
-
parser (>= 3.3.
|
158
|
-
|
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.
|
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.
|
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.
|
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.
|
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.
|
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 '
|
35
|
-
|
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.
|
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.
|
116
|
+
@prompt.warn "notice: -H/--human flag present, message sizes are given with SI prefixes"
|
115
117
|
else
|
116
|
-
@prompt.
|
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[:
|
163
|
-
@prompt.
|
164
|
-
@client.responses
|
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
|
|
data/lib/imapcli/client.rb
CHANGED
@@ -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
|
-
|
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
|
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 <<
|
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
|
data/lib/imapcli/version.rb
CHANGED
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:
|
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-
|
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.
|
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: []
|