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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a244374a14bae1b8d9bee48293eb744266d4d9fa67be560a3ca52a25b49a0cfa
|
4
|
+
data.tar.gz: 03fc3fe13037bcc3c9927117a5fb9edd4a85e053ea3d8e8f2380d8daee514c9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc751d9d7f9af7f483536251234b5b40ffa9813d947d0739229ab14bf3d35d8878af6656d2180a490ad21b06d5b99c746547a95b75b6925c968fca51b91ba917
|
7
|
+
data.tar.gz: 8f4944c21e5458dda098554b3338c5baaecfe2e111fc5acc23ca0bcf1a20794202a80d0139a9932bba28960702ed8531881ea5bc7030af1b04a2e98afdc6dd22
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "imap/backup/account/folder_ensurer"
|
2
|
+
require "imap/backup/account/local_only_folder_deleter"
|
3
|
+
require "imap/backup/account/serialized_folders"
|
4
|
+
require "imap/backup/downloader"
|
5
|
+
require "imap/backup/flag_refresher"
|
6
|
+
require "imap/backup/local_only_message_deleter"
|
7
|
+
|
8
|
+
module Imap::Backup
|
9
|
+
class Account; end
|
10
|
+
|
11
|
+
class Account::Backup
|
12
|
+
attr_reader :account
|
13
|
+
attr_reader :refresh
|
14
|
+
|
15
|
+
def initialize(account:, refresh: false)
|
16
|
+
@account = account
|
17
|
+
@refresh = refresh
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
Logger.logger.info "Running backup of account: #{account.username}"
|
22
|
+
# start the connection so we get logging messages in the right order
|
23
|
+
account.client
|
24
|
+
|
25
|
+
Account::FolderEnsurer.new(account: account).run
|
26
|
+
Account::LocalOnlyFolderDeleter.new(account: account).run if account.mirror_mode
|
27
|
+
each_folder do |folder, serializer|
|
28
|
+
begin
|
29
|
+
next if !folder.exist?
|
30
|
+
rescue Encoding::UndefinedConversionError
|
31
|
+
message = "Skipping backup for '#{folder.name}' " \
|
32
|
+
"as it is not UTF-7 encoded correctly"
|
33
|
+
Logger.logger.info message
|
34
|
+
next
|
35
|
+
end
|
36
|
+
|
37
|
+
Logger.logger.debug "[#{folder.name}] running backup"
|
38
|
+
serializer.apply_uid_validity(folder.uid_validity)
|
39
|
+
Downloader.new(
|
40
|
+
folder,
|
41
|
+
serializer,
|
42
|
+
multi_fetch_size: account.multi_fetch_size,
|
43
|
+
reset_seen_flags_after_fetch: account.reset_seen_flags_after_fetch
|
44
|
+
).run
|
45
|
+
if account.mirror_mode
|
46
|
+
Logger.logger.info "Mirror mode - Deleting messages only present locally"
|
47
|
+
LocalOnlyMessageDeleter.new(folder, serializer).run
|
48
|
+
end
|
49
|
+
FlagRefresher.new(folder, serializer).run if account.mirror_mode || refresh
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def each_folder
|
56
|
+
backup_folders = Account::BackupFolders.new(
|
57
|
+
client: account.client, account: account
|
58
|
+
)
|
59
|
+
backup_folders.each do |folder|
|
60
|
+
serializer = Serializer.new(account.local_path, folder.name)
|
61
|
+
yield folder, serializer
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -1,8 +1,7 @@
|
|
1
1
|
module Imap::Backup
|
2
2
|
class Account; end
|
3
|
-
class Account::Connection; end
|
4
3
|
|
5
|
-
class Account::
|
4
|
+
class Account::BackupFolders
|
6
5
|
attr_reader :account
|
7
6
|
attr_reader :client
|
8
7
|
|
@@ -11,8 +10,10 @@ module Imap::Backup
|
|
11
10
|
@account = account
|
12
11
|
end
|
13
12
|
|
14
|
-
def
|
15
|
-
|
13
|
+
def each(&block)
|
14
|
+
return enum_for(:each) if !block
|
15
|
+
|
16
|
+
all_names = client.list
|
16
17
|
|
17
18
|
configured =
|
18
19
|
case
|
@@ -31,7 +32,13 @@ module Imap::Backup
|
|
31
32
|
all_names & configured
|
32
33
|
end
|
33
34
|
|
34
|
-
names.
|
35
|
+
names.each { |name| block.call(Account::Folder.new(client, name)) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def map(&block)
|
39
|
+
each.map do |folder|
|
40
|
+
block.call(folder)
|
41
|
+
end
|
35
42
|
end
|
36
43
|
end
|
37
44
|
end
|
@@ -1,11 +1,17 @@
|
|
1
|
+
require "socket"
|
2
|
+
|
1
3
|
require "email/provider"
|
4
|
+
require "imap/backup/client/apple_mail"
|
5
|
+
require "imap/backup/client/default"
|
2
6
|
require "retry_on_error"
|
3
7
|
|
4
8
|
module Imap::Backup
|
5
|
-
class Account
|
9
|
+
class Account; end
|
10
|
+
|
11
|
+
class Account::ClientFactory
|
6
12
|
include RetryOnError
|
7
13
|
|
8
|
-
LOGIN_RETRY_CLASSES = [EOFError, Errno::ECONNRESET, SocketError].freeze
|
14
|
+
LOGIN_RETRY_CLASSES = [::EOFError, ::Errno::ECONNRESET, ::SocketError].freeze
|
9
15
|
|
10
16
|
attr_reader :account
|
11
17
|
|
@@ -23,23 +29,17 @@ module Imap::Backup
|
|
23
29
|
)
|
24
30
|
client =
|
25
31
|
if provider.is_a?(Email::Provider::AppleMail)
|
26
|
-
Client::AppleMail.new(server, options)
|
32
|
+
Client::AppleMail.new(server, account, options)
|
27
33
|
else
|
28
|
-
Client::Default.new(server, options)
|
34
|
+
Client::Default.new(server, account, options)
|
29
35
|
end
|
30
|
-
|
31
|
-
client.login(account.username, account.password)
|
32
|
-
Logger.logger.debug "Login complete"
|
36
|
+
client.login
|
33
37
|
client
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
37
41
|
private
|
38
42
|
|
39
|
-
def masked_password
|
40
|
-
account.password.gsub(/./, "x")
|
41
|
-
end
|
42
|
-
|
43
43
|
def provider
|
44
44
|
@provider ||= Email::Provider.for_address(account.username)
|
45
45
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "forwardable"
|
2
|
+
require "net/imap"
|
2
3
|
|
3
4
|
require "retry_on_error"
|
4
5
|
|
@@ -12,28 +13,21 @@ module Imap::Backup
|
|
12
13
|
include RetryOnError
|
13
14
|
|
14
15
|
BODY_ATTRIBUTE = "BODY[]".freeze
|
15
|
-
UID_FETCH_RETRY_CLASSES = [EOFError, Errno::ECONNRESET, IOError].freeze
|
16
|
-
APPEND_RETRY_CLASSES = [Net::IMAP::BadResponseError].freeze
|
17
|
-
CREATE_RETRY_CLASSES = [Net::IMAP::BadResponseError].freeze
|
18
|
-
EXAMINE_RETRY_CLASSES = [Net::IMAP::BadResponseError].freeze
|
16
|
+
UID_FETCH_RETRY_CLASSES = [::EOFError, ::Errno::ECONNRESET, ::IOError].freeze
|
17
|
+
APPEND_RETRY_CLASSES = [::Net::IMAP::BadResponseError].freeze
|
18
|
+
CREATE_RETRY_CLASSES = [::Net::IMAP::BadResponseError].freeze
|
19
|
+
EXAMINE_RETRY_CLASSES = [::Net::IMAP::BadResponseError].freeze
|
19
20
|
PERMITTED_FLAGS = %i(Answered Draft Flagged Seen).freeze
|
20
21
|
|
21
|
-
attr_reader :
|
22
|
+
attr_reader :client
|
22
23
|
attr_reader :name
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
def initialize(connection, name)
|
27
|
-
@connection = connection
|
25
|
+
def initialize(client, name)
|
26
|
+
@client = client
|
28
27
|
@name = name
|
29
28
|
@uid_validity = nil
|
30
29
|
end
|
31
30
|
|
32
|
-
# Deprecated: use #name
|
33
|
-
def folder
|
34
|
-
name
|
35
|
-
end
|
36
|
-
|
37
31
|
def exist?
|
38
32
|
retry_on_error(errors: EXAMINE_RETRY_CLASSES) do
|
39
33
|
examine
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "imap/backup/serializer/directory"
|
2
|
+
require "imap/backup/serializer/folder_maker"
|
3
|
+
|
4
|
+
module Imap::Backup
|
5
|
+
class Account; end
|
6
|
+
|
7
|
+
class Account::FolderEnsurer
|
8
|
+
attr_reader :account
|
9
|
+
|
10
|
+
def initialize(account:)
|
11
|
+
@account = account
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
raise "The backup path for #{account.username} is not set" if !account.local_path
|
16
|
+
|
17
|
+
Serializer::FolderMaker.new(
|
18
|
+
base: File.dirname(account.local_path),
|
19
|
+
path: File.basename(account.local_path),
|
20
|
+
permissions: Serializer::Directory::DIRECTORY_PERMISSIONS
|
21
|
+
).run
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "imap/backup/account/backup_folders"
|
2
|
+
require "imap/backup/account/serialized_folders"
|
3
|
+
|
4
|
+
module Imap::Backup
|
5
|
+
class Account; end
|
6
|
+
|
7
|
+
# Deletes serialized folders that are not configured to be backed up
|
8
|
+
class Account::LocalOnlyFolderDeleter
|
9
|
+
attr_reader :account
|
10
|
+
|
11
|
+
def initialize(account:)
|
12
|
+
@account = account
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
backup_folders = Account::BackupFolders.new(
|
17
|
+
client: account.client, account: account
|
18
|
+
)
|
19
|
+
wanted = backup_folders.map(&:name)
|
20
|
+
serialized_folders = Account::SerializedFolders.new(account: account)
|
21
|
+
serialized_folders.each do |serializer, _folder|
|
22
|
+
serializer.delete if !wanted.include?(serializer.folder)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "imap/backup/account/serialized_folders"
|
2
|
+
|
3
|
+
module Imap::Backup
|
4
|
+
class Account; end
|
5
|
+
|
6
|
+
class Account::Restore
|
7
|
+
attr_reader :account
|
8
|
+
|
9
|
+
def initialize(account:)
|
10
|
+
@account = account
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
serialized_folders = Account::SerializedFolders.new(account: account)
|
15
|
+
serialized_folders.each do |serializer, folder|
|
16
|
+
Uploader.new(folder, serializer).run
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "imap/backup/account/folder_ensurer"
|
2
|
+
|
3
|
+
module Imap::Backup
|
4
|
+
class Account; end
|
5
|
+
|
6
|
+
class Account::SerializedFolders
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
attr_reader :account
|
10
|
+
|
11
|
+
def initialize(account:)
|
12
|
+
@account = account
|
13
|
+
end
|
14
|
+
|
15
|
+
def each(&block)
|
16
|
+
return enum_for(:each) if !block
|
17
|
+
|
18
|
+
glob.each do |path|
|
19
|
+
name = path.relative_path_from(base).to_s[0..-6]
|
20
|
+
serializer = Serializer.new(account.local_path, name)
|
21
|
+
folder = Account::Folder.new(account.client, name)
|
22
|
+
block.call(serializer, folder)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def base
|
29
|
+
@base ||= Pathname.new(account.local_path)
|
30
|
+
end
|
31
|
+
|
32
|
+
def glob
|
33
|
+
@glob ||= begin
|
34
|
+
Account::FolderEnsurer.new(account: account).run
|
35
|
+
|
36
|
+
pattern = File.join(account.local_path, "**", "*.imap")
|
37
|
+
Pathname.glob(pattern)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/imap/backup/account.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "imap/backup/account/client_factory"
|
2
|
+
require "imap/backup/account/restore"
|
3
|
+
|
1
4
|
module Imap; end
|
2
5
|
|
3
6
|
module Imap::Backup
|
@@ -26,13 +29,22 @@ module Imap::Backup
|
|
26
29
|
@connection_options = options[:connection_options]
|
27
30
|
@multi_fetch_size = options[:multi_fetch_size]
|
28
31
|
@reset_seen_flags_after_fetch = options[:reset_seen_flags_after_fetch]
|
29
|
-
@
|
32
|
+
@client = nil
|
30
33
|
@changes = {}
|
31
34
|
@marked_for_deletion = false
|
32
35
|
end
|
33
36
|
|
34
|
-
def
|
35
|
-
@
|
37
|
+
def client
|
38
|
+
@client ||= Account::ClientFactory.new(account: self).run
|
39
|
+
end
|
40
|
+
|
41
|
+
def namespaces
|
42
|
+
client.namespace
|
43
|
+
end
|
44
|
+
|
45
|
+
def restore
|
46
|
+
restore = Account::Restore.new(account: self)
|
47
|
+
restore.run
|
36
48
|
end
|
37
49
|
|
38
50
|
def valid?
|
@@ -145,7 +157,7 @@ module Imap::Backup
|
|
145
157
|
changes[field] = {from: current, to: value} if value != current
|
146
158
|
end
|
147
159
|
|
148
|
-
@
|
160
|
+
@client = nil
|
149
161
|
instance_variable_set(key, value)
|
150
162
|
end
|
151
163
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "imap/backup/account/backup"
|
2
|
+
|
1
3
|
module Imap::Backup
|
2
4
|
class CLI::Backup < Thor
|
3
5
|
include Thor::Actions
|
@@ -13,21 +15,18 @@ module Imap::Backup
|
|
13
15
|
no_commands do
|
14
16
|
def run
|
15
17
|
config = load_config(**options)
|
16
|
-
|
17
|
-
|
18
|
+
requested_accounts(config).each do |account|
|
19
|
+
backup = Account::Backup.new(account: account, refresh: refresh)
|
20
|
+
backup.run
|
18
21
|
rescue StandardError => e
|
19
22
|
message =
|
20
|
-
"Backup for account '#{
|
23
|
+
"Backup for account '#{account.username}' " \
|
21
24
|
"failed with error #{e}"
|
22
25
|
Logger.logger.warn message
|
23
26
|
next
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
27
|
-
def emails
|
28
|
-
(options[:accounts] || "").split(",")
|
29
|
-
end
|
30
|
-
|
31
30
|
def refresh
|
32
31
|
options.key?(:refresh) ? !!options[:refresh] : false
|
33
32
|
end
|
@@ -4,6 +4,15 @@ module Imap::Backup
|
|
4
4
|
module CLI::Helpers
|
5
5
|
def self.included(base)
|
6
6
|
base.class_eval do
|
7
|
+
def self.accounts_option
|
8
|
+
method_option(
|
9
|
+
"accounts",
|
10
|
+
type: :string,
|
11
|
+
desc: "a comma-separated list of accounts (defaults to all configured accounts)",
|
12
|
+
aliases: ["-a"]
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
7
16
|
def self.config_option
|
8
17
|
method_option(
|
9
18
|
"config",
|
@@ -78,22 +87,13 @@ module Imap::Backup
|
|
78
87
|
account
|
79
88
|
end
|
80
89
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
def each_connection(config, names)
|
88
|
-
return enum_for(:each_connection, config, names) if !block_given?
|
89
|
-
|
90
|
-
config.accounts.each do |account|
|
91
|
-
next if names.any? && !names.include?(account.username)
|
92
|
-
|
93
|
-
yield account.connection
|
90
|
+
def requested_accounts(config)
|
91
|
+
emails = (options[:accounts] || "").split(",")
|
92
|
+
if emails.any?
|
93
|
+
config.accounts.filter { |a| emails.include?(a.username) }
|
94
|
+
else
|
95
|
+
config.accounts
|
94
96
|
end
|
95
|
-
rescue ConfigurationNotFound
|
96
|
-
raise "imap-backup is not configured. Run `imap-backup setup`"
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
@@ -8,8 +8,9 @@ module Imap::Backup
|
|
8
8
|
desc "accounts", "List locally backed-up accounts"
|
9
9
|
config_option
|
10
10
|
format_option
|
11
|
+
quiet_option
|
12
|
+
verbose_option
|
11
13
|
def accounts
|
12
|
-
config = load_config(**options)
|
13
14
|
names = config.accounts.map(&:username)
|
14
15
|
case options[:format]
|
15
16
|
when "json"
|
@@ -29,13 +30,16 @@ module Imap::Backup
|
|
29
30
|
type: :boolean,
|
30
31
|
desc: "deletes any corrupted folders - USE WITH CAUTION!"
|
31
32
|
)
|
33
|
+
accounts_option
|
32
34
|
config_option
|
33
35
|
format_option
|
36
|
+
quiet_option
|
37
|
+
verbose_option
|
34
38
|
def check
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
results = requested_accounts(config).map do |account|
|
40
|
+
serialized_folders = Account::SerializedFolders.new(account: account)
|
41
|
+
folder_results = serialized_folders.map do |serializer, _folder|
|
42
|
+
puts "serializer: #{serializer.inspect}"
|
39
43
|
serializer.check_integrity!
|
40
44
|
{name: serializer.folder, result: "OK"}
|
41
45
|
rescue Serializer::FolderIntegrityError => e
|
@@ -50,7 +54,7 @@ module Imap::Backup
|
|
50
54
|
result: message
|
51
55
|
}
|
52
56
|
end
|
53
|
-
{account:
|
57
|
+
{account: account.username, folders: folder_results}
|
54
58
|
end
|
55
59
|
|
56
60
|
case options[:format]
|
@@ -64,17 +68,18 @@ module Imap::Backup
|
|
64
68
|
desc "folders EMAIL", "List backed up folders"
|
65
69
|
config_option
|
66
70
|
format_option
|
71
|
+
quiet_option
|
72
|
+
verbose_option
|
67
73
|
def folders(email)
|
68
|
-
|
69
|
-
connection = connection(config, email)
|
74
|
+
account = account(config, email)
|
70
75
|
|
71
|
-
|
76
|
+
serialized_folders = Account::SerializedFolders.new(account: account)
|
72
77
|
case options[:format]
|
73
78
|
when "json"
|
74
|
-
list =
|
79
|
+
list = serialized_folders.map { |_s, f| {name: f.name} }
|
75
80
|
Kernel.puts list.to_json
|
76
81
|
else
|
77
|
-
|
82
|
+
serialized_folders.each do |_s, f|
|
78
83
|
Kernel.puts %("#{f.name}")
|
79
84
|
end
|
80
85
|
end
|
@@ -83,11 +88,13 @@ module Imap::Backup
|
|
83
88
|
desc "list EMAIL FOLDER", "List emails in a folder"
|
84
89
|
config_option
|
85
90
|
format_option
|
91
|
+
quiet_option
|
92
|
+
verbose_option
|
86
93
|
def list(email, folder_name)
|
87
|
-
|
88
|
-
connection = connection(config, email)
|
94
|
+
account = account(config, email)
|
89
95
|
|
90
|
-
|
96
|
+
serialized_folders = Account::SerializedFolders.new(account: account)
|
97
|
+
serializer, _folder = serialized_folders.find do |_s, f|
|
91
98
|
f.name == folder_name
|
92
99
|
end
|
93
100
|
raise "Folder '#{folder_name}' not found" if !serializer
|
@@ -108,11 +115,13 @@ module Imap::Backup
|
|
108
115
|
DESC
|
109
116
|
config_option
|
110
117
|
format_option
|
118
|
+
quiet_option
|
119
|
+
verbose_option
|
111
120
|
def show(email, folder_name, uids)
|
112
|
-
|
113
|
-
connection = connection(config, email)
|
121
|
+
account = account(config, email)
|
114
122
|
|
115
|
-
|
123
|
+
serialized_folders = Account::SerializedFolders.new(account: account)
|
124
|
+
serializer, _folder = serialized_folders.find do |_s, f|
|
116
125
|
f.name == folder_name
|
117
126
|
end
|
118
127
|
raise "Folder '#{folder_name}' not found" if !serializer
|
@@ -197,8 +206,11 @@ module Imap::Backup
|
|
197
206
|
end
|
198
207
|
end
|
199
208
|
|
200
|
-
def
|
201
|
-
|
209
|
+
def config
|
210
|
+
@config ||= begin
|
211
|
+
non_logging_options = Logger.setup_logging(options)
|
212
|
+
load_config(**non_logging_options)
|
213
|
+
end
|
202
214
|
end
|
203
215
|
end
|
204
216
|
end
|
@@ -12,12 +12,12 @@ module Imap::Backup
|
|
12
12
|
verbose_option
|
13
13
|
def folders(email)
|
14
14
|
Imap::Backup::Logger.setup_logging options
|
15
|
-
|
15
|
+
folder_names = folder_names(email)
|
16
16
|
case options[:format]
|
17
17
|
when "json"
|
18
|
-
json_format_names
|
18
|
+
json_format_names folder_names
|
19
19
|
else
|
20
|
-
list_names
|
20
|
+
list_names folder_names
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -35,8 +35,8 @@ module Imap::Backup
|
|
35
35
|
def namespaces(email)
|
36
36
|
Imap::Backup::Logger.setup_logging options
|
37
37
|
config = load_config(**options)
|
38
|
-
|
39
|
-
namespaces =
|
38
|
+
account = account(config, email)
|
39
|
+
namespaces = account.namespaces
|
40
40
|
case options[:format]
|
41
41
|
when "json"
|
42
42
|
json_format_namespaces namespaces
|
@@ -46,11 +46,11 @@ module Imap::Backup
|
|
46
46
|
end
|
47
47
|
|
48
48
|
no_commands do
|
49
|
-
def
|
49
|
+
def folder_names(email)
|
50
50
|
config = load_config(**options)
|
51
|
-
|
51
|
+
account = account(config, email)
|
52
52
|
|
53
|
-
|
53
|
+
account.client.list
|
54
54
|
end
|
55
55
|
|
56
56
|
def json_format_names(names)
|
@@ -16,26 +16,22 @@ module Imap::Backup
|
|
16
16
|
def run
|
17
17
|
config = load_config(**options)
|
18
18
|
case
|
19
|
-
when email && !
|
20
|
-
|
21
|
-
|
22
|
-
when !email && !
|
19
|
+
when email && !options.key?(:accounts)
|
20
|
+
account = account(config, email)
|
21
|
+
account.restore
|
22
|
+
when !email && !options.key?(:accounts)
|
23
23
|
Logger.logger.info "Calling restore without an EMAIL parameter is deprecated"
|
24
|
-
|
25
|
-
when email &&
|
26
|
-
raise "
|
27
|
-
when
|
24
|
+
config.accounts.map(&:restore)
|
25
|
+
when email && options.key?(:accounts)
|
26
|
+
raise "Missing EMAIL parameter"
|
27
|
+
when !email && options.key?(:accounts)
|
28
28
|
Logger.logger.info(
|
29
29
|
"Calling restore with the --account option is deprected, " \
|
30
|
-
"please pass a single EMAIL
|
30
|
+
"please pass a single EMAIL parameter"
|
31
31
|
)
|
32
|
-
|
32
|
+
requested_accounts(config).each(&:restore)
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
36
|
-
def emails
|
37
|
-
@emails ||= options[:accounts].split(",") if options.key?(:accounts)
|
38
|
-
end
|
39
35
|
end
|
40
36
|
end
|
41
37
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "imap/backup/account/backup_folders"
|
2
|
+
|
1
3
|
module Imap::Backup
|
2
4
|
class CLI::Stats < Thor
|
3
5
|
include Thor::Actions
|
@@ -32,12 +34,15 @@ module Imap::Backup
|
|
32
34
|
|
33
35
|
def stats
|
34
36
|
config = load_config(**options)
|
35
|
-
|
37
|
+
account = account(config, email)
|
36
38
|
|
37
|
-
|
39
|
+
backup_folders = Account::BackupFolders.new(
|
40
|
+
client: account.client, account: account
|
41
|
+
)
|
42
|
+
backup_folders.map do |folder|
|
38
43
|
next if !folder.exist?
|
39
44
|
|
40
|
-
serializer = Serializer.new(
|
45
|
+
serializer = Serializer.new(account.local_path, folder.name)
|
41
46
|
local_uids = serializer.uids
|
42
47
|
remote_uids = folder.uids
|
43
48
|
{
|