imap-backup 5.2.0 → 6.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -2
- data/docs/development.md +10 -4
- data/imap-backup.gemspec +5 -1
- data/lib/cli_coverage.rb +11 -11
- data/lib/email/provider/base.rb +2 -0
- data/lib/email/provider/unknown.rb +2 -0
- data/lib/email/provider.rb +2 -0
- data/lib/imap/backup/account/connection/backup_folders.rb +27 -0
- data/lib/imap/backup/account/connection/client_factory.rb +54 -0
- data/lib/imap/backup/account/connection/folder_names.rb +26 -0
- data/lib/imap/backup/account/connection.rb +17 -105
- data/lib/imap/backup/account/folder.rb +9 -6
- data/lib/imap/backup/account.rb +36 -16
- data/lib/imap/backup/cli/backup.rb +1 -3
- data/lib/imap/backup/cli/folders.rb +3 -3
- data/lib/imap/backup/cli/helpers.rb +24 -22
- data/lib/imap/backup/cli/local.rb +20 -13
- data/lib/imap/backup/cli/migrate.rb +5 -11
- data/lib/imap/backup/cli/restore.rb +8 -7
- data/lib/imap/backup/cli/setup.rb +10 -8
- data/lib/imap/backup/cli/stats.rb +78 -0
- data/lib/imap/backup/cli/status.rb +2 -2
- data/lib/imap/backup/cli/utils.rb +6 -8
- data/lib/imap/backup/cli.rb +24 -3
- data/lib/imap/backup/configuration.rb +9 -21
- data/lib/imap/backup/downloader.rb +56 -34
- data/lib/imap/backup/migrator.rb +5 -5
- data/lib/imap/backup/sanitizer.rb +3 -2
- data/lib/imap/backup/serializer/appender.rb +49 -0
- data/lib/imap/backup/serializer/directory.rb +37 -0
- data/lib/imap/backup/serializer/imap.rb +144 -0
- data/lib/imap/backup/serializer/mbox.rb +33 -88
- data/lib/imap/backup/serializer/mbox_enumerator.rb +2 -0
- data/lib/imap/backup/serializer/message_enumerator.rb +29 -0
- data/lib/imap/backup/serializer/unused_name_finder.rb +25 -0
- data/lib/imap/backup/serializer.rb +160 -3
- data/lib/imap/backup/setup/account/header.rb +75 -0
- data/lib/imap/backup/setup/account.rb +41 -95
- data/lib/imap/backup/setup/asker.rb +4 -15
- data/lib/imap/backup/setup/backup_path.rb +41 -0
- data/lib/imap/backup/setup/email.rb +45 -0
- data/lib/imap/backup/setup/folder_chooser.rb +3 -3
- data/lib/imap/backup/setup/helpers.rb +2 -2
- data/lib/imap/backup/setup.rb +5 -4
- data/lib/imap/backup/thunderbird/mailbox_exporter.rb +41 -22
- data/lib/imap/backup/uploader.rb +46 -8
- data/lib/imap/backup/utils.rb +1 -1
- data/lib/imap/backup/version.rb +3 -3
- data/lib/imap/backup.rb +0 -2
- metadata +31 -105
- data/lib/imap/backup/serializer/mbox_store.rb +0 -217
- data/spec/features/backup_spec.rb +0 -108
- data/spec/features/configuration/minimal_configuration.rb +0 -15
- data/spec/features/configuration/missing_configuration.rb +0 -14
- data/spec/features/folders_spec.rb +0 -36
- data/spec/features/helper.rb +0 -2
- data/spec/features/local/list_accounts_spec.rb +0 -12
- data/spec/features/local/list_emails_spec.rb +0 -21
- data/spec/features/local/list_folders_spec.rb +0 -21
- data/spec/features/local/show_an_email_spec.rb +0 -34
- data/spec/features/migrate_spec.rb +0 -35
- data/spec/features/remote/list_account_folders_spec.rb +0 -16
- data/spec/features/restore_spec.rb +0 -162
- data/spec/features/status_spec.rb +0 -43
- data/spec/features/support/aruba.rb +0 -77
- data/spec/features/support/backup_directory.rb +0 -43
- data/spec/features/support/email_server.rb +0 -110
- data/spec/features/support/shared/connection_context.rb +0 -14
- data/spec/features/support/shared/message_fixtures.rb +0 -16
- data/spec/fixtures/connection.yml +0 -7
- data/spec/spec_helper.rb +0 -15
- data/spec/support/fixtures.rb +0 -11
- data/spec/support/higline_test_helpers.rb +0 -8
- data/spec/support/silence_logging.rb +0 -7
- data/spec/unit/email/mboxrd/message_spec.rb +0 -177
- data/spec/unit/email/provider/apple_mail_spec.rb +0 -7
- data/spec/unit/email/provider/base_spec.rb +0 -11
- data/spec/unit/email/provider/fastmail_spec.rb +0 -7
- data/spec/unit/email/provider/gmail_spec.rb +0 -7
- data/spec/unit/email/provider_spec.rb +0 -27
- data/spec/unit/imap/backup/account/connection_spec.rb +0 -405
- data/spec/unit/imap/backup/account/folder_spec.rb +0 -251
- data/spec/unit/imap/backup/cli/accounts_spec.rb +0 -47
- data/spec/unit/imap/backup/cli/helpers_spec.rb +0 -87
- data/spec/unit/imap/backup/cli/local_spec.rb +0 -81
- data/spec/unit/imap/backup/cli/utils_spec.rb +0 -62
- data/spec/unit/imap/backup/client/default_spec.rb +0 -22
- data/spec/unit/imap/backup/configuration_spec.rb +0 -238
- data/spec/unit/imap/backup/downloader_spec.rb +0 -44
- data/spec/unit/imap/backup/logger_spec.rb +0 -48
- data/spec/unit/imap/backup/migrator_spec.rb +0 -58
- data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +0 -45
- data/spec/unit/imap/backup/serializer/mbox_spec.rb +0 -222
- data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +0 -329
- data/spec/unit/imap/backup/setup/account_spec.rb +0 -366
- data/spec/unit/imap/backup/setup/asker_spec.rb +0 -137
- data/spec/unit/imap/backup/setup/connection_tester_spec.rb +0 -51
- data/spec/unit/imap/backup/setup/folder_chooser_spec.rb +0 -146
- data/spec/unit/imap/backup/setup_spec.rb +0 -301
- data/spec/unit/imap/backup/uploader_spec.rb +0 -54
- data/spec/unit/imap/backup/utils_spec.rb +0 -92
@@ -1,11 +1,19 @@
|
|
1
|
-
require "imap/backup/setup/
|
1
|
+
require "imap/backup/setup/account/header"
|
2
|
+
require "imap/backup/setup/backup_path"
|
3
|
+
require "imap/backup/setup/email"
|
2
4
|
|
3
5
|
module Imap::Backup
|
4
6
|
class Setup; end
|
5
7
|
|
6
|
-
Setup::Account
|
8
|
+
class Setup::Account
|
9
|
+
attr_reader :account
|
10
|
+
attr_reader :config
|
11
|
+
attr_reader :highline
|
12
|
+
|
7
13
|
def initialize(config, account, highline)
|
8
|
-
|
14
|
+
@account = account
|
15
|
+
@config = config
|
16
|
+
@highline = highline
|
9
17
|
end
|
10
18
|
|
11
19
|
def run
|
@@ -26,6 +34,7 @@ module Imap::Backup
|
|
26
34
|
modify_password menu
|
27
35
|
modify_backup_path menu
|
28
36
|
choose_folders menu
|
37
|
+
modify_multi_fetch_size menu
|
29
38
|
modify_server menu
|
30
39
|
modify_connection_options menu
|
31
40
|
test_connection menu
|
@@ -36,47 +45,12 @@ module Imap::Backup
|
|
36
45
|
end
|
37
46
|
|
38
47
|
def header(menu)
|
39
|
-
|
40
|
-
connection_options =
|
41
|
-
if account.connection_options
|
42
|
-
escaped =
|
43
|
-
JSON.generate(account.connection_options).
|
44
|
-
gsub('"', '\"')
|
45
|
-
"\n connection options #{escaped}"
|
46
|
-
end
|
47
|
-
menu.header = <<~HEADER.chomp
|
48
|
-
#{helpers.title_prefix} Account#{modified}
|
49
|
-
|
50
|
-
email #{account.username}
|
51
|
-
password #{masked_password}
|
52
|
-
path #{account.local_path}
|
53
|
-
folders #{folders.map { |f| f[:name] }.join(', ')}
|
54
|
-
server #{account.server}#{connection_options}
|
55
|
-
|
56
|
-
Choose an action
|
57
|
-
HEADER
|
48
|
+
Setup::Account::Header.new(menu: menu, account: account).run
|
58
49
|
end
|
59
50
|
|
60
51
|
def modify_email(menu)
|
61
52
|
menu.choice("modify email") do
|
62
|
-
|
63
|
-
Kernel.puts "username: #{username}"
|
64
|
-
other_accounts = config.accounts.reject { |a| a == account }
|
65
|
-
others = other_accounts.map { |a| a.username }
|
66
|
-
Kernel.puts "others: #{others.inspect}"
|
67
|
-
if others.include?(username)
|
68
|
-
Kernel.puts(
|
69
|
-
"There is already an account set up with that email address"
|
70
|
-
)
|
71
|
-
else
|
72
|
-
account.username = username
|
73
|
-
# rubocop:disable Style/IfUnlessModifier
|
74
|
-
default = default_server(username)
|
75
|
-
if default && (account.server.nil? || (account.server == ""))
|
76
|
-
account.server = default
|
77
|
-
end
|
78
|
-
# rubocop:enable Style/IfUnlessModifier
|
79
|
-
end
|
53
|
+
Setup::Email.new(account: account, config: config).run
|
80
54
|
end
|
81
55
|
end
|
82
56
|
|
@@ -88,45 +62,44 @@ module Imap::Backup
|
|
88
62
|
end
|
89
63
|
end
|
90
64
|
|
91
|
-
def
|
92
|
-
menu.choice("modify
|
93
|
-
|
94
|
-
account.server = server if !server.nil?
|
65
|
+
def modify_backup_path(menu)
|
66
|
+
menu.choice("modify backup path") do
|
67
|
+
Setup::BackupPath.new(account: account, config: config).run
|
95
68
|
end
|
96
69
|
end
|
97
70
|
|
98
|
-
def
|
99
|
-
menu.choice("
|
100
|
-
|
101
|
-
account.connection_options = connection_options if !connection_options.nil?
|
71
|
+
def choose_folders(menu)
|
72
|
+
menu.choice("choose backup folders") do
|
73
|
+
Setup::FolderChooser.new(account).run
|
102
74
|
end
|
103
75
|
end
|
104
76
|
|
105
|
-
def
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
Kernel.puts "The path '#{path}' is used to backup " \
|
111
|
-
"the account '#{same.username}'"
|
112
|
-
false
|
113
|
-
else
|
114
|
-
true
|
77
|
+
def modify_multi_fetch_size(menu)
|
78
|
+
menu.choice("modify multi-fetch size (number of emails to fetch at a time)") do
|
79
|
+
size = highline.ask("size: ")
|
80
|
+
int = size.to_i
|
81
|
+
account.multi_fetch_size = int if int.positive?
|
115
82
|
end
|
116
83
|
end
|
117
84
|
|
118
|
-
def
|
119
|
-
menu.choice("modify
|
120
|
-
|
121
|
-
account.
|
122
|
-
account.local_path, ->(path) { path_modification_validator(path) }
|
123
|
-
)
|
85
|
+
def modify_server(menu)
|
86
|
+
menu.choice("modify server") do
|
87
|
+
server = highline.ask("server: ")
|
88
|
+
account.server = server if !server.nil?
|
124
89
|
end
|
125
90
|
end
|
126
91
|
|
127
|
-
def
|
128
|
-
menu.choice("
|
129
|
-
|
92
|
+
def modify_connection_options(menu)
|
93
|
+
menu.choice("modify connection options") do
|
94
|
+
connection_options = highline.ask("connections options (as JSON): ")
|
95
|
+
if !connection_options.nil?
|
96
|
+
begin
|
97
|
+
account.connection_options = connection_options
|
98
|
+
rescue JSON::ParserError
|
99
|
+
Kernel.puts "Malformed JSON, please try again"
|
100
|
+
highline.ask "Press a key "
|
101
|
+
end
|
102
|
+
end
|
130
103
|
end
|
131
104
|
end
|
132
105
|
|
@@ -141,37 +114,10 @@ module Imap::Backup
|
|
141
114
|
def delete_account(menu)
|
142
115
|
menu.choice("delete") do
|
143
116
|
if highline.agree("Are you sure? (y/n) ")
|
144
|
-
account.mark_for_deletion
|
117
|
+
account.mark_for_deletion
|
145
118
|
throw :done
|
146
119
|
end
|
147
120
|
end
|
148
121
|
end
|
149
|
-
|
150
|
-
def folders
|
151
|
-
account.folders || []
|
152
|
-
end
|
153
|
-
|
154
|
-
def masked_password
|
155
|
-
if (account.password == "") || account.password.nil?
|
156
|
-
"(unset)"
|
157
|
-
else
|
158
|
-
account.password.gsub(/./, "x")
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def default_server(username)
|
163
|
-
provider = Email::Provider.for_address(username)
|
164
|
-
|
165
|
-
if provider.is_a?(Email::Provider::Unknown)
|
166
|
-
Kernel.puts "Can't decide provider for email address '#{username}'"
|
167
|
-
return nil
|
168
|
-
end
|
169
|
-
|
170
|
-
provider.host
|
171
|
-
end
|
172
|
-
|
173
|
-
def helpers
|
174
|
-
Setup::Helpers.new
|
175
|
-
end
|
176
122
|
end
|
177
123
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
module Imap::Backup
|
2
2
|
class Setup; end
|
3
3
|
|
4
|
-
Setup::Asker
|
4
|
+
class Setup::Asker
|
5
5
|
EMAIL_MATCHER = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]+$/i.freeze
|
6
6
|
|
7
|
+
attr_reader :highline
|
8
|
+
|
7
9
|
def initialize(highline)
|
8
|
-
|
10
|
+
@highline = highline
|
9
11
|
end
|
10
12
|
|
11
13
|
def email(default = "")
|
@@ -30,15 +32,6 @@ module Imap::Backup
|
|
30
32
|
password
|
31
33
|
end
|
32
34
|
|
33
|
-
def backup_path(default, validator)
|
34
|
-
highline.ask("backup directory: ") do |q|
|
35
|
-
q.default = default
|
36
|
-
q.readline = true
|
37
|
-
q.validate = validator
|
38
|
-
q.responses[:not_valid] = "Choose a different directory "
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
35
|
def self.email(default = "")
|
43
36
|
new(Setup.highline).email(default)
|
44
37
|
end
|
@@ -46,9 +39,5 @@ module Imap::Backup
|
|
46
39
|
def self.password
|
47
40
|
new(Setup.highline).password
|
48
41
|
end
|
49
|
-
|
50
|
-
def self.backup_path(default, validator)
|
51
|
-
new(Setup.highline).backup_path(default, validator)
|
52
|
-
end
|
53
42
|
end
|
54
43
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Imap::Backup
|
2
|
+
class Setup; end
|
3
|
+
|
4
|
+
class Setup::BackupPath
|
5
|
+
attr_reader :account
|
6
|
+
attr_reader :config
|
7
|
+
|
8
|
+
def initialize(account:, config:)
|
9
|
+
@account = account
|
10
|
+
@config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
account.local_path = highline.ask("backup directory: ") do |q|
|
15
|
+
q.default = account.local_path
|
16
|
+
q.readline = true
|
17
|
+
q.validate = ->(path) { path_modification_validator(path) }
|
18
|
+
q.responses[:not_valid] = "Choose a different directory "
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def highline
|
25
|
+
Setup.highline
|
26
|
+
end
|
27
|
+
|
28
|
+
def path_modification_validator(path)
|
29
|
+
same = config.accounts.find do |a|
|
30
|
+
a.username != account.username && a.local_path == path
|
31
|
+
end
|
32
|
+
if same
|
33
|
+
Kernel.puts "The path '#{path}' is used to backup " \
|
34
|
+
"the account '#{same.username}'"
|
35
|
+
false
|
36
|
+
else
|
37
|
+
true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "email/provider"
|
2
|
+
|
3
|
+
module Imap::Backup
|
4
|
+
class Setup; end
|
5
|
+
|
6
|
+
class Setup::Email
|
7
|
+
attr_reader :account
|
8
|
+
attr_reader :config
|
9
|
+
|
10
|
+
def initialize(account:, config:)
|
11
|
+
@account = account
|
12
|
+
@config = config
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
username = Setup::Asker.email(account.username)
|
17
|
+
other_accounts = config.accounts.reject { |a| a == account }
|
18
|
+
others = other_accounts.map(&:username)
|
19
|
+
if others.include?(username)
|
20
|
+
Kernel.puts(
|
21
|
+
"There is already an account set up with that email address"
|
22
|
+
)
|
23
|
+
else
|
24
|
+
account.username = username
|
25
|
+
if account.server.nil? || (account.server == "")
|
26
|
+
default = default_server(username)
|
27
|
+
account.server = default if default
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def default_server(username)
|
35
|
+
provider = Email::Provider.for_address(username)
|
36
|
+
|
37
|
+
if provider.is_a?(Email::Provider::Unknown)
|
38
|
+
Kernel.puts "Can't decide provider for email address '#{username}'"
|
39
|
+
return nil
|
40
|
+
end
|
41
|
+
|
42
|
+
provider.host
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -12,13 +12,13 @@ module Imap::Backup
|
|
12
12
|
|
13
13
|
def run
|
14
14
|
if connection.nil?
|
15
|
-
|
15
|
+
Logger.logger.warn "Connection failed"
|
16
16
|
highline.ask "Press a key "
|
17
17
|
return
|
18
18
|
end
|
19
19
|
|
20
20
|
if imap_folders.nil?
|
21
|
-
|
21
|
+
Logger.logger.warn "Unable to get folder list"
|
22
22
|
highline.ask "Press a key "
|
23
23
|
return
|
24
24
|
end
|
@@ -90,7 +90,7 @@ module Imap::Backup
|
|
90
90
|
|
91
91
|
def toggle_selection(folder_name)
|
92
92
|
if selected?(folder_name)
|
93
|
-
new_list = account.folders.
|
93
|
+
new_list = account.folders.reject { |f| f[:name] == folder_name }
|
94
94
|
account.folders = new_list
|
95
95
|
else
|
96
96
|
existing = account.folders || []
|
data/lib/imap/backup/setup.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "highline"
|
2
2
|
|
3
|
+
require "email/provider"
|
3
4
|
require "imap/backup/account"
|
4
5
|
require "imap/backup/setup/helpers"
|
5
6
|
|
@@ -36,7 +37,7 @@ module Imap::Backup
|
|
36
37
|
config.save
|
37
38
|
throw :done
|
38
39
|
end
|
39
|
-
menu.choice("exit without saving changes")
|
40
|
+
menu.choice("exit without saving changes") { throw :done }
|
40
41
|
else
|
41
42
|
menu.choice("quit") { throw :done }
|
42
43
|
end
|
@@ -67,7 +68,7 @@ module Imap::Backup
|
|
67
68
|
new_setting = !config.debug?
|
68
69
|
menu.choice(menu_item) do
|
69
70
|
config.debug = new_setting
|
70
|
-
|
71
|
+
Logger.setup_logging(config)
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
@@ -76,13 +77,13 @@ module Imap::Backup
|
|
76
77
|
end
|
77
78
|
|
78
79
|
def default_account_config(username)
|
79
|
-
|
80
|
+
Imap::Backup::Account.new(
|
80
81
|
username: username,
|
81
82
|
password: "",
|
82
83
|
local_path: File.join(config.path, username.tr("@", "_")),
|
83
84
|
folders: []
|
84
85
|
).tap do |a|
|
85
|
-
server = Email::Provider.for_address(username)
|
86
|
+
server = ::Email::Provider.for_address(username)
|
86
87
|
a.server = server.host if server.host
|
87
88
|
end
|
88
89
|
end
|
@@ -19,30 +19,53 @@ module Imap::Backup
|
|
19
19
|
|
20
20
|
def run
|
21
21
|
local_folder_ok = local_folder.set_up
|
22
|
-
return if !local_folder_ok
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
22
|
+
return false if !local_folder_ok
|
23
|
+
|
24
|
+
skip_for_msf = check_msf
|
25
|
+
return false if skip_for_msf
|
26
|
+
|
27
|
+
skip_for_local_folder = check_local_folder
|
28
|
+
return false if skip_for_local_folder
|
29
|
+
|
30
|
+
copy_messages
|
31
|
+
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def check_local_folder
|
38
|
+
return false if !local_folder.exists?
|
39
|
+
|
40
|
+
if force
|
41
|
+
Kernel.puts "Overwriting '#{local_folder.path}' as --force option was supplied"
|
42
|
+
return false
|
32
43
|
end
|
33
44
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
45
|
+
Kernel.puts "Skipping export of '#{serializer.folder}' as '#{local_folder.path}' exists"
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def check_msf
|
50
|
+
return false if !local_folder.msf_exists?
|
51
|
+
|
52
|
+
if force
|
53
|
+
Kernel.puts "Deleting '#{local_folder.msf_path}' as --force option was supplied"
|
54
|
+
File.unlink local_folder.msf_path
|
55
|
+
return false
|
41
56
|
end
|
42
57
|
|
58
|
+
Kernel.puts(
|
59
|
+
"Skipping export of '#{serializer.folder}' " \
|
60
|
+
"as '#{local_folder.msf_path}' exists"
|
61
|
+
)
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
def copy_messages
|
43
66
|
File.open(local_folder.full_path, "w") do |f|
|
44
67
|
enumerator = Serializer::MboxEnumerator.new(serializer.mbox_pathname)
|
45
|
-
enumerator.each
|
68
|
+
enumerator.each do |raw|
|
46
69
|
clean = Email::Mboxrd::Message.clean_serialized(raw)
|
47
70
|
timestamp = Time.now.strftime("%a %b %d %H:%M:%S %Y")
|
48
71
|
thunderbird_fom_line = "From - #{timestamp}"
|
@@ -50,12 +73,8 @@ module Imap::Backup
|
|
50
73
|
f.write output
|
51
74
|
end
|
52
75
|
end
|
53
|
-
|
54
|
-
true
|
55
76
|
end
|
56
77
|
|
57
|
-
private
|
58
|
-
|
59
78
|
def local_folder
|
60
79
|
@local_folder ||= begin
|
61
80
|
top_level_folders = [EXPORT_PREFIX, email]
|
data/lib/imap/backup/uploader.rb
CHANGED
@@ -9,27 +9,65 @@ module Imap::Backup
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def run
|
12
|
-
|
12
|
+
if folder.uids.any?
|
13
|
+
rename_serialized_folder
|
14
|
+
else
|
15
|
+
folder.create
|
16
|
+
serializer.force_uid_validity(folder.uid_validity)
|
17
|
+
end
|
18
|
+
|
13
19
|
return if count.zero?
|
14
20
|
|
15
|
-
|
21
|
+
Logger.logger.debug "[#{folder.name}] #{count} to restore"
|
16
22
|
serializer.each_message(missing_uids).with_index do |(uid, message), i|
|
17
|
-
|
23
|
+
upload_message uid, message, i + 1
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def upload_message(uid, message, index)
|
30
|
+
return if message.nil?
|
18
31
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
32
|
+
log_prefix = "[#{folder.name}] uid: #{uid} (#{index}/#{count}) -"
|
33
|
+
Logger.logger.debug(
|
34
|
+
"#{log_prefix} #{message.supplied_body.size} bytes"
|
35
|
+
)
|
23
36
|
|
37
|
+
begin
|
24
38
|
new_uid = folder.append(message)
|
25
39
|
serializer.update_uid(uid, new_uid)
|
40
|
+
rescue StandardError => e
|
41
|
+
Logger.logger.warn "#{log_prefix} append error: #{e}"
|
26
42
|
end
|
27
43
|
end
|
28
44
|
|
29
|
-
|
45
|
+
def count
|
46
|
+
@count ||= missing_uids.count
|
47
|
+
end
|
30
48
|
|
31
49
|
def missing_uids
|
32
50
|
serializer.uids - folder.uids
|
33
51
|
end
|
52
|
+
|
53
|
+
def rename_serialized_folder
|
54
|
+
Logger.logger.debug(
|
55
|
+
"There's already a '#{folder.name}' folder with emails"
|
56
|
+
)
|
57
|
+
|
58
|
+
# Rename the local folder to a unique name
|
59
|
+
new_name = serializer.apply_uid_validity(folder.uid_validity)
|
60
|
+
|
61
|
+
return if !new_name
|
62
|
+
|
63
|
+
# Restore the renamed folder
|
64
|
+
Logger.logger.debug(
|
65
|
+
"Backup '#{serializer.folder}' renamed and restored to '#{new_name}'"
|
66
|
+
)
|
67
|
+
@folder = Account::Folder.new(folder.connection, new_name)
|
68
|
+
folder.create
|
69
|
+
@serializer = Serializer.new(serializer.path, new_name)
|
70
|
+
serializer.force_uid_validity(@folder.uid_validity)
|
71
|
+
end
|
34
72
|
end
|
35
73
|
end
|
data/lib/imap/backup/utils.rb
CHANGED
data/lib/imap/backup/version.rb
CHANGED
data/lib/imap/backup.rb
CHANGED
@@ -8,14 +8,12 @@ require "imap/backup/downloader"
|
|
8
8
|
require "imap/backup/logger"
|
9
9
|
require "imap/backup/uploader"
|
10
10
|
require "imap/backup/serializer"
|
11
|
-
require "imap/backup/serializer/mbox"
|
12
11
|
require "imap/backup/setup"
|
13
12
|
require "imap/backup/setup/account"
|
14
13
|
require "imap/backup/setup/asker"
|
15
14
|
require "imap/backup/setup/connection_tester"
|
16
15
|
require "imap/backup/setup/folder_chooser"
|
17
16
|
require "imap/backup/version"
|
18
|
-
require "email/provider"
|
19
17
|
|
20
18
|
module Imap::Backup
|
21
19
|
class ConfigurationNotFound < StandardError; end
|