imap-backup 4.0.7 → 4.1.1

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/bin/imap-backup +5 -2
  3. data/lib/imap/backup/account/connection.rb +53 -33
  4. data/lib/imap/backup/account/folder.rb +22 -2
  5. data/lib/imap/backup/account.rb +4 -0
  6. data/lib/imap/backup/cli/accounts.rb +43 -0
  7. data/lib/imap/backup/cli/folders.rb +3 -1
  8. data/lib/imap/backup/cli/helpers.rb +8 -9
  9. data/lib/imap/backup/cli/local.rb +4 -2
  10. data/lib/imap/backup/cli/setup.rb +1 -1
  11. data/lib/imap/backup/cli/utils.rb +3 -2
  12. data/lib/imap/backup/{configuration/store.rb → configuration.rb} +16 -3
  13. data/lib/imap/backup/downloader.rb +26 -12
  14. data/lib/imap/backup/logger.rb +42 -0
  15. data/lib/imap/backup/sanitizer.rb +42 -0
  16. data/lib/imap/backup/serializer/mbox_store.rb +2 -2
  17. data/lib/imap/backup/{configuration → setup}/account.rb +29 -19
  18. data/lib/imap/backup/{configuration → setup}/asker.rb +5 -5
  19. data/lib/imap/backup/setup/connection_tester.rb +26 -0
  20. data/lib/imap/backup/{configuration → setup}/folder_chooser.rb +18 -8
  21. data/lib/imap/backup/setup/helpers.rb +15 -0
  22. data/lib/imap/backup/{configuration/setup.rb → setup.rb} +23 -17
  23. data/lib/imap/backup/uploader.rb +2 -2
  24. data/lib/imap/backup/version.rb +2 -2
  25. data/lib/imap/backup.rb +7 -33
  26. data/lib/retry_on_error.rb +1 -1
  27. data/spec/features/backup_spec.rb +1 -0
  28. data/spec/features/support/email_server.rb +5 -2
  29. data/spec/support/higline_test_helpers.rb +1 -1
  30. data/spec/support/silence_logging.rb +1 -1
  31. data/spec/unit/imap/backup/account/connection_spec.rb +14 -9
  32. data/spec/unit/imap/backup/cli/accounts_spec.rb +47 -0
  33. data/spec/unit/imap/backup/cli/local_spec.rb +7 -3
  34. data/spec/unit/imap/backup/cli/utils_spec.rb +15 -5
  35. data/spec/unit/imap/backup/{configuration/store_spec.rb → configuration_spec.rb} +2 -2
  36. data/spec/unit/imap/backup/downloader_spec.rb +1 -1
  37. data/spec/unit/imap/backup/logger_spec.rb +48 -0
  38. data/spec/unit/imap/backup/{configuration → setup}/account_spec.rb +31 -24
  39. data/spec/unit/imap/backup/{configuration → setup}/asker_spec.rb +2 -2
  40. data/spec/unit/imap/backup/{configuration → setup}/connection_tester_spec.rb +10 -10
  41. data/spec/unit/imap/backup/{configuration → setup}/folder_chooser_spec.rb +8 -8
  42. data/spec/unit/imap/backup/{configuration/setup_spec.rb → setup_spec.rb} +48 -40
  43. metadata +49 -46
  44. data/lib/imap/backup/configuration/connection_tester.rb +0 -14
  45. data/lib/imap/backup/configuration/list.rb +0 -53
  46. data/spec/unit/imap/backup/configuration/list_spec.rb +0 -96
  47. data/spec/unit/imap/backup_spec.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5819f0b50ce3de10cfedb1cdb5381e51f2d94f00dc2bcdd99234f57855c9959d
4
- data.tar.gz: a140267c179d6002a7186f8591743abbfea2dca7697b7f1761feaa359fd1521c
3
+ metadata.gz: d6302ae17c5b96de2f99c6683c4a6403edbf80d2afc51cbe0f471918251cfaef
4
+ data.tar.gz: 349c0b68911a751e670176a91dfc98d4359a06a9cb8acae7c2cc5d5efa028f25
5
5
  SHA512:
