imap-backup 9.1.0 → 9.2.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/lib/imap/backup/cli.rb +12 -12
- data/lib/imap/backup/logger.rb +9 -4
- data/lib/imap/backup/naming.rb +25 -0
- data/lib/imap/backup/serializer/appender.rb +2 -0
- data/lib/imap/backup/serializer.rb +14 -7
- data/lib/imap/backup/version.rb +1 -1
- data/lib/text/sanitizer.rb +46 -0
- metadata +4 -3
- data/lib/imap/backup/sanitizer.rb +0 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2817e61358b848f7dbef08e1a16562def8cd364e66d317e4dac56c1f5e62f958
|
4
|
+
data.tar.gz: ec0e2d2963e863b204b0529ca3746492703486e8f77a9e7c08bc301b203249de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 66871fce3faebbcbd87737fef230803b46f32025b28753fe4f83813e652ef14817fce302da0570000f0d0ecb582862589a84f535a94aa1fa7cc1578eaf30591c
|
7
|
+
data.tar.gz: 274cfc47767322e31eb1e7206c3d1d449b2098ba1a65073c80aa5010c06924abfc7a952aeace01436715a7f95599503d86bcecbbdf210f7c8b5529bf7bee4fdf
|
data/lib/imap/backup/cli.rb
CHANGED
@@ -54,8 +54,8 @@ module Imap::Backup
|
|
54
54
|
aliases: ["-r"]
|
55
55
|
)
|
56
56
|
def backup
|
57
|
-
Imap::Backup::Logger.setup_logging
|
58
|
-
Backup.new(
|
57
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
58
|
+
Backup.new(non_logging_options).run
|
59
59
|
end
|
60
60
|
|
61
61
|
desc "local SUBCOMMAND [OPTIONS]", "View local info"
|
@@ -111,8 +111,8 @@ module Imap::Backup
|
|
111
111
|
aliases: ["-s"]
|
112
112
|
)
|
113
113
|
def migrate(source_email, destination_email)
|
114
|
-
Imap::Backup::Logger.setup_logging
|
115
|
-
Migrate.new(source_email, destination_email, **
|
114
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
115
|
+
Migrate.new(source_email, destination_email, **non_logging_options).run
|
116
116
|
end
|
117
117
|
|
118
118
|
desc(
|
@@ -161,8 +161,8 @@ module Imap::Backup
|
|
161
161
|
aliases: ["-s"]
|
162
162
|
)
|
163
163
|
def mirror(source_email, destination_email)
|
164
|
-
Imap::Backup::Logger.setup_logging
|
165
|
-
Mirror.new(source_email, destination_email, **
|
164
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
165
|
+
Mirror.new(source_email, destination_email, **non_logging_options).run
|
166
166
|
end
|
167
167
|
|
168
168
|
desc "remote SUBCOMMAND [OPTIONS]", "View info about online accounts"
|
@@ -178,8 +178,8 @@ module Imap::Backup
|
|
178
178
|
quiet_option
|
179
179
|
verbose_option
|
180
180
|
def restore(email = nil)
|
181
|
-
Imap::Backup::Logger.setup_logging
|
182
|
-
Restore.new(email,
|
181
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
182
|
+
Restore.new(email, non_logging_options).run
|
183
183
|
end
|
184
184
|
|
185
185
|
desc "setup", "Configure imap-backup"
|
@@ -191,8 +191,8 @@ module Imap::Backup
|
|
191
191
|
quiet_option
|
192
192
|
verbose_option
|
193
193
|
def setup
|
194
|
-
Imap::Backup::Logger.setup_logging
|
195
|
-
Setup.new(
|
194
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
195
|
+
Setup.new(non_logging_options).run
|
196
196
|
end
|
197
197
|
|
198
198
|
desc "stats EMAIL [OPTIONS]", "Print stats for each account folder"
|
@@ -206,8 +206,8 @@ module Imap::Backup
|
|
206
206
|
quiet_option
|
207
207
|
verbose_option
|
208
208
|
def stats(email)
|
209
|
-
Imap::Backup::Logger.setup_logging
|
210
|
-
Stats.new(email,
|
209
|
+
non_logging_options = Imap::Backup::Logger.setup_logging(options)
|
210
|
+
Stats.new(email, non_logging_options).run
|
211
211
|
end
|
212
212
|
|
213
213
|
desc "utils SUBCOMMAND [OPTIONS]", "Various utilities"
|
data/lib/imap/backup/logger.rb
CHANGED
@@ -2,7 +2,7 @@ require "logger"
|
|
2
2
|
require "singleton"
|
3
3
|
|
4
4
|
require "imap/backup/configuration"
|
5
|
-
require "
|
5
|
+
require "text/sanitizer"
|
6
6
|
|
7
7
|
module Imap::Backup
|
8
8
|
class Logger
|
@@ -13,11 +13,14 @@ module Imap::Backup
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.setup_logging(options = {})
|
16
|
+
copy = options.clone
|
17
|
+
quiet = copy.delete(:quiet)
|
18
|
+
verbose = copy.delete(:verbose)
|
16
19
|
level =
|
17
20
|
case
|
18
|
-
when
|
21
|
+
when quiet
|
19
22
|
::Logger::Severity::UNKNOWN
|
20
|
-
when
|
23
|
+
when verbose
|
21
24
|
::Logger::Severity::DEBUG
|
22
25
|
else
|
23
26
|
::Logger::Severity::INFO
|
@@ -25,10 +28,12 @@ module Imap::Backup
|
|
25
28
|
logger.level = level
|
26
29
|
debug = level == ::Logger::Severity::DEBUG
|
27
30
|
Net::IMAP.debug = debug
|
31
|
+
|
32
|
+
copy
|
28
33
|
end
|
29
34
|
|
30
35
|
def self.sanitize_stderr
|
31
|
-
sanitizer = Sanitizer.new($stdout)
|
36
|
+
sanitizer = Text::Sanitizer.new($stdout)
|
32
37
|
previous_stderr = $stderr
|
33
38
|
$stderr = sanitizer
|
34
39
|
yield
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Imap::Backup
|
2
|
+
class Naming
|
3
|
+
INVALID_FILENAME_CHARACTERS = ":%;".freeze
|
4
|
+
INVALID_FILENAME_CHARACTER_MATCH = /([#{INVALID_FILENAME_CHARACTERS}])/.freeze
|
5
|
+
|
6
|
+
# `*_path` functions treat `/` as an acceptable character
|
7
|
+
def self.to_local_path(name)
|
8
|
+
name.gsub(INVALID_FILENAME_CHARACTER_MATCH) do |character|
|
9
|
+
hex =
|
10
|
+
character.
|
11
|
+
codepoints[0].
|
12
|
+
to_s(16)
|
13
|
+
"%#{hex};"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.from_local_path(name)
|
18
|
+
name.gsub(/%(.*?);/) do
|
19
|
+
::Regexp.last_match(1).
|
20
|
+
to_i(16).
|
21
|
+
chr("UTF-8")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "forwardable"
|
2
2
|
|
3
3
|
require "email/mboxrd/message"
|
4
|
+
require "imap/backup/naming"
|
4
5
|
require "imap/backup/serializer/appender"
|
5
6
|
require "imap/backup/serializer/imap"
|
6
7
|
require "imap/backup/serializer/message"
|
@@ -72,7 +73,7 @@ module Imap::Backup
|
|
72
73
|
def append(uid, message, flags)
|
73
74
|
validate!
|
74
75
|
|
75
|
-
appender = Serializer::Appender.new(folder:
|
76
|
+
appender = Serializer::Appender.new(folder: sanitized, imap: imap, mbox: mbox)
|
76
77
|
appender.run(uid: uid, message: message, flags: flags)
|
77
78
|
end
|
78
79
|
|
@@ -116,14 +117,16 @@ module Imap::Backup
|
|
116
117
|
end
|
117
118
|
|
118
119
|
def folder_path
|
119
|
-
self.class.folder_path_for(path: path, folder:
|
120
|
+
self.class.folder_path_for(path: path, folder: sanitized)
|
120
121
|
end
|
121
122
|
|
122
123
|
private
|
123
124
|
|
124
125
|
def rename(new_name)
|
125
126
|
destination = self.class.folder_path_for(path: path, folder: new_name)
|
126
|
-
|
127
|
+
relative = File.dirname(new_name)
|
128
|
+
directory = Serializer::Directory.new(path, relative)
|
129
|
+
directory.ensure_exists
|
127
130
|
mbox.rename destination
|
128
131
|
imap.rename destination
|
129
132
|
end
|
@@ -136,7 +139,7 @@ module Imap::Backup
|
|
136
139
|
def mbox
|
137
140
|
@mbox ||=
|
138
141
|
begin
|
139
|
-
ensure_containing_directory
|
142
|
+
ensure_containing_directory
|
140
143
|
Serializer::Mbox.new(folder_path)
|
141
144
|
end
|
142
145
|
end
|
@@ -144,11 +147,15 @@ module Imap::Backup
|
|
144
147
|
def imap
|
145
148
|
@imap ||=
|
146
149
|
begin
|
147
|
-
ensure_containing_directory
|
150
|
+
ensure_containing_directory
|
148
151
|
Serializer::Imap.new(folder_path)
|
149
152
|
end
|
150
153
|
end
|
151
154
|
|
155
|
+
def sanitized
|
156
|
+
@sanitized ||= Naming.to_local_path(folder)
|
157
|
+
end
|
158
|
+
|
152
159
|
def optionally_migrate2to3
|
153
160
|
migrator = Version2Migrator.new(folder_path)
|
154
161
|
return if !migrator.required?
|
@@ -162,8 +169,8 @@ module Imap::Backup
|
|
162
169
|
migrator.run
|
163
170
|
end
|
164
171
|
|
165
|
-
def ensure_containing_directory
|
166
|
-
relative = File.dirname(
|
172
|
+
def ensure_containing_directory
|
173
|
+
relative = File.dirname(sanitized)
|
167
174
|
directory = Serializer::Directory.new(path, relative)
|
168
175
|
directory.ensure_exists
|
169
176
|
end
|
data/lib/imap/backup/version.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module Text; end
|
4
|
+
|
5
|
+
class Text::Sanitizer
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
attr_reader :output
|
9
|
+
|
10
|
+
delegate puts: :output
|
11
|
+
delegate write: :output
|
12
|
+
|
13
|
+
def initialize(output)
|
14
|
+
@output = output
|
15
|
+
@current = ""
|
16
|
+
end
|
17
|
+
|
18
|
+
def print(*args)
|
19
|
+
@current << args.join
|
20
|
+
loop do
|
21
|
+
line, newline, rest = @current.partition("\n")
|
22
|
+
break if newline != "\n"
|
23
|
+
|
24
|
+
clean = sanitize(line)
|
25
|
+
output.puts clean
|
26
|
+
@current = rest
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def flush
|
31
|
+
return if @current == ""
|
32
|
+
|
33
|
+
clean = sanitize(@current)
|
34
|
+
output.puts clean
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def sanitize(text)
|
40
|
+
# Hide password in Net::IMAP debug output
|
41
|
+
text.gsub(
|
42
|
+
/\A(C: RUBY\d+ LOGIN \S+) \S+/,
|
43
|
+
"\\1 [PASSWORD REDACTED]"
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: imap-backup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 9.
|
4
|
+
version: 9.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Yates
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -258,7 +258,7 @@ files:
|
|
258
258
|
- lib/imap/backup/migrator.rb
|
259
259
|
- lib/imap/backup/mirror.rb
|
260
260
|
- lib/imap/backup/mirror/map.rb
|
261
|
-
- lib/imap/backup/
|
261
|
+
- lib/imap/backup/naming.rb
|
262
262
|
- lib/imap/backup/serializer.rb
|
263
263
|
- lib/imap/backup/serializer/appender.rb
|
264
264
|
- lib/imap/backup/serializer/directory.rb
|
@@ -282,6 +282,7 @@ files:
|
|
282
282
|
- lib/imap/backup/utils.rb
|
283
283
|
- lib/imap/backup/version.rb
|
284
284
|
- lib/retry_on_error.rb
|
285
|
+
- lib/text/sanitizer.rb
|
285
286
|
homepage: https://github.com/joeyates/imap-backup
|
286
287
|
licenses:
|
287
288
|
- MIT
|
@@ -1,46 +0,0 @@
|
|
1
|
-
require "forwardable"
|
2
|
-
|
3
|
-
module Imap::Backup
|
4
|
-
class Sanitizer
|
5
|
-
extend Forwardable
|
6
|
-
|
7
|
-
attr_reader :output
|
8
|
-
|
9
|
-
delegate puts: :output
|
10
|
-
delegate write: :output
|
11
|
-
|
12
|
-
def initialize(output)
|
13
|
-
@output = output
|
14
|
-
@current = ""
|
15
|
-
end
|
16
|
-
|
17
|
-
def print(*args)
|
18
|
-
@current << args.join
|
19
|
-
loop do
|
20
|
-
line, newline, rest = @current.partition("\n")
|
21
|
-
break if newline != "\n"
|
22
|
-
|
23
|
-
clean = sanitize(line)
|
24
|
-
output.puts clean
|
25
|
-
@current = rest
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def flush
|
30
|
-
return if @current == ""
|
31
|
-
|
32
|
-
clean = sanitize(@current)
|
33
|
-
output.puts clean
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def sanitize(text)
|
39
|
-
# Hide password in Net::IMAP debug output
|
40
|
-
text.gsub(
|
41
|
-
/\A(C: RUBY\d+ LOGIN \S+) \S+/,
|
42
|
-
"\\1 [PASSWORD REDACTED]"
|
43
|
-
)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|