imap-backup 9.3.2 → 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/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 +0 -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 +1 -1
- 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 +12 -7
- 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
@@ -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
|