imap-backup 9.4.0.pre1 → 10.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|