imap-backup 14.4.4 → 14.4.5
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/README.md +67 -137
- data/docs/documentation.md +19 -0
- data/lib/imap/backup/account/backup.rb +2 -0
- data/lib/imap/backup/account/backup_folders.rb +7 -1
- data/lib/imap/backup/account/client_factory.rb +1 -0
- data/lib/imap/backup/account/folder.rb +26 -0
- data/lib/imap/backup/account/folder_backup.rb +4 -1
- data/lib/imap/backup/account/folder_ensurer.rb +3 -0
- data/lib/imap/backup/account/local_only_folder_deleter.rb +2 -0
- data/lib/imap/backup/account/restore.rb +2 -0
- data/lib/imap/backup/account/serialized_folders.rb +5 -1
- data/lib/imap/backup/account.rb +15 -11
- data/lib/imap/backup/cli/backup.rb +3 -0
- data/lib/imap/backup/cli/folder_enumerator.rb +6 -0
- data/lib/imap/backup/cli/helpers.rb +13 -0
- data/lib/imap/backup/cli/local/check.rb +3 -0
- data/lib/imap/backup/cli/local.rb +13 -0
- data/lib/imap/backup/cli/remote.rb +7 -0
- data/lib/imap/backup/cli/restore.rb +4 -0
- data/lib/imap/backup/cli/setup.rb +3 -0
- data/lib/imap/backup/cli/single/backup.rb +3 -0
- data/lib/imap/backup/cli/single.rb +4 -0
- data/lib/imap/backup/cli/stats.rb +3 -0
- data/lib/imap/backup/cli/transfer.rb +8 -0
- data/lib/imap/backup/cli/utils.rb +6 -0
- data/lib/imap/backup/cli.rb +8 -0
- data/lib/imap/backup/client/apple_mail.rb +2 -0
- data/lib/imap/backup/client/automatic_login_wrapper.rb +9 -1
- data/lib/imap/backup/client/default.rb +15 -4
- data/lib/imap/backup/configuration.rb +13 -0
- data/lib/imap/backup/configuration_not_found.rb +1 -0
- data/lib/imap/backup/downloader.rb +4 -0
- data/lib/imap/backup/email/mboxrd/message.rb +14 -0
- data/lib/imap/backup/email/provider/apple_mail.rb +2 -0
- data/lib/imap/backup/email/provider/base.rb +2 -0
- data/lib/imap/backup/email/provider/fastmail.rb +2 -0
- data/lib/imap/backup/email/provider/gmail.rb +2 -0
- data/lib/imap/backup/email/provider/purelymail.rb +2 -0
- data/lib/imap/backup/email/provider/unknown.rb +2 -6
- data/lib/imap/backup/email/provider.rb +5 -0
- data/lib/imap/backup/file_mode.rb +2 -0
- data/lib/imap/backup/flag_refresher.rb +4 -0
- data/lib/imap/backup/local_only_message_deleter.rb +2 -0
- data/lib/imap/backup/logger.rb +18 -0
- data/lib/imap/backup/migrator.rb +3 -0
- data/lib/imap/backup/mirror/map.rb +21 -0
- data/lib/imap/backup/mirror.rb +8 -0
- data/lib/imap/backup/naming.rb +10 -1
- data/lib/imap/backup/retry_on_error.rb +9 -0
- data/lib/imap/backup/serializer/appender.rb +9 -0
- data/lib/imap/backup/serializer/delayed_metadata_serializer.rb +4 -0
- data/lib/imap/backup/serializer/folder_maker.rb +1 -0
- data/lib/imap/backup/serializer/imap.rb +38 -2
- data/lib/imap/backup/serializer/integrity_checker.rb +1 -0
- data/lib/imap/backup/serializer/mbox.rb +26 -0
- data/lib/imap/backup/serializer/message.rb +13 -0
- data/lib/imap/backup/serializer/message_enumerator.rb +10 -2
- data/lib/imap/backup/serializer/permission_checker.rb +6 -0
- data/lib/imap/backup/serializer/transaction.rb +18 -0
- data/lib/imap/backup/serializer/unused_name_finder.rb +4 -0
- data/lib/imap/backup/serializer/version2_migrator.rb +4 -0
- data/lib/imap/backup/serializer.rb +56 -2
- data/lib/imap/backup/setup/account/header.rb +6 -0
- data/lib/imap/backup/setup/account.rb +6 -0
- data/lib/imap/backup/setup/asker.rb +16 -0
- data/lib/imap/backup/setup/backup_path.rb +6 -0
- data/lib/imap/backup/setup/connection_tester.rb +5 -0
- data/lib/imap/backup/setup/email_changer.rb +6 -0
- data/lib/imap/backup/setup/folder_chooser.rb +4 -0
- data/lib/imap/backup/setup/global_options/download_strategy_chooser.rb +4 -0
- data/lib/imap/backup/setup/global_options.rb +4 -0
- data/lib/imap/backup/setup/helpers.rb +3 -0
- data/lib/imap/backup/setup.rb +5 -0
- data/lib/imap/backup/text/sanitizer.rb +9 -0
- data/lib/imap/backup/thunderbird/mailbox_exporter.rb +7 -0
- data/lib/imap/backup/uploader.rb +5 -0
- data/lib/imap/backup/version.rb +6 -1
- metadata +3 -5
- data/docs/api.md +0 -20
- data/docs/development.md +0 -110
- data/docs/migrate-server-keep-address.md +0 -47
@@ -1,15 +1,23 @@
|
|
1
1
|
module Imap; end
|
2
2
|
|
3
3
|
module Imap::Backup
|
4
|
+
# Stores data during a transaction
|
4
5
|
class Serializer::Transaction
|
6
|
+
# @return the transaction's stored data
|
5
7
|
attr_reader :data
|
6
8
|
|
9
|
+
# @param owner [any] the class using the transaction -
|
10
|
+
# this is used when raising errors
|
7
11
|
def initialize(owner:)
|
8
12
|
@data = nil
|
9
13
|
@owner = owner
|
10
14
|
@in_transaction = false
|
11
15
|
end
|
12
16
|
|
17
|
+
# Runs the transaction
|
18
|
+
# @param data [any] the data to maintain during the transaction
|
19
|
+
# @param block [block] the block to wrap with the transaction
|
20
|
+
# @return [void]
|
13
21
|
def begin(data, &block)
|
14
22
|
@data = data
|
15
23
|
@in_transaction = true
|
@@ -17,6 +25,8 @@ module Imap::Backup
|
|
17
25
|
@in_transaction = false
|
18
26
|
end
|
19
27
|
|
28
|
+
# Clears rollback data
|
29
|
+
# @return [void]
|
20
30
|
def clear
|
21
31
|
@data = nil
|
22
32
|
end
|
@@ -25,10 +35,18 @@ module Imap::Backup
|
|
25
35
|
@in_transaction
|
26
36
|
end
|
27
37
|
|
38
|
+
# Throws an exception if there is a current transaction
|
39
|
+
# @param method [Symbol] the method where the check is run
|
40
|
+
# @raise [RuntimeError] if called from inside a transaction
|
41
|
+
# @return [void]
|
28
42
|
def fail_in_transaction!(method, message: "not supported inside trasactions")
|
29
43
|
raise "#{owner.class}##{method} #{message}" if in_transaction?
|
30
44
|
end
|
31
45
|
|
46
|
+
# Throws an exception if there is not a current transaction
|
47
|
+
# @param method [Symbol] the method where the check is run
|
48
|
+
# @raise [RuntimeError] if called from outside a transaction
|
49
|
+
# @return [void]
|
32
50
|
def fail_outside_transaction!(method)
|
33
51
|
raise "#{owner.class}##{method} can only be called inside a transaction" if !in_transaction?
|
34
52
|
end
|
@@ -3,11 +3,15 @@ require "imap/backup/serializer"
|
|
3
3
|
module Imap; end
|
4
4
|
|
5
5
|
module Imap::Backup
|
6
|
+
# Finds a name that can be used to rename a serialized folder
|
6
7
|
class Serializer::UnusedNameFinder
|
8
|
+
# @param serializer [Serializer] a folder serializer
|
7
9
|
def initialize(serializer:)
|
8
10
|
@serializer = serializer
|
9
11
|
end
|
10
12
|
|
13
|
+
# Finds the name
|
14
|
+
# @return [String] the name
|
11
15
|
def run
|
12
16
|
digit = 0
|
13
17
|
folder = nil
|
@@ -5,7 +5,9 @@ require "imap/backup/serializer/imap"
|
|
5
5
|
module Imap; end
|
6
6
|
|
7
7
|
module Imap::Backup
|
8
|
+
# Migrates serialized folder metadata from the version 2 format to the version 3 format
|
8
9
|
class Serializer::Version2Migrator
|
10
|
+
# @param folder_path [String] the base pathv(without extension) of the folder backup
|
9
11
|
def initialize(folder_path)
|
10
12
|
@folder_path = folder_path
|
11
13
|
end
|
@@ -21,6 +23,8 @@ module Imap::Backup
|
|
21
23
|
true
|
22
24
|
end
|
23
25
|
|
26
|
+
# Runs the migration
|
27
|
+
# @return [Boolean] whether the migration was run
|
24
28
|
def run
|
25
29
|
return false if !required?
|
26
30
|
|
@@ -15,7 +15,11 @@ require "imap/backup/serializer/unused_name_finder"
|
|
15
15
|
module Imap; end
|
16
16
|
|
17
17
|
module Imap::Backup
|
18
|
+
# Handles serialization for a folder
|
18
19
|
class Serializer
|
20
|
+
# @param path [String] an account's backup path
|
21
|
+
# @param folder [String] a folder name
|
22
|
+
# @return [String] the full path to a serialized folder (without file extensions)
|
19
23
|
def self.folder_path_for(path:, folder:)
|
20
24
|
relative = File.join(path, folder)
|
21
25
|
File.expand_path(relative)
|
@@ -26,9 +30,13 @@ module Imap::Backup
|
|
26
30
|
def_delegator :mbox, :pathname, :mbox_pathname
|
27
31
|
def_delegators :imap, :get, :messages, :uid_validity, :uids, :update_uid
|
28
32
|
|
33
|
+
# @return [String] a folder name
|
29
34
|
attr_reader :folder
|
35
|
+
# @return [String] an account's backup path
|
30
36
|
attr_reader :path
|
31
37
|
|
38
|
+
# @param path [String] an account's backup path
|
39
|
+
# @param folder [String] a folder name
|
32
40
|
def initialize(path, folder)
|
33
41
|
@path = path
|
34
42
|
@folder = folder
|
@@ -38,14 +46,17 @@ module Imap::Backup
|
|
38
46
|
# Calls the supplied block.
|
39
47
|
# This method is present so that this class implements the same
|
40
48
|
# interface as {DelayedMetadataSerializer}
|
49
|
+
# @param block [block] the block that is wrapped by the transaction
|
41
50
|
#
|
42
51
|
# @return [void]
|
43
52
|
def transaction(&block)
|
44
53
|
block.call
|
45
54
|
end
|
46
55
|
|
47
|
-
#
|
48
|
-
#
|
56
|
+
# Checks that the metadata files are valid, migrates the metadata file
|
57
|
+
# from older versions, if necessary,
|
58
|
+
# or deletes any existing files if the pair are not valid.
|
59
|
+
# @return [Boolean] indicates whether there are existing, valid files
|
49
60
|
def validate!
|
50
61
|
return true if @validated
|
51
62
|
|
@@ -61,16 +72,33 @@ module Imap::Backup
|
|
61
72
|
false
|
62
73
|
end
|
63
74
|
|
75
|
+
# Checks that the folder's data is stored correctly
|
76
|
+
# @return [void]
|
64
77
|
def check_integrity!
|
65
78
|
IntegrityChecker.new(imap: imap, mbox: mbox).run
|
66
79
|
end
|
67
80
|
|
81
|
+
# Deletes the serialized data
|
82
|
+
# @return [void]
|
68
83
|
def delete
|
69
84
|
imap.delete
|
70
85
|
mbox.delete
|
71
86
|
reload
|
72
87
|
end
|
73
88
|
|
89
|
+
# Sets the folder's UID validity.
|
90
|
+
# If the existing value is nil, it sets the new value
|
91
|
+
# and ensures that both the metadata file and the mailbox
|
92
|
+
# are saved.
|
93
|
+
# If the supplied value is the same as the existing value,
|
94
|
+
# it does nothing.
|
95
|
+
# If the supplied valued is *different* to the existing value,
|
96
|
+
# it renames the existing folder to a new name, and creates a
|
97
|
+
# new folder with the supplied value.
|
98
|
+
#
|
99
|
+
# @param value [Integer] The new UID validity value
|
100
|
+
#
|
101
|
+
# @return [String, nil] The name of the new folder
|
74
102
|
def apply_uid_validity(value)
|
75
103
|
validate!
|
76
104
|
|
@@ -86,12 +114,22 @@ module Imap::Backup
|
|
86
114
|
end
|
87
115
|
end
|
88
116
|
|
117
|
+
# Overwrites the UID validity of the folder
|
118
|
+
# and ensures that both the metadata file and the mailbox
|
119
|
+
# are saved.
|
120
|
+
# @param value [Integer] the new UID validity
|
121
|
+
# @return [void]
|
89
122
|
def force_uid_validity(value)
|
90
123
|
validate!
|
91
124
|
|
92
125
|
internal_force_uid_validity(value)
|
93
126
|
end
|
94
127
|
|
128
|
+
# Appends a message to the serialized data
|
129
|
+
# @param uid [Integer] the message's UID
|
130
|
+
# @param message [Integer] the message text
|
131
|
+
# @param flags [Array[Symbol]] the message's flags
|
132
|
+
# @return [void]
|
95
133
|
def append(uid, message, flags)
|
96
134
|
validate!
|
97
135
|
|
@@ -99,6 +137,10 @@ module Imap::Backup
|
|
99
137
|
appender.append(uid: uid, message: message, flags: flags)
|
100
138
|
end
|
101
139
|
|
140
|
+
# Updates a messages flags
|
141
|
+
# @param uid [Integer] the message's UID
|
142
|
+
# @param flags [Array<Symbol>] the flags to set on the message
|
143
|
+
# @return [void]
|
102
144
|
def update(uid, flags: nil)
|
103
145
|
message = imap.get(uid)
|
104
146
|
return if !message
|
@@ -107,6 +149,10 @@ module Imap::Backup
|
|
107
149
|
imap.save
|
108
150
|
end
|
109
151
|
|
152
|
+
# Enumerates over a series of messages.
|
153
|
+
# When called without a block, returns an Enumerator
|
154
|
+
# @param required_uids [Array<Integer>] the UIDs of the message to enumerate over
|
155
|
+
# @return [Enumerator, void]
|
110
156
|
def each_message(required_uids = nil, &block)
|
111
157
|
return enum_for(:each_message, required_uids) if !block
|
112
158
|
|
@@ -118,6 +164,10 @@ module Imap::Backup
|
|
118
164
|
enumerator.run(uids: required_uids, &block)
|
119
165
|
end
|
120
166
|
|
167
|
+
# Calls the supplied block on each message in the folder
|
168
|
+
# and discards those for which the block returns a false result
|
169
|
+
# @param block [block] the block to call
|
170
|
+
# @return [void]
|
121
171
|
def filter(&block)
|
122
172
|
temp_name = Serializer::UnusedNameFinder.new(serializer: self).run
|
123
173
|
temp_folder_path = self.class.folder_path_for(path: path, folder: temp_name)
|
@@ -137,14 +187,18 @@ module Imap::Backup
|
|
137
187
|
reload
|
138
188
|
end
|
139
189
|
|
190
|
+
# @return [String] the path to the serialized folder (without file extensions)
|
140
191
|
def folder_path
|
141
192
|
self.class.folder_path_for(path: path, folder: sanitized)
|
142
193
|
end
|
143
194
|
|
195
|
+
# @return [String] The folder's name adapted for using as a file name
|
144
196
|
def sanitized
|
145
197
|
@sanitized ||= Naming.to_local_path(folder)
|
146
198
|
end
|
147
199
|
|
200
|
+
# Forces a reload of the serialized files
|
201
|
+
# @return [void]
|
148
202
|
def reload
|
149
203
|
@imap = nil
|
150
204
|
@mbox = nil
|
@@ -8,12 +8,18 @@ module Imap::Backup
|
|
8
8
|
class Setup; end
|
9
9
|
class Setup::Account; end
|
10
10
|
|
11
|
+
# Displays the header to the account modification menu
|
11
12
|
class Setup::Account::Header
|
13
|
+
# @param menu [Highline::Menu] the menu
|
14
|
+
# @param account [Account] an Account
|
12
15
|
def initialize(menu:, account:)
|
13
16
|
@menu = menu
|
14
17
|
@account = account
|
15
18
|
end
|
16
19
|
|
20
|
+
# Displays the header
|
21
|
+
#
|
22
|
+
# @return [void]
|
17
23
|
def run
|
18
24
|
rows = [
|
19
25
|
email,
|
@@ -10,13 +10,19 @@ module Imap; end
|
|
10
10
|
module Imap::Backup
|
11
11
|
class Setup; end
|
12
12
|
|
13
|
+
# Handles interactive account setup
|
13
14
|
class Setup::Account
|
15
|
+
# @param config [Configuration] the application configuration
|
16
|
+
# @param account [Account] an Account
|
17
|
+
# @param highline [Higline] the configured Highline instance
|
14
18
|
def initialize(config, account, highline)
|
15
19
|
@account = account
|
16
20
|
@config = config
|
17
21
|
@highline = highline
|
18
22
|
end
|
19
23
|
|
24
|
+
# Shows the menu
|
25
|
+
# @return [void]
|
20
26
|
def run
|
21
27
|
if !account.local_path
|
22
28
|
account.local_path = File.join(config.path, account.username.tr("@", "_"))
|
@@ -3,11 +3,17 @@ module Imap; end
|
|
3
3
|
module Imap::Backup
|
4
4
|
class Setup; end
|
5
5
|
|
6
|
+
# Implements interactively requesting information from the user
|
6
7
|
class Setup::Asker
|
8
|
+
# @param highline [Higline] the configured Highline instance
|
7
9
|
def initialize(highline)
|
8
10
|
@highline = highline
|
9
11
|
end
|
10
12
|
|
13
|
+
# Asks for a email address
|
14
|
+
#
|
15
|
+
# @param default [String] the existing email address
|
16
|
+
# @return [String] the email address
|
11
17
|
def email(default = "")
|
12
18
|
highline.ask("email address: ") do |q|
|
13
19
|
q.default = default
|
@@ -16,6 +22,9 @@ module Imap::Backup
|
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
25
|
+
# Asks for a password
|
26
|
+
#
|
27
|
+
# @return [String] the password
|
19
28
|
def password
|
20
29
|
password = highline.ask("password: ") { |q| q.echo = false }
|
21
30
|
confirmation = highline.ask("repeat password: ") { |q| q.echo = false }
|
@@ -29,10 +38,17 @@ module Imap::Backup
|
|
29
38
|
password
|
30
39
|
end
|
31
40
|
|
41
|
+
# Asks for a email address using the configured menu handler
|
42
|
+
#
|
43
|
+
# @param default [String] the existing email address
|
44
|
+
# @return [String] the email address
|
32
45
|
def self.email(default = "")
|
33
46
|
new(Setup.highline).email(default)
|
34
47
|
end
|
35
48
|
|
49
|
+
# Asks for a password using the configured menu handler
|
50
|
+
#
|
51
|
+
# @return [String] the password
|
36
52
|
def self.password
|
37
53
|
new(Setup.highline).password
|
38
54
|
end
|
@@ -3,12 +3,18 @@ module Imap; end
|
|
3
3
|
module Imap::Backup
|
4
4
|
class Setup; end
|
5
5
|
|
6
|
+
# Requests an updated backup path from the user
|
6
7
|
class Setup::BackupPath
|
8
|
+
# @param account [Account] an Account
|
9
|
+
# @param config [Configuration] the application configuration
|
7
10
|
def initialize(account:, config:)
|
8
11
|
@account = account
|
9
12
|
@config = config
|
10
13
|
end
|
11
14
|
|
15
|
+
# Asks the user for a backup path
|
16
|
+
#
|
17
|
+
# @return [void]
|
12
18
|
def run
|
13
19
|
account.local_path = highline.ask("backup directory: ") do |q|
|
14
20
|
q.default = account.local_path
|
@@ -5,11 +5,16 @@ module Imap; end
|
|
5
5
|
module Imap::Backup
|
6
6
|
class Setup; end
|
7
7
|
|
8
|
+
# Attempts to login to an account and reports the result
|
8
9
|
class Setup::ConnectionTester
|
10
|
+
# @param account [Account] an Account
|
9
11
|
def initialize(account)
|
10
12
|
@account = account
|
11
13
|
end
|
12
14
|
|
15
|
+
# Carries out the attempted login and indicates
|
16
|
+
# whether it was successful
|
17
|
+
# @return [void]
|
13
18
|
def test
|
14
19
|
account.client.login
|
15
20
|
"Connection successful"
|
@@ -6,12 +6,18 @@ module Imap; end
|
|
6
6
|
module Imap::Backup
|
7
7
|
class Setup; end
|
8
8
|
|
9
|
+
# Asks the user for a new email address
|
9
10
|
class Setup::EmailChanger
|
11
|
+
# @param account [Account] an Account
|
12
|
+
# @param config [Configuration] the application configuration
|
10
13
|
def initialize(account:, config:)
|
11
14
|
@account = account
|
12
15
|
@config = config
|
13
16
|
end
|
14
17
|
|
18
|
+
# Asks the user for an email address,
|
19
|
+
# ensuring that the supplied address is not an existing account
|
20
|
+
# @return [void]
|
15
21
|
def run
|
16
22
|
username = Setup::Asker.email(account.username)
|
17
23
|
other_accounts = config.accounts.reject { |a| a == account }
|
@@ -5,11 +5,15 @@ module Imap; end
|
|
5
5
|
module Imap::Backup
|
6
6
|
class Setup; end
|
7
7
|
|
8
|
+
# Allows the user to select and deselect folders to be backed up
|
8
9
|
class Setup::FolderChooser
|
10
|
+
# @param account [Account] an Account
|
9
11
|
def initialize(account)
|
10
12
|
@account = account
|
11
13
|
end
|
12
14
|
|
15
|
+
# Lists account folders and allows the user to toggle whther they are selected
|
16
|
+
# @return [void]
|
13
17
|
def run
|
14
18
|
if client.nil?
|
15
19
|
highline.ask "Press a key "
|
@@ -5,11 +5,15 @@ module Imap::Backup; end
|
|
5
5
|
class Imap::Backup::Setup; end
|
6
6
|
|
7
7
|
class Imap::Backup::Setup::GlobalOptions
|
8
|
+
# Allows changing the globally configured download strategy
|
8
9
|
class DownloadStrategyChooser
|
10
|
+
# @param config [Configuration] the application configuration
|
9
11
|
def initialize(config:)
|
10
12
|
@config = config
|
11
13
|
end
|
12
14
|
|
15
|
+
# Shows the menu
|
16
|
+
# @return [void]
|
13
17
|
def run
|
14
18
|
catch :done do
|
15
19
|
loop do
|
@@ -6,11 +6,15 @@ module Imap; end
|
|
6
6
|
module Imap::Backup
|
7
7
|
class Setup; end
|
8
8
|
|
9
|
+
# Shows the menu of global options
|
9
10
|
class Setup::GlobalOptions
|
11
|
+
# @param config [Configuration] the application configuration
|
10
12
|
def initialize(config:)
|
11
13
|
@config = config
|
12
14
|
end
|
13
15
|
|
16
|
+
# Shows the menu
|
17
|
+
# @return [void]
|
14
18
|
def run
|
15
19
|
catch :done do
|
16
20
|
loop do
|
@@ -5,11 +5,14 @@ module Imap; end
|
|
5
5
|
module Imap::Backup
|
6
6
|
class Setup; end
|
7
7
|
|
8
|
+
# Helpers for the setup system
|
8
9
|
class Setup::Helpers
|
10
|
+
# @return [String] the prefix for setup menus
|
9
11
|
def title_prefix
|
10
12
|
"imap-backup -"
|
11
13
|
end
|
12
14
|
|
15
|
+
# @return [String] the current application version
|
13
16
|
def version
|
14
17
|
VERSION
|
15
18
|
end
|
data/lib/imap/backup/setup.rb
CHANGED
@@ -10,16 +10,21 @@ require "imap/backup/setup/helpers"
|
|
10
10
|
module Imap; end
|
11
11
|
|
12
12
|
module Imap::Backup
|
13
|
+
# Interactively updates the application's configuration file
|
13
14
|
class Setup
|
14
15
|
class << self
|
16
|
+
# @return [Highline]
|
15
17
|
attr_accessor :highline
|
16
18
|
end
|
17
19
|
self.highline = HighLine.new
|
18
20
|
|
21
|
+
# @param config [Configuration] the application configuration
|
19
22
|
def initialize(config:)
|
20
23
|
@config = config
|
21
24
|
end
|
22
25
|
|
26
|
+
# Shows the menu
|
27
|
+
# @return [void]
|
23
28
|
def run
|
24
29
|
catch :done do
|
25
30
|
loop do
|
@@ -5,17 +5,24 @@ module Imap; end
|
|
5
5
|
module Imap::Backup
|
6
6
|
module Text; end
|
7
7
|
|
8
|
+
# Wraps standard output and hides passwords from debug output
|
9
|
+
# Any text matching Net::IMAP debug output of passwords is sanitized
|
8
10
|
class Text::Sanitizer
|
9
11
|
extend Forwardable
|
10
12
|
|
11
13
|
delegate puts: :output
|
12
14
|
delegate write: :output
|
13
15
|
|
16
|
+
# @param output [IO] the stream to write output to
|
14
17
|
def initialize(output)
|
15
18
|
@output = output
|
16
19
|
@current = ""
|
17
20
|
end
|
18
21
|
|
22
|
+
# Outputs everything up to the last newline character,
|
23
|
+
# storing whatever follows the newline.
|
24
|
+
# @param args [Array<String>] lines of text
|
25
|
+
# @return [void]
|
19
26
|
def print(*args)
|
20
27
|
@current << args.join
|
21
28
|
loop do
|
@@ -28,6 +35,8 @@ module Imap::Backup
|
|
28
35
|
end
|
29
36
|
end
|
30
37
|
|
38
|
+
# Outputs any text still not printed
|
39
|
+
# @return [void]
|
31
40
|
def flush
|
32
41
|
return if @current == ""
|
33
42
|
|
@@ -7,7 +7,11 @@ module Imap; end
|
|
7
7
|
module Imap::Backup
|
8
8
|
class Thunderbird; end
|
9
9
|
|
10
|
+
# Exports an account's emails to Thunderbird
|
10
11
|
class Thunderbird::MailboxExporter
|
12
|
+
# @param email [String] an email address
|
13
|
+
# @param serializer [Serializer] a local folder backup
|
14
|
+
# @param profile [Thunderbird::Profile] an existing Thunderbird profile
|
11
15
|
def initialize(email, serializer, profile, force: false)
|
12
16
|
@email = email
|
13
17
|
@serializer = serializer
|
@@ -15,6 +19,9 @@ module Imap::Backup
|
|
15
19
|
@force = force
|
16
20
|
end
|
17
21
|
|
22
|
+
# Copies the account's messages to the Thunderbird directory
|
23
|
+
# in the format expected by Thunderbird
|
24
|
+
# @return [void]
|
18
25
|
def run
|
19
26
|
if !profile_set_up
|
20
27
|
error "The Thunderbird profile '#{profile.title}' " \
|
data/lib/imap/backup/uploader.rb
CHANGED
@@ -5,12 +5,17 @@ require "imap/backup/serializer"
|
|
5
5
|
module Imap; end
|
6
6
|
|
7
7
|
module Imap::Backup
|
8
|
+
# Uploads a backed-up folder
|
8
9
|
class Uploader
|
10
|
+
# @param folder [Account::Folder] an online folder
|
11
|
+
# @param serializer [Serializer] a local folder backup
|
9
12
|
def initialize(folder, serializer)
|
10
13
|
@folder = folder
|
11
14
|
@serializer = serializer
|
12
15
|
end
|
13
16
|
|
17
|
+
# Uploads messages that are present in the backup, but not in the online folder
|
18
|
+
# @return [void]
|
14
19
|
def run
|
15
20
|
if folder.uids.any?
|
16
21
|
rename_serialized_folder
|
data/lib/imap/backup/version.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
module Imap; end
|
2
2
|
|
3
3
|
module Imap::Backup
|
4
|
+
# @private
|
4
5
|
MAJOR = 14
|
6
|
+
# @private
|
5
7
|
MINOR = 4
|
6
|
-
|
8
|
+
# @private
|
9
|
+
REVISION = 5
|
10
|
+
# @private
|
7
11
|
PRE = nil
|
12
|
+
# The application version
|
8
13
|
VERSION = [MAJOR, MINOR, REVISION, PRE].compact.map(&:to_s).join(".")
|
9
14
|
end
|
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: 14.4.
|
4
|
+
version: 14.4.5
|
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-
|
11
|
+
date: 2023-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -133,10 +133,8 @@ files:
|
|
133
133
|
- LICENSE
|
134
134
|
- README.md
|
135
135
|
- bin/imap-backup
|
136
|
-
- docs/api.md
|
137
136
|
- docs/delimiters-and-prefixes.md
|
138
|
-
- docs/
|
139
|
-
- docs/migrate-server-keep-address.md
|
137
|
+
- docs/documentation.md
|
140
138
|
- docs/performance.md
|
141
139
|
- imap-backup.gemspec
|
142
140
|
- lib/imap/backup/account.rb
|
data/docs/api.md
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# @title Index
|
2
|
-
# imap-backup API Documentation
|
3
|
-
|
4
|
-

|
5
|
-
[][CI Status]
|
6
|
-

|
7
|
-

|
8
|
-
[][GitHub Stars]
|
9
|
-
|
10
|
-
[CI Status]: https://github.com/joeyates/imap-backup/actions/workflows/main.yml
|
11
|
-
[GitHub Stars]: https://github.com/joeyates/imap-backup/stargazers "GitHub Stars"
|
12
|
-
|
13
|
-
This is the developer documentation for imap-backup's **code**.
|
14
|
-
|
15
|
-
Usage documentation is on [GitHub](https://github.com/joeyates/imap-backup).
|
16
|
-
|
17
|
-
You can get an overview of the program's structure from the
|
18
|
-
{file:ARCHITECTURE.md ARCHITECTURE} file.
|
19
|
-
|
20
|
-
The {file:CHANGELOG.md CHANGELOG} has a history of the changes to the program.
|