6
- metadata.gz: 1b7d49f159df4d29582cf98f01ce105769301bcf94fd019486f1e0b43321eb90594e16861e24fe9d7993a76eeba0c115d6d991b64c1188020b09d04ea8db0714
7
- data.tar.gz: 7dacdd3c5c3835e1925cd36a3beaaf7cdf6bf98d4bf7f02bbdd4abe3635512708c03654c3da9dfbfcf35f4e94a46dd43a3fc9e6e4693dd2b943d34d4a9ec8b02
6
+ metadata.gz: 444432d3bf689fa12de1226cb84e9f8975a300f2c94cc2529254e1e3680fba6d7b0cfddfc3fff9001a866dd5d84d1afabc0e952e894ec5ae1a91557ea5538472
7
+ data.tar.gz: f4d156790a84308e08ee3d4348741e6d55b26f07fece75473a80f4fc0b7c0265c1bb62230cee178bf4c00941ff0de91a323ade1c0e0783a72a970c738c8823f0
data/bin/imap-backup CHANGED
@@ -2,7 +2,10 @@
2
2
 
3
3
  $LOAD_PATH.unshift(File.expand_path("../lib/", __dir__))
4
4
  require "imap/backup/cli"
5
+ require "imap/backup/logger"
5
6
 
6
- Imap::Backup::Configuration::List.new.setup_logging
7
+ Imap::Backup::Logger.setup_logging
7
8
 
8
- Imap::Backup::CLI.start(ARGV)
9
+ Imap::Backup::Logger.sanitize_stderr do
10
+ Imap::Backup::CLI.start(ARGV)
11
+ end
@@ -15,44 +15,63 @@ module Imap::Backup
15
15
 
16
16
  def initialize(account)
17
17
  @account = account
18
- @folders = nil
18
+ reset
19
19
  create_account_folder
20
20
  end
21
21
 
22
- def folders
23
- @folders ||=
22
+ # TODO: Make this private once the 'folders' command
23
+ # has been removed.
24
+ def folder_names
25
+ @folder_names ||=
24
26
  begin
25
- folders = client.list
27
+ folder_names = client.list
26
28
 
27
- if folders.empty?
29
+ if folder_names.empty?
28
30
  message = "Unable to get folder list for account #{account.username}"
29
- Imap::Backup.logger.info message
31
+ Imap::Backup::Logger.logger.info message
30
32
  raise message
31
33
  end
32
34
 
33
- folders
35
+ folder_names
36
+ end
37
+ end
38
+
39
+ def backup_folders
40
+ @backup_folders ||=
41
+ begin
42
+ names =
43
+ if account.folders&.any?
44
+ account.folders.map { |af| af[:name] }
45
+ else
46
+ folder_names
47
+ end
48
+
49
+ names.map do |name|
50
+ Account::Folder.new(self, name)
51
+ end
34
52
  end
35
53
  end
36
54
 
37
55
  def status
38
- backup_folders.map do |backup_folder|
39
- f = Account::Folder.new(self, backup_folder[:name])
40
- s = Serializer::Mbox.new(account.local_path, backup_folder[:name])
41
- {name: backup_folder[:name], local: s.uids, remote: f.uids}
56
+ backup_folders.map do |folder|
57
+ s = Serializer::Mbox.new(account.local_path, folder.name)
58
+ {name: folder.name, local: s.uids, remote: folder.uids}
42
59
  end
43
60
  end
44
61
 
45
62
  def run_backup
46
- Imap::Backup.logger.debug "Running backup of account: #{account.username}"
63
+ Imap::Backup::Logger.logger.debug "Running backup of account: #{account.username}"
47
64
  # start the connection so we get logging messages in the right order
48
65
  client
49
66
  each_folder do |folder, serializer|
50
67
  next if !folder.exist?
51
68
 
52
- Imap::Backup.logger.debug "[#{folder.name}] running backup"
69
+ Imap::Backup::Logger.logger.debug "[#{folder.name}] running backup"
53
70
  serializer.apply_uid_validity(folder.uid_validity)
54
71
  begin
55
- Downloader.new(folder, serializer).run
72
+ Downloader.new(
73
+ folder, serializer, block_size: config.download_block_size
74
+ ).run
56
75
  rescue Net::IMAP::ByeResponseError
57
76
  reconnect
58
77
  retry
@@ -81,18 +100,27 @@ module Imap::Backup
81
100
 
82
101
  def disconnect
83
102
  client.disconnect if @client
103
+ reset
84
104
  end
85
105
 
86
106
  def reconnect
87
107
  disconnect
108
+ end
109
+
110
+ def reset
111
+ @backup_folders = nil
88
112
  @client = nil
113
+ @config = nil
114
+ @folder_names = nil
115
+ @provider = nil
116
+ @server = nil
89
117
  end
90
118
 
91
119
  def client
92
120
  @client ||=
93
121
  retry_on_error(errors: LOGIN_RETRY_CLASSES) do
94
122
  options = provider_options
95
- Imap::Backup.logger.debug(
123
+ Imap::Backup::Logger.logger.debug(
96
124
  "Creating IMAP instance: #{server}, options: #{options.inspect}"
97
125
  )
98
126
  client =
@@ -101,9 +129,9 @@ module Imap::Backup
101
129
  else
102
130
  Client::Default.new(server, options)
103
131
  end
104
- Imap::Backup.logger.debug "Logging in: #{account.username}/#{masked_password}"
132
+ Imap::Backup::Logger.logger.debug "Logging in: #{account.username}/#{masked_password}"
105
133
  client.login(account.username, account.password)
106
- Imap::Backup.logger.debug "Login complete"
134
+ Imap::Backup::Logger.logger.debug "Login complete"
107
135
  client
108
136
  end
109
137
  end
@@ -115,9 +143,8 @@ module Imap::Backup
115
143
  private
116
144
 
117
145
  def each_folder
118
- backup_folders.each do |backup_folder|
119
- folder = Account::Folder.new(self, backup_folder[:name])
120
- serializer = Serializer::Mbox.new(account.local_path, backup_folder[:name])
146
+ backup_folders.each do |folder|
147
+ serializer = Serializer::Mbox.new(account.local_path, folder.name)
121
148
  yield folder, serializer
122
149
  end
123
150
  end
@@ -125,13 +152,13 @@ module Imap::Backup
125
152
  def restore_folder(serializer, folder)
126
153
  existing_uids = folder.uids
127
154
  if existing_uids.any?
128
- Imap::Backup.logger.debug(
155
+ Imap::Backup::Logger.logger.debug(
129
156
  "There's already a '#{folder.name}' folder with emails"
130
157
  )
131
158
  new_name = serializer.apply_uid_validity(folder.uid_validity)
132
159
  old_name = serializer.folder
133
160
  if new_name
134
- Imap::Backup.logger.debug(
161
+ Imap::Backup::Logger.logger.debug(
135
162
  "Backup '#{old_name}' renamed and restored to '#{new_name}'"
136
163
  )
137
164
  new_serializer = Serializer::Mbox.new(account.local_path, new_name)
@@ -161,17 +188,6 @@ module Imap::Backup
161
188
  account.password.gsub(/./, "x")
162
189
  end
163
190
 
164
- def backup_folders
165
- @backup_folders ||=
166
- begin
167
- if account.folders&.any?
168
- account.folders
169
- else
170
- folders.map { |name| {name: name} }
171
- end
172
- end
173
- end
174
-
175
191
  def provider
176
192
  @provider ||= Email::Provider.for_address(account.username)
177
193
  end
@@ -179,5 +195,9 @@ module Imap::Backup
179
195
  def provider_options
180
196
  provider.options.merge(account.connection_options || {})
181
197
  end
198
+
199
+ def config
200
+ @config ||= Configuration.new
201
+ end
182
202
  end
183
203
  end
@@ -64,7 +64,7 @@ module Imap::Backup
64
64
  in `search_internal` in stdlib net/imap.rb.
65
65
  This is caused by `@responses["SEARCH"] being unset/undefined
66
66
  MESSAGE
67
- Imap::Backup.logger.warn message
67
+ Imap::Backup::Logger.logger.warn message
68
68
  []
69
69
  end
70
70
 
@@ -84,6 +84,26 @@ module Imap::Backup
84
84
  nil
85
85
  end
86
86
 
87
+ def fetch_multi(uids)
88
+ examine
89
+ fetch_data_items =
90
+ retry_on_error(errors: UID_FETCH_RETRY_CLASSES) do
91
+ client.uid_fetch(uids, [BODY_ATTRIBUTE])
92
+ end
93
+ return nil if fetch_data_items.nil?
94
+
95
+ fetch_data_items.map do |item|
96
+ attributes = item.attr
97
+
98
+ {
99
+ uid: attributes["UID"],
100
+ body: attributes[BODY_ATTRIBUTE]
101
+ }
102
+ end
103
+ rescue FolderNotFound
104
+ nil
105
+ end
106
+
87
107
  def append(message)
88
108
  body = message.imap_body
89
109
  date = message.date&.to_time
@@ -96,7 +116,7 @@ module Imap::Backup
96
116
  def examine
97
117
  client.examine(utf7_encoded_name)
98
118
  rescue Net::IMAP::NoResponseError
99
- Imap::Backup.logger.warn "Folder '#{name}' does not exist on server"
119
+ Imap::Backup::Logger.logger.warn "Folder '#{name}' does not exist on server"
100
120
  raise FolderNotFound, "Folder '#{name}' does not exist on server"
101
121
  end
102
122
 
@@ -20,6 +20,10 @@ module Imap::Backup
20
20
  @marked_for_deletion = false
21
21
  end
22
22
 
23
+ def connection
24
+ Account::Connection.new(self)
25
+ end
26
+
23
27
  def valid?
24
28
  username && password
25
29
  end
@@ -0,0 +1,43 @@
1
+ module Imap::Backup
2
+ class CLI; end
3
+
4
+ class CLI::Accounts
5
+ include Enumerable
6
+
7
+ attr_reader :required_accounts
8
+
9
+ def initialize(required_accounts = [])
10
+ @required_accounts = required_accounts
11
+ end
12
+
13
+ def each(&block)
14
+ return enum_for(:each) if !block
15
+
16
+ accounts.each(&block)
17
+ end
18
+
19
+ private
20
+
21
+ def accounts
22
+ @accounts ||=
23
+ if required_accounts.empty?
24
+ config.accounts
25
+ else
26
+ config.accounts.select do |account|
27
+ required_accounts.include?(account.username)
28
+ end
29
+ end
30
+ end
31
+
32
+ def config
33
+ @config ||= begin
34
+ exists = Configuration.exist?
35
+ if !exists
36
+ path = Configuration.default_pathname
37
+ raise ConfigurationNotFound, "Configuration file '#{path}' not found"
38
+ end
39
+ Configuration.new
40
+ end
41
+ end
42
+ end
43
+ end
@@ -14,7 +14,9 @@ module Imap::Backup
14
14
  def run
15
15
  each_connection(account_names) do |connection|
16
16
  puts connection.username
17
- folders = connection.folders
17
+ # TODO: Make folder_names private once this command
18
+ # has been removed.
19
+ folders = connection.folder_names
18
20
  if folders.nil?
19
21
  warn "Unable to list account folders"
20
22
  return false
@@ -1,4 +1,5 @@
1
1
  require "imap/backup"
2
+ require "imap/backup/cli/accounts"
2
3
 
3
4
  module Imap::Backup::CLI::Helpers
4
5
  def symbolized(options)
@@ -6,8 +7,8 @@ module Imap::Backup::CLI::Helpers
6
7
  end
7
8
 
8
9
  def account(email)
9
- connections = Imap::Backup::Configuration::List.new
10
- account = connections.accounts.find { |a| a.username == email }
10
+ accounts = Imap::Backup::CLI::Accounts.new
11
+ account = accounts.find { |a| a.username == email }
11
12
  raise "#{email} is not a configured account" if !account
12
13
 
13
14
  account
@@ -20,14 +21,12 @@ module Imap::Backup::CLI::Helpers
20
21
  end
21
22
 
22
23
  def each_connection(names)
23
- begin
24
- connections = Imap::Backup::Configuration::List.new(names)
25
- rescue Imap::Backup::ConfigurationNotFound
26
- raise "imap-backup is not configured. Run `imap-backup setup`"
27
- end
24
+ accounts = Imap::Backup::CLI::Accounts.new(names)
28
25
 
29
- connections.each_connection do |connection|
30
- yield connection
26
+ accounts.each do |account|
27
+ yield account.connection
31
28
  end
29
+ rescue Imap::Backup::ConfigurationNotFound
30
+ raise "imap-backup is not configured. Run `imap-backup setup`"
32
31
  end
33
32
  end
@@ -1,3 +1,5 @@
1
+ require "imap/backup/cli/accounts"
2
+
1
3
  module Imap::Backup
2
4
  class CLI::Local < Thor
3
5
  include Thor::Actions
@@ -5,8 +7,8 @@ module Imap::Backup
5
7
 
6
8
  desc "accounts", "List locally backed-up accounts"
7
9
  def accounts
8
- connections = Imap::Backup::Configuration::List.new
9
- connections.accounts.each { |a| Kernel.puts a.username }
10
+ accounts = CLI::Accounts.new
11
+ accounts.each { |a| Kernel.puts a.username }
10
12
  end
11
13
 
12
14
  desc "folders EMAIL", "List account folders"
@@ -7,7 +7,7 @@ class Imap::Backup::CLI::Setup < Thor
7
7
 
8
8
  no_commands do
9
9
  def run
10
- Imap::Backup::Configuration::Setup.new.run
10
+ Imap::Backup::Setup.new.run
11
11
  end
12
12
  end
13
13
  end
@@ -11,9 +11,10 @@ module Imap::Backup
11
11
  def ignore_history(email)
12
12
  connection = connection(email)
13
13
 
14
- connection.local_folders.each do |serializer, folder|
14
+ connection.backup_folders.each do |folder|
15
15
  next if !folder.exist?
16
16
 
17
+ serializer = Serializer::Mbox.new(connection.account.local_path, folder.name)
17
18
  do_ignore_folder_history(folder, serializer)
18
19
  end
19
20
  end
@@ -63,7 +64,7 @@ module Imap::Backup
63
64
  no_commands do
64
65
  def do_ignore_folder_history(folder, serializer)
65
66
  uids = folder.uids - serializer.uids
66
- Imap::Backup.logger.info "Folder '#{folder.name}' - #{uids.length} messages"
67
+ Imap::Backup::Logger.logger.info "Folder '#{folder.name}' - #{uids.length} messages"
67
68
 
68
69
  serializer.apply_uid_validity(folder.uid_validity)
69
70
 
@@ -4,10 +4,9 @@ require "os"
4
4
  require "imap/backup/account"
5
5
 
6
6
  module Imap::Backup
7
- module Configuration; end
8
-
9
- class Configuration::Store
7
+ class Configuration
10
8
  CONFIGURATION_DIRECTORY = File.expand_path("~/.imap-backup")
9
+ DEFAULT_DOWNLOAD_BLOCK_SIZE = 1
11
10
  VERSION = "2.0"
12
11
 
13
12
  attr_reader :pathname
@@ -22,6 +21,7 @@ module Imap::Backup
22
21
 
23
22
  def initialize(pathname = self.class.default_pathname)
24
23
  @pathname = pathname
24
+ @saved_debug = nil
25
25
  @debug = nil
26
26
  end
27
27
 
@@ -42,6 +42,7 @@ module Imap::Backup
42
42
  }
43
43
  File.open(pathname, "w") { |f| f.write(JSON.pretty_generate(save_data)) }
44
44
  FileUtils.chmod(0o600, pathname) if !windows?
45
+ @data = nil
45
46
  end
46
47
 
47
48
  def accounts
@@ -51,8 +52,19 @@ module Imap::Backup
51
52
  end
52
53
  end
53
54
 
55
+ def download_block_size
56
+ size = ENV["DOWNLOAD_BLOCK_SIZE"].to_i
57
+ if size > 0
58
+ size
59
+ else
60
+ DEFAULT_DOWNLOAD_BLOCK_SIZE
61
+ end
62
+ end
63
+
54
64
  def modified?
55
65
  ensure_loaded!
66
+ return true if @saved_debug != @debug
67
+
56
68
  accounts.any? { |a| a.modified? || a.marked_for_deletion? }
57
69
  end
58
70
 
@@ -73,6 +85,7 @@ module Imap::Backup
73
85
 
74
86
  data
75
87
  @debug = data.key?(:debug) ? data[:debug] == true : false
88
+ @saved_debug = @debug
76
89
  true
77
90
  end
78
91
 
@@ -2,27 +2,41 @@ module Imap::Backup
2
2
  class Downloader
3
3
  attr_reader :folder
4
4
  attr_reader :serializer
5
+ attr_reader :block_size
5
6
 
6
- def initialize(folder, serializer)
7
+ def initialize(folder, serializer, block_size: 1)
7
8
  @folder = folder
8
9
  @serializer = serializer
10
+ @block_size = block_size
9
11
  end
10
12
 
11
13
  def run
12
14
  uids = folder.uids - serializer.uids
13
15
  count = uids.count
14
- Imap::Backup.logger.debug "[#{folder.name}] #{count} new messages"
15
- uids.each.with_index do |uid, i|
16
- body = folder.fetch(uid)
17
- log_prefix = "[#{folder.name}] uid: #{uid} (#{i + 1}/#{count}) -"
18
- if body.nil?
19
- Imap::Backup.logger.debug("#{log_prefix} not available - skipped")
20
- next
16
+ Imap::Backup::Logger.logger.debug "[#{folder.name}] #{count} new messages"
17
+ uids.each_slice(block_size).with_index do |block, i|
18
+ offset = i * block_size + 1
19
+ uids_and_bodies = folder.fetch_multi(block)
20
+ if uids_and_bodies.nil?
21
+ if block_size > 1
22
+ Imap::Backup::Logger.logger.debug("[#{folder.name}] Multi fetch failed for UIDs #{block.join(", ")}, switching to single fetches")
23
+ @block_size = 1
24
+ redo
25
+ else
26
+ Imap::Backup::Logger.logger.debug("[#{folder.name}] Fetch failed for UID #{block[0]} - skipping")
27
+ next
28
+ end
29
+ end
30
+
31
+ uids_and_bodies.each.with_index do |uid_and_body, j|
32
+ uid = uid_and_body[:uid]
33
+ body = uid_and_body[:body]
34
+ Imap::Backup::Logger.logger.debug(
35
+ "[#{folder.name}] uid: #{uid} (#{offset +j}/#{count}) - " \
36
+ "#{body.size} bytes"
37
+ )
38
+ serializer.save(uid, body)
21
39
  end
22
- Imap::Backup.logger.debug(
23
- "#{log_prefix} #{body.size} bytes"
24
- )
25
- serializer.save(uid, body)
26
40
  end
27
41
  end
28
42
  end
@@ -0,0 +1,42 @@
1
+ require "logger"
2
+ require "singleton"
3
+
4
+ require "imap/backup/configuration"
5
+ require "imap/backup/sanitizer"
6
+
7
+ module Imap::Backup
8
+ class Logger
9
+ include Singleton
10
+
11
+ def self.logger
12
+ Logger.instance.logger
13
+ end
14
+
15
+ def self.setup_logging(config = Configuration.new)
16
+ logger.level =
17
+ if config.debug?
18
+ ::Logger::Severity::DEBUG
19
+ else
20
+ ::Logger::Severity::ERROR
21
+ end
22
+ Net::IMAP.debug = config.debug?
23
+ end
24
+
25
+ def self.sanitize_stderr
26
+ sanitizer = Sanitizer.new($stdout)
27
+ previous_stderr = $stderr
28
+ $stderr = sanitizer
29
+ yield
30
+ ensure
31
+ sanitizer.flush
32
+ $stderr = previous_stderr
33
+ end
34
+
35
+ attr_reader :logger
36
+
37
+ def initialize
38
+ @logger = ::Logger.new($stdout)
39
+ $stdout.sync = true
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ module Imap::Backup
2
+ class Sanitizer
3
+ attr_reader :output
4
+
5
+ def initialize(output)
6
+ @output = output
7
+ @current = ""
8
+ end
9
+
10
+ def write(*args)
11
+ output.write(*args)
12
+ end
13
+
14
+ def print(*args)
15
+ @current << args.join
16
+ loop do
17
+ line, newline, rest = @current.partition("\n")
18
+ break if newline != "\n"
19
+ clean = sanitize(line)
20
+ output.puts clean
21
+ @current = rest
22
+ end
23
+ end
24
+
25
+ def flush
26
+ return if @current == ""
27
+
28
+ clean = sanitize(@current)
29
+ output.puts clean
30
+ end
31
+
32
+ private
33
+
34
+ def sanitize(t)
35
+ # Hide password in Net::IMAP debug output
36
+ t.gsub(
37
+ /\A(C: RUBY\d+ LOGIN \S+) \S+/,
38
+ "\\1 [PASSWORD REDACTED]"
39
+ )
40
+ end
41
+ end
42
+ end
@@ -46,7 +46,7 @@ module Imap::Backup
46
46
 
47
47
  uid = uid.to_i
48
48
  if uids.include?(uid)
49
- Imap::Backup.logger.debug(
49
+ Imap::Backup::Logger.logger.debug(
50
50
  "[#{folder}] message #{uid} already downloaded - skipping"
51
51
  )
52
52
  return
@@ -65,7 +65,7 @@ module Imap::Backup
65
65
  #{body}. #{e}:
66
66
  #{e.backtrace.join("\n")}"
67
67
  ERROR
68
- Imap::Backup.logger.warn message
68
+ Imap::Backup::Logger.logger.warn message
69
69
  ensure
70
70
  mbox&.close
71
71
  end