imapcli 1.0.5 → 2.0.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 +4 -4
- data/.devcontainer/devcontainer.json +22 -0
- data/.github/dependabot.yml +12 -0
- data/.github/workflows/ci.yml +57 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +53 -0
- data/.vscode/launch.json +59 -0
- data/CHANGELOG.md +71 -0
- data/Dockerfile +8 -5
- data/Gemfile +13 -4
- data/Gemfile.lock +189 -67
- data/Guardfile +8 -6
- data/README.md +68 -101
- data/Rakefile +5 -7
- data/bin/bundle +109 -0
- data/bin/rspec +27 -0
- data/bin/rubocop +27 -0
- data/exe/imapcli +8 -0
- data/imapcli.gemspec +26 -19
- data/lib/imapcli/cli.rb +180 -0
- data/lib/imapcli/client.rb +32 -32
- data/lib/imapcli/command.rb +44 -44
- data/lib/imapcli/mailbox.rb +34 -38
- data/lib/imapcli/option_validator.rb +6 -6
- data/lib/imapcli/stats.rb +9 -11
- data/lib/imapcli/version.rb +3 -1
- data/lib/imapcli.rb +20 -6
- data/spec/lib/imapcli/client_spec.rb +34 -22
- data/spec/lib/imapcli/command_spec.rb +35 -31
- data/spec/lib/imapcli/mailbox_spec.rb +36 -23
- data/spec/lib/imapcli/stats_spec.rb +18 -16
- data/spec/spec_helper.rb +22 -70
- metadata +64 -44
- data/.rspec +0 -1
- data/NEWS +0 -12
- data/bin/imapcli +0 -164
- data/spec/lib/imapcli/option_validator_spec.rb +0 -4
metadata
CHANGED
@@ -1,142 +1,156 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: imapcli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Kraus (bovender)
|
8
|
-
autorequire:
|
9
|
-
bindir:
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: csv
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
-
type: :
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: descriptive_statistics
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '5
|
34
|
-
type: :
|
33
|
+
version: '2.5'
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '5
|
40
|
+
version: '2.5'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: dotenv
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '3.1'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '3.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: activesupport
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '8.0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '8.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: gli
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '2.22'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '2.22'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: net-imap
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '0'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: tty-progressbar
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.18'
|
104
104
|
type: :runtime
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.18'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: tty-prompt
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0.
|
117
|
+
version: '0.23'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0.
|
124
|
+
version: '0.23'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: tty-table
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version: '0.
|
131
|
+
version: '0.12'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.12'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: zeitwerk
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 2.7.0
|
132
146
|
type: :runtime
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
150
|
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
139
|
-
description:
|
152
|
+
version: 2.7.0
|
153
|
+
description:
|
140
154
|
email: bovender@bovender.de
|
141
155
|
executables:
|
142
156
|
- imapcli
|
@@ -145,19 +159,27 @@ extra_rdoc_files:
|
|
145
159
|
- README.md
|
146
160
|
- imapcli.rdoc
|
147
161
|
files:
|
162
|
+
- ".devcontainer/devcontainer.json"
|
163
|
+
- ".github/dependabot.yml"
|
164
|
+
- ".github/workflows/ci.yml"
|
148
165
|
- ".gitignore"
|
149
|
-
- ".
|
166
|
+
- ".rubocop.yml"
|
167
|
+
- ".vscode/launch.json"
|
168
|
+
- CHANGELOG.md
|
150
169
|
- Dockerfile
|
151
170
|
- Gemfile
|
152
171
|
- Gemfile.lock
|
153
172
|
- Guardfile
|
154
|
-
- NEWS
|
155
173
|
- README.md
|
156
174
|
- Rakefile
|
157
|
-
- bin/
|
175
|
+
- bin/bundle
|
176
|
+
- bin/rspec
|
177
|
+
- bin/rubocop
|
178
|
+
- exe/imapcli
|
158
179
|
- imapcli.gemspec
|
159
180
|
- imapcli.rdoc
|
160
181
|
- lib/imapcli.rb
|
182
|
+
- lib/imapcli/cli.rb
|
161
183
|
- lib/imapcli/client.rb
|
162
184
|
- lib/imapcli/command.rb
|
163
185
|
- lib/imapcli/mailbox.rb
|
@@ -167,14 +189,13 @@ files:
|
|
167
189
|
- spec/lib/imapcli/client_spec.rb
|
168
190
|
- spec/lib/imapcli/command_spec.rb
|
169
191
|
- spec/lib/imapcli/mailbox_spec.rb
|
170
|
-
- spec/lib/imapcli/option_validator_spec.rb
|
171
192
|
- spec/lib/imapcli/stats_spec.rb
|
172
193
|
- spec/spec_helper.rb
|
173
194
|
homepage: https://github.com/bovender/imapcli
|
174
195
|
licenses:
|
175
196
|
- Apache-2.0
|
176
197
|
metadata: {}
|
177
|
-
post_install_message:
|
198
|
+
post_install_message:
|
178
199
|
rdoc_options:
|
179
200
|
- "--title"
|
180
201
|
- imapcli
|
@@ -183,20 +204,19 @@ rdoc_options:
|
|
183
204
|
- "-ri"
|
184
205
|
require_paths:
|
185
206
|
- lib
|
186
|
-
- lib
|
187
207
|
required_ruby_version: !ruby/object:Gem::Requirement
|
188
208
|
requirements:
|
189
209
|
- - ">="
|
190
210
|
- !ruby/object:Gem::Version
|
191
|
-
version:
|
211
|
+
version: 3.1.0
|
192
212
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
213
|
requirements:
|
194
214
|
- - ">="
|
195
215
|
- !ruby/object:Gem::Version
|
196
216
|
version: '0'
|
197
217
|
requirements: []
|
198
|
-
rubygems_version: 3.
|
199
|
-
signing_key:
|
218
|
+
rubygems_version: 3.5.22
|
219
|
+
signing_key:
|
200
220
|
specification_version: 4
|
201
221
|
summary: Command-line tool to query IMAP servers
|
202
222
|
test_files: []
|
data/.rspec
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
--require spec_helper
|
data/NEWS
DELETED
data/bin/imapcli
DELETED
@@ -1,164 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'gli'
|
3
|
-
require 'imapcli'
|
4
|
-
require 'dotenv'
|
5
|
-
require 'tty-prompt'
|
6
|
-
require 'tty-table'
|
7
|
-
require 'tty-progressbar'
|
8
|
-
require 'csv'
|
9
|
-
# require 'pry'
|
10
|
-
# require 'pp'
|
11
|
-
|
12
|
-
Dotenv.load
|
13
|
-
|
14
|
-
include GLI::App
|
15
|
-
|
16
|
-
program_desc 'Command-line interface for IMAP servers'
|
17
|
-
|
18
|
-
version Imapcli::VERSION
|
19
|
-
|
20
|
-
subcommand_option_handling :normal
|
21
|
-
arguments :strict
|
22
|
-
sort_help :manually
|
23
|
-
wrap_help_text :tty_only
|
24
|
-
|
25
|
-
desc 'Domain name (FQDN) of the IMAP server'
|
26
|
-
default_value ENV['IMAP_SERVER']
|
27
|
-
arg_name 'imap.example.com'
|
28
|
-
flag [:s,:server]
|
29
|
-
|
30
|
-
desc 'Log-in name (username/email)'
|
31
|
-
default_value ENV['IMAP_USER']
|
32
|
-
arg_name 'user'
|
33
|
-
flag [:u,:user]
|
34
|
-
|
35
|
-
desc 'Log-in password'
|
36
|
-
# default_value ENV['IMAP_PASS']
|
37
|
-
arg_name 'password'
|
38
|
-
flag [:p,:password]
|
39
|
-
|
40
|
-
desc 'Prompt for password'
|
41
|
-
switch [:P, :prompt], negatable: false
|
42
|
-
|
43
|
-
desc 'Verbose output (e.g., response values from Ruby''s Net::IMAP)'
|
44
|
-
switch [:v,:verbose], negatable: false
|
45
|
-
|
46
|
-
desc 'Tests if the server is available and log-in succeeds with the credentials'
|
47
|
-
command :check do |c|
|
48
|
-
c.action do |global_options,options,args|
|
49
|
-
@command.check ? @prompt.ok('login successful') : @prompt.error('login failed')
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
desc 'Prints information about the server'
|
54
|
-
command :info do |c|
|
55
|
-
c.action do |global_options,options,args|
|
56
|
-
@command.info.each { |line| @prompt.say line }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
desc 'Lists mailboxes (folders)'
|
61
|
-
command :list do |c|
|
62
|
-
c.action do |global_options,options,args|
|
63
|
-
@command.list.each { |line| @prompt.say line }
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
desc 'Collects mailbox statistics'
|
68
|
-
arg_name :mailbox, optional: false, multiple: true
|
69
|
-
command :stats do |c|
|
70
|
-
c.switch [:r, :recurse], desc: 'Recurse into sub mailboxes', negatable: false
|
71
|
-
c.switch [:R, :no_recurse], desc: 'Do not recurse into sub mailboxes', negatable: false
|
72
|
-
c.flag [:o, :sort], desc: 'Order', arg_name: 'property'
|
73
|
-
c.switch [:O, :reverse], desc: 'Reverse sort order (largest first)', negatable: false
|
74
|
-
c.switch [:csv], desc: 'Output comma-separated values (CSV)'
|
75
|
-
|
76
|
-
c.action do |global_options,options,args|
|
77
|
-
raise unless @validator.stats_options_valid?(options, args)
|
78
|
-
|
79
|
-
progress_bar = nil
|
80
|
-
body = @command.stats(args, @validator.options) do |n|
|
81
|
-
if progress_bar
|
82
|
-
progress_bar.advance
|
83
|
-
else
|
84
|
-
@prompt.say "info: collecting stats for #{n} folders" if n > 1
|
85
|
-
progress_bar = TTY::ProgressBar.new(
|
86
|
-
"collecting stats... :current/:total (:percent, :eta remaining)",
|
87
|
-
total: n, clear: true)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
head = [ 'Mailbox', 'Count', 'Total size', 'Min', 'Q1', 'Median', 'Q3', 'Max' ]
|
92
|
-
if options[:csv]
|
93
|
-
@prompt.warn 'notice: messages sizes in CSV output are in kiB (1024 bytes)'
|
94
|
-
@prompt.say head.to_csv
|
95
|
-
last_mailbox_line = body.length == 1 ? -1 : -2 # skip grand total if present
|
96
|
-
body[0..last_mailbox_line].each { |row| @prompt.say row.to_csv }
|
97
|
-
else
|
98
|
-
nice_body = body.map do |row|
|
99
|
-
row[0..1] + row[2..-1].map { |cell| format_kib(cell) }
|
100
|
-
end
|
101
|
-
table = TTY::Table.new(head, nice_body)
|
102
|
-
@prompt.say table.render(:unicode, alignments: [:left] + Array.new(7, :right) )
|
103
|
-
if body.any? { |line| line[0].start_with? Imapcli::Command.unknown_mailbox_prefix }
|
104
|
-
@prompt.warn "#{Imapcli::Command.unknown_mailbox_prefix}unknown mailbox"
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def format_kib(kib)
|
111
|
-
if kib
|
112
|
-
kib.to_s.reverse.gsub(/...(?=.)/,'\&,').reverse + ' kiB'.freeze
|
113
|
-
else
|
114
|
-
'NA'
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
pre do |global,command,options,args|
|
119
|
-
@prompt = TTY::Prompt.new
|
120
|
-
@validator = Imapcli::OptionValidator.new()
|
121
|
-
raise unless @validator.global_options_valid?(global)
|
122
|
-
|
123
|
-
if global[:P]
|
124
|
-
global[:p] = @prompt.mask 'Enter password:'
|
125
|
-
end
|
126
|
-
global[:p] ||= ENV['IMAP_PASS']
|
127
|
-
|
128
|
-
client = Imapcli::Client.new(global[:s], global[:u], global[:p])
|
129
|
-
@prompt.say "server: #{global[:s]}"
|
130
|
-
@prompt.say "user: #{global[:u]}"
|
131
|
-
raise 'invalid server name' unless client.server_valid?
|
132
|
-
raise 'invalid user name' unless client.user_valid?
|
133
|
-
@prompt.warn 'warning: no password was provided (missing -p/-P option)' unless global[:p]
|
134
|
-
raise 'unable to connect to server' unless client.connection
|
135
|
-
@command = Imapcli::Command.new(client)
|
136
|
-
|
137
|
-
true
|
138
|
-
end
|
139
|
-
|
140
|
-
post do |global,command,options,args|
|
141
|
-
@client.logout if @client
|
142
|
-
if global[:v]
|
143
|
-
@prompt.say "\n>>> --verbose switch on, listing server responses <<<"
|
144
|
-
@client.responses.each do |response|
|
145
|
-
@prompt.say response
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
on_error do |exception|
|
151
|
-
@client.logout if @client
|
152
|
-
if @validator && @validator.errors.any?
|
153
|
-
@validator.errors.each { |error| @prompt.error error }
|
154
|
-
else
|
155
|
-
@prompt&.error "error: #{exception}"
|
156
|
-
end
|
157
|
-
@prompt.nil? # if we do not have a prompt yet, let GLI handle the exception
|
158
|
-
end
|
159
|
-
|
160
|
-
def print_warnings
|
161
|
-
@validator.warnings.each { |warning| @prompt.warn warning }
|
162
|
-
end
|
163
|
-
|
164
|
-
exit run(ARGV)
|