imap-backup 9.4.0.pre1 → 10.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/docs/development.md +6 -0
- data/lib/email/mboxrd/message.rb +5 -13
- data/lib/imap/backup/account/backup.rb +65 -0
- data/lib/imap/backup/account/{connection/backup_folders.rb → backup_folders.rb} +12 -5
- data/lib/imap/backup/account/{connection/client_factory.rb → client_factory.rb} +11 -11
- data/lib/imap/backup/account/folder.rb +8 -14
- data/lib/imap/backup/account/folder_ensurer.rb +24 -0
- data/lib/imap/backup/account/local_only_folder_deleter.rb +26 -0
- data/lib/imap/backup/account/restore.rb +20 -0
- data/lib/imap/backup/account/serialized_folders.rb +41 -0
- data/lib/imap/backup/account.rb +16 -4
- data/lib/imap/backup/cli/backup.rb +6 -7
- data/lib/imap/backup/cli/folder_enumerator.rb +1 -1
- data/lib/imap/backup/cli/helpers.rb +15 -15
- data/lib/imap/backup/cli/local.rb +31 -19
- data/lib/imap/backup/cli/mirror.rb +1 -1
- data/lib/imap/backup/cli/remote.rb +8 -8
- data/lib/imap/backup/cli/restore.rb +10 -14
- data/lib/imap/backup/cli/stats.rb +8 -3
- data/lib/imap/backup/cli/utils.rb +14 -5
- data/lib/imap/backup/cli.rb +13 -9
- data/lib/imap/backup/client/default.rb +28 -5
- data/lib/imap/backup/configuration.rb +8 -2
- data/lib/imap/backup/downloader.rb +4 -1
- data/lib/imap/backup/file_mode.rb +16 -0
- data/lib/imap/backup/mirror.rb +1 -2
- data/lib/imap/backup/serializer/directory.rb +6 -4
- data/lib/imap/backup/serializer/folder_maker.rb +33 -0
- data/lib/imap/backup/serializer/permission_checker.rb +26 -0
- data/lib/imap/backup/serializer.rb +9 -3
- data/lib/imap/backup/setup/connection_tester.rb +1 -7
- data/lib/imap/backup/setup/folder_chooser.rb +9 -9
- data/lib/imap/backup/thunderbird/mailbox_exporter.rb +34 -7
- data/lib/imap/backup/uploader.rb +1 -1
- data/lib/imap/backup/version.rb +3 -3
- data/lib/imap/backup.rb +0 -2
- metadata +14 -9
- data/lib/imap/backup/account/connection/folder_names.rb +0 -26
- data/lib/imap/backup/account/connection.rb +0 -136
- data/lib/imap/backup/utils.rb +0 -40
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:
|
4
|
+
version: 10.0.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-07-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -232,11 +232,14 @@ files:
|
|
232
232
|
- lib/email/provider/unknown.rb
|
233
233
|
- lib/imap/backup.rb
|
234
234
|
- lib/imap/backup/account.rb
|
235
|
-
- lib/imap/backup/account/
|
236
|
-
- lib/imap/backup/account/
|
237
|
-
- lib/imap/backup/account/
|
238
|
-
- lib/imap/backup/account/connection/folder_names.rb
|
235
|
+
- lib/imap/backup/account/backup.rb
|
236
|
+
- lib/imap/backup/account/backup_folders.rb
|
237
|
+
- lib/imap/backup/account/client_factory.rb
|
239
238
|
- lib/imap/backup/account/folder.rb
|
239
|
+
- lib/imap/backup/account/folder_ensurer.rb
|
240
|
+
- lib/imap/backup/account/local_only_folder_deleter.rb
|
241
|
+
- lib/imap/backup/account/restore.rb
|
242
|
+
- lib/imap/backup/account/serialized_folders.rb
|
240
243
|
- lib/imap/backup/cli.rb
|
241
244
|
- lib/imap/backup/cli/backup.rb
|
242
245
|
- lib/imap/backup/cli/folder_enumerator.rb
|
@@ -253,6 +256,7 @@ files:
|
|
253
256
|
- lib/imap/backup/client/default.rb
|
254
257
|
- lib/imap/backup/configuration.rb
|
255
258
|
- lib/imap/backup/downloader.rb
|
259
|
+
- lib/imap/backup/file_mode.rb
|
256
260
|
- lib/imap/backup/flag_refresher.rb
|
257
261
|
- lib/imap/backup/local_only_message_deleter.rb
|
258
262
|
- lib/imap/backup/logger.rb
|
@@ -263,10 +267,12 @@ files:
|
|
263
267
|
- lib/imap/backup/serializer.rb
|
264
268
|
- lib/imap/backup/serializer/appender.rb
|
265
269
|
- lib/imap/backup/serializer/directory.rb
|
270
|
+
- lib/imap/backup/serializer/folder_maker.rb
|
266
271
|
- lib/imap/backup/serializer/imap.rb
|
267
272
|
- lib/imap/backup/serializer/mbox.rb
|
268
273
|
- lib/imap/backup/serializer/message.rb
|
269
274
|
- lib/imap/backup/serializer/message_enumerator.rb
|
275
|
+
- lib/imap/backup/serializer/permission_checker.rb
|
270
276
|
- lib/imap/backup/serializer/unused_name_finder.rb
|
271
277
|
- lib/imap/backup/serializer/version2_migrator.rb
|
272
278
|
- lib/imap/backup/setup.rb
|
@@ -280,7 +286,6 @@ files:
|
|
280
286
|
- lib/imap/backup/setup/helpers.rb
|
281
287
|
- lib/imap/backup/thunderbird/mailbox_exporter.rb
|
282
288
|
- lib/imap/backup/uploader.rb
|
283
|
-
- lib/imap/backup/utils.rb
|
284
289
|
- lib/imap/backup/version.rb
|
285
290
|
- lib/retry_on_error.rb
|
286
291
|
- lib/text/sanitizer.rb
|
@@ -300,9 +305,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
300
305
|
version: '2.6'
|
301
306
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
302
307
|
requirements:
|
303
|
-
- - "
|
308
|
+
- - ">="
|
304
309
|
- !ruby/object:Gem::Version
|
305
|
-
version:
|
310
|
+
version: '0'
|
306
311
|
requirements: []
|
307
312
|
rubygems_version: 3.3.7
|
308
313
|
signing_key:
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Imap::Backup
|
2
|
-
class Account; end
|
3
|
-
class Account::Connection; end
|
4
|
-
|
5
|
-
class Account::Connection::FolderNames
|
6
|
-
attr_reader :account
|
7
|
-
attr_reader :client
|
8
|
-
|
9
|
-
def initialize(client:, account:)
|
10
|
-
@client = client
|
11
|
-
@account = account
|
12
|
-
end
|
13
|
-
|
14
|
-
def run
|
15
|
-
folder_names = client.list
|
16
|
-
|
17
|
-
if folder_names.empty?
|
18
|
-
message = "Unable to get folder list for account #{account.username}"
|
19
|
-
Logger.logger.info message
|
20
|
-
raise message
|
21
|
-
end
|
22
|
-
|
23
|
-
folder_names
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,136 +0,0 @@
|
|
1
|
-
require "imap/backup/client/apple_mail"
|
2
|
-
require "imap/backup/client/default"
|
3
|
-
require "imap/backup/account/connection/backup_folders"
|
4
|
-
require "imap/backup/account/connection/client_factory"
|
5
|
-
require "imap/backup/account/connection/folder_names"
|
6
|
-
require "imap/backup/flag_refresher"
|
7
|
-
require "imap/backup/local_only_message_deleter"
|
8
|
-
require "imap/backup/serializer/directory"
|
9
|
-
|
10
|
-
module Imap::Backup
|
11
|
-
class Account; end
|
12
|
-
|
13
|
-
class Account::Connection
|
14
|
-
attr_reader :account
|
15
|
-
|
16
|
-
def initialize(account)
|
17
|
-
@account = account
|
18
|
-
reset
|
19
|
-
end
|
20
|
-
|
21
|
-
def folder_names
|
22
|
-
@folder_names ||= Account::Connection::FolderNames.new(client: client, account: account).run
|
23
|
-
end
|
24
|
-
|
25
|
-
def backup_folders
|
26
|
-
@backup_folders ||=
|
27
|
-
Account::Connection::BackupFolders.new(client: client, account: account).run
|
28
|
-
end
|
29
|
-
|
30
|
-
def namespaces
|
31
|
-
client.namespace
|
32
|
-
end
|
33
|
-
|
34
|
-
def run_backup(refresh: false)
|
35
|
-
Logger.logger.info "Running backup of account: #{account.username}"
|
36
|
-
# start the connection so we get logging messages in the right order
|
37
|
-
client
|
38
|
-
ensure_account_folder
|
39
|
-
if account.mirror_mode
|
40
|
-
# Delete serialized folders that are not to be backed up
|
41
|
-
wanted = backup_folders.map(&:name)
|
42
|
-
local_folders do |serializer, _folder|
|
43
|
-
serializer.delete if !wanted.include?(serializer.folder)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
each_folder do |folder, serializer|
|
47
|
-
begin
|
48
|
-
next if !folder.exist?
|
49
|
-
rescue Encoding::UndefinedConversionError
|
50
|
-
message = "Skipping backup for '#{folder.name}' " \
|
51
|
-
"as it is not UTF-7 encoded correctly"
|
52
|
-
Logger.logger.info message
|
53
|
-
next
|
54
|
-
end
|
55
|
-
|
56
|
-
Logger.logger.debug "[#{folder.name}] running backup"
|
57
|
-
serializer.apply_uid_validity(folder.uid_validity)
|
58
|
-
begin
|
59
|
-
Downloader.new(
|
60
|
-
folder,
|
61
|
-
serializer,
|
62
|
-
multi_fetch_size: account.multi_fetch_size,
|
63
|
-
reset_seen_flags_after_fetch: account.reset_seen_flags_after_fetch
|
64
|
-
).run
|
65
|
-
if account.mirror_mode
|
66
|
-
Logger.logger.info "Mirror mode - Deleting messages only present locally"
|
67
|
-
LocalOnlyMessageDeleter.new(folder, serializer).run
|
68
|
-
end
|
69
|
-
FlagRefresher.new(folder, serializer).run if account.mirror_mode || refresh
|
70
|
-
rescue Net::IMAP::ByeResponseError
|
71
|
-
reconnect
|
72
|
-
retry
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def local_folders
|
78
|
-
return enum_for(:local_folders) if !block_given?
|
79
|
-
|
80
|
-
ensure_account_folder
|
81
|
-
glob = File.join(account.local_path, "**", "*.imap")
|
82
|
-
base = Pathname.new(account.local_path)
|
83
|
-
Pathname.glob(glob) do |path|
|
84
|
-
name = path.relative_path_from(base).to_s[0..-6]
|
85
|
-
serializer = Serializer.new(account.local_path, name)
|
86
|
-
folder = Account::Folder.new(self, name)
|
87
|
-
yield serializer, folder
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
def restore
|
92
|
-
local_folders do |serializer, folder|
|
93
|
-
Uploader.new(folder, serializer).run
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def disconnect
|
98
|
-
client.disconnect if @client
|
99
|
-
reset
|
100
|
-
end
|
101
|
-
|
102
|
-
def reconnect
|
103
|
-
disconnect
|
104
|
-
end
|
105
|
-
|
106
|
-
def reset
|
107
|
-
@backup_folders = nil
|
108
|
-
@client = nil
|
109
|
-
@folder_names = nil
|
110
|
-
end
|
111
|
-
|
112
|
-
# TODO: make this private
|
113
|
-
def client
|
114
|
-
@client ||= Account::Connection::ClientFactory.new(account: account).run
|
115
|
-
end
|
116
|
-
|
117
|
-
private
|
118
|
-
|
119
|
-
def each_folder
|
120
|
-
backup_folders.each do |folder|
|
121
|
-
serializer = Serializer.new(account.local_path, folder.name)
|
122
|
-
yield folder, serializer
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def ensure_account_folder
|
127
|
-
raise "The backup path for #{account.username} is not set" if !account.local_path
|
128
|
-
|
129
|
-
Utils.make_folder(
|
130
|
-
File.dirname(account.local_path),
|
131
|
-
File.basename(account.local_path),
|
132
|
-
Serializer::Directory::DIRECTORY_PERMISSIONS
|
133
|
-
)
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
data/lib/imap/backup/utils.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require "fileutils"
|
2
|
-
|
3
|
-
module Imap::Backup
|
4
|
-
module Utils
|
5
|
-
def self.check_permissions(filename, limit)
|
6
|
-
actual = mode(filename)
|
7
|
-
return nil if actual.nil?
|
8
|
-
|
9
|
-
mask = ~limit & 0o777
|
10
|
-
return if (actual & mask).zero?
|
11
|
-
|
12
|
-
message = format(
|
13
|
-
"Permissions on '%<filename>s' " \
|
14
|
-
"should be 0%<limit>o, not 0%<actual>o",
|
15
|
-
filename: filename, limit: limit, actual: actual
|
16
|
-
)
|
17
|
-
raise message
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.mode(filename)
|
21
|
-
return nil if !File.exist?(filename)
|
22
|
-
|
23
|
-
stat = File.stat(filename)
|
24
|
-
stat.mode & 0o777
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.make_folder(base_path, path, permissions)
|
28
|
-
parts = path.split("/")
|
29
|
-
return if parts.empty?
|
30
|
-
|
31
|
-
full_path = File.join(base_path, path)
|
32
|
-
FileUtils.mkdir_p full_path
|
33
|
-
path = base_path
|
34
|
-
parts.each do |part|
|
35
|
-
path = File.join(path, part)
|
36
|
-
FileUtils.chmod permissions, path
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|