imap-backup 4.0.1 → 4.0.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -1
  3. data/docs/development.md +5 -12
  4. data/imap-backup.gemspec +1 -4
  5. data/lib/email/mboxrd/message.rb +6 -2
  6. data/lib/email/provider/apple_mail.rb +7 -0
  7. data/lib/email/provider/base.rb +8 -0
  8. data/lib/email/provider/fastmail.rb +7 -0
  9. data/lib/email/provider/gmail.rb +7 -0
  10. data/lib/email/provider/unknown.rb +11 -0
  11. data/lib/email/provider.rb +16 -26
  12. data/lib/imap/backup/account/connection.rb +19 -29
  13. data/lib/imap/backup/account/folder.rb +9 -10
  14. data/lib/imap/backup/account.rb +103 -0
  15. data/lib/imap/backup/cli/helpers.rb +14 -0
  16. data/lib/imap/backup/cli/local.rb +19 -25
  17. data/lib/imap/backup/cli/utils.rb +67 -10
  18. data/lib/imap/backup/client/apple_mail.rb +11 -0
  19. data/lib/imap/backup/client/default.rb +51 -0
  20. data/lib/imap/backup/configuration/account.rb +3 -1
  21. data/lib/imap/backup/configuration/connection_tester.rb +1 -1
  22. data/lib/imap/backup/configuration/store.rb +10 -5
  23. data/lib/imap/backup/downloader.rb +3 -4
  24. data/lib/imap/backup/serializer/mbox.rb +5 -0
  25. data/lib/imap/backup/serializer/mbox_store.rb +8 -8
  26. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +58 -0
  27. data/lib/imap/backup/version.rb +1 -1
  28. data/lib/imap/backup.rb +1 -0
  29. data/lib/thunderbird/install.rb +16 -0
  30. data/lib/thunderbird/local_folder.rb +65 -0
  31. data/lib/thunderbird/profile.rb +30 -0
  32. data/lib/thunderbird/profiles.rb +71 -0
  33. data/lib/thunderbird/subdirectory.rb +96 -0
  34. data/lib/thunderbird/subdirectory_placeholder.rb +21 -0
  35. data/lib/thunderbird.rb +14 -0
  36. data/spec/features/restore_spec.rb +1 -1
  37. data/spec/features/support/email_server.rb +2 -2
  38. data/spec/unit/email/provider/apple_mail_spec.rb +7 -0
  39. data/spec/unit/email/provider/base_spec.rb +11 -0
  40. data/spec/unit/email/provider/fastmail_spec.rb +7 -0
  41. data/spec/unit/email/provider/gmail_spec.rb +7 -0
  42. data/spec/unit/email/provider_spec.rb +12 -25
  43. data/spec/unit/imap/backup/account/connection_spec.rb +26 -51
  44. data/spec/unit/imap/backup/account/folder_spec.rb +22 -22
  45. data/spec/unit/imap/backup/cli/local_spec.rb +70 -0
  46. data/spec/unit/imap/backup/cli/utils_spec.rb +50 -0
  47. data/spec/unit/imap/backup/client/default_spec.rb +22 -0
  48. data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +3 -3
  49. data/spec/unit/imap/backup/configuration/store_spec.rb +25 -12
  50. data/spec/unit/imap/backup/downloader_spec.rb +1 -2
  51. metadata +68 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97ae9089aa19dee6fcf7a1c211091671a6befe882d5b664654a25d6d10e81704
4
- data.tar.gz: 2677746ed662c457a738033224da11a40a76367e4031e7636b33391d51ee4659
3
+ metadata.gz: 6eebcf60acbb2e97a007e5da03c63fb7c32e24413397f28d3ec9f94154b8def5
4
+ data.tar.gz: 5f81961b55811c8c9fadabf2def11e1e00ab8572fd844f44b8fda371aa190bbb
5
5
  SHA512:
6
- metadata.gz: 5e97ba8ab64e27924166609c1cb80e52dbfa8136b4248324a7589e143d64ebddbb415ad6c4c7a0e472732db55c717d14e08be47c7640efcb36029c80b10938ef
7
- data.tar.gz: 2fd74f2b86946b79d07a1354a55b00444022838fcd4968a6a2f0dc15494f4c2d80d0ea06b1e0290b921e7f2242566a56fb8e9bd6bf03b5a88595871c91d08604
6
+ metadata.gz: 6ebb0d93413c0911487235584837f76f6409d66cc06a64ad9e7db7ec0a4ccca2694b9be363e02922bbf1c981d944a9772e6705190ad92b461252d7b57bf1e4b0
7
+ data.tar.gz: 6f29640122bf11c098050476e60caa073ebb868a0859624d6e7b74df435e85a1d6ebbcf964840058c6978a42d16034d86341741caead66d99722554ffc2ca4a3
data/README.md CHANGED
@@ -134,7 +134,15 @@ in the configuration file.
134
134
 
135
135
  The directory ~/.imap-backup, the configuration file and all backup
136
136
  directories have their access permissions set to only allow access
137
- by your user.
137
+ by your user. This is not done on Windows - see below.
138
+
139
+ ## Windows
140
+
141
+ Due to the complexity of managing permissions on Windows,
142
+ directory and file access permissions are not set explicity.
143
+
144
+ A pull request that implements permissions management on Windows
145
+ would be welcome!
138
146
 
139
147
  # Run Backup
140
148
 
data/docs/development.md CHANGED
@@ -2,18 +2,12 @@
2
2
 
3
3
  ## Integration Tests
4
4
 
5
- Integration tests (feature specs) are run against a Docker image
6
- (antespi/docker-imap-devel:latest).
7
-
8
- In one shell, run the Docker image:
5
+ Integration tests (feature specs) are run against a local IMAP server
6
+ controlled by Docker Compose, which needs to be started
7
+ before running the test suite.
9
8
 
10
9
  ```sh
11
- $ docker run \
12
- --env MAIL_ADDRESS=address@example.org \
13
- --env MAIL_PASS=pass \
14
- --env MAILNAME=example.org \
15
- --publish 8993:993 \
16
- antespi/docker-imap-devel:latest
10
+ $ docker-compose up -d
17
11
  ```
18
12
 
19
13
  ```sh
@@ -47,8 +41,7 @@ response = imap.append("INBOX", message, nil, nil)
47
41
  imap.examine("INBOX")
48
42
  uids = imap.uid_search(["ALL"]).sort
49
43
 
50
- REQUESTED_ATTRIBUTES = ["RFC822", "FLAGS", "INTERNALDATE"].freeze
51
- fetch_data_items = imap.uid_fetch(uids, REQUESTED_ATTRIBUTES)
44
+ fetch_data_items = imap.uid_fetch(uids, ["BODY[]"])
52
45
  ```
53
46
 
54
47
  # Contributing
data/imap-backup.gemspec CHANGED
@@ -17,10 +17,6 @@ Gem::Specification.new do |gem|
17
17
  gem.files += %w[imap-backup.gemspec]
18
18
  gem.files += %w[LICENSE README.md]
19
19
 
20
- gem.extra_rdoc_files += Dir.glob("README.md")
21
- gem.extra_rdoc_files += Dir.glob("docs/*.md")
22
- gem.rdoc_options = ["--main", "README.md"]
23
-
24
20
  gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
25
21
  gem.test_files = Dir.glob("spec/**/*{.rb,.yml}")
26
22
  gem.require_paths = ["lib"]
@@ -28,6 +24,7 @@ Gem::Specification.new do |gem|
28
24
 
29
25
  gem.add_runtime_dependency "highline"
30
26
  gem.add_runtime_dependency "mail"
27
+ gem.add_runtime_dependency "os"
31
28
  gem.add_runtime_dependency "rake"
32
29
  gem.add_runtime_dependency "thor", "~> 1.1"
33
30
 
@@ -1,9 +1,13 @@
1
+ require "forwardable"
1
2
  require "mail"
2
3
 
3
4
  module Email; end
4
5
 
5
6
  module Email::Mboxrd
6
7
  class Message
8
+ extend Forwardable
9
+ def_delegators :@parsed, :subject
10
+
7
11
  attr_reader :supplied_body
8
12
 
9
13
  def self.from_serialized(serialized)
@@ -36,12 +40,12 @@ module Email::Mboxrd
36
40
  supplied_body.gsub(/(?<!\r)\n/, "\r\n")
37
41
  end
38
42
 
43
+ private
44
+
39
45
  def parsed
40
46
  @parsed ||= Mail.new(supplied_body)
41
47
  end
42
48
 
43
- private
44
-
45
49
  def from
46
50
  @from ||=
47
51
  begin
@@ -0,0 +1,7 @@
1
+ require "email/provider/base"
2
+
3
+ class Email::Provider::AppleMail < Email::Provider::Base
4
+ def host
5
+ "imap.mail.me.com"
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Email; end
2
+ class Email::Provider; end
3
+
4
+ class Email::Provider::Base
5
+ def options
6
+ {port: 993, ssl: {ssl_version: :TLSv1_2}}
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ require "email/provider/base"
2
+
3
+ class Email::Provider::Fastmail < Email::Provider::Base
4
+ def host
5
+ "imap.fastmail.com"
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require "email/provider/base"
2
+
3
+ class Email::Provider::GMail < Email::Provider::Base
4
+ def host
5
+ "imap.gmail.com"
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ require "email/provider/base"
2
+
3
+ class Email::Provider::Unknown < Email::Provider::Base
4
+ # We don't know how to guess the IMAP server
5
+ def host
6
+ end
7
+
8
+ def options
9
+ {port: 993, ssl: {ssl_version: :TLSv1_2}}
10
+ end
11
+ end
@@ -1,37 +1,27 @@
1
+ require "email/provider/apple_mail"
2
+ require "email/provider/fastmail"
3
+ require "email/provider/gmail"
4
+ require "email/provider/unknown"
5
+
1
6
  module Email; end
2
7
 
3
8
  class Email::Provider
4
- GMAIL_IMAP_SERVER = "imap.gmail.com".freeze
5
-
6
9
  def self.for_address(address)
7
10
  case
8
11
  when address.end_with?("@fastmail.com")
9
- new(:fastmail)
10
- when address.end_with?("@gmail.com")
11
- new(:gmail)
12
+ Email::Provider::Fastmail.new
12
13
  when address.end_with?("@fastmail.fm")
13
- new(:fastmail)
14
+ Email::Provider::Fastmail.new
15
+ when address.end_with?("@gmail.com")
16
+ Email::Provider::GMail.new
17
+ when address.end_with?("@icloud.com")
18
+ Email::Provider::AppleMail.new
19
+ when address.end_with?("@mac.com")
20
+ Email::Provider::AppleMail.new
21
+ when address.end_with?("@me.com")
22
+ Email::Provider::AppleMail.new
14
23
  else
15
- new(:default)
16
- end
17
- end
18
-
19
- attr_reader :provider
20
-
21
- def initialize(provider)
22
- @provider = provider
23
- end
24
-
25
- def options
26
- {port: 993, ssl: {ssl_version: :TLSv1_2}}
27
- end
28
-
29
- def host
30
- case provider
31
- when :gmail
32
- GMAIL_IMAP_SERVER
33
- when :fastmail
34
- "imap.fastmail.com"
24
+ Email::Provider::Unknown.new
35
25
  end
36
26
  end
37
27
  end
@@ -1,4 +1,5 @@
1
- require "net/imap"
1
+ require "imap/backup/client/apple_mail"
2
+ require "imap/backup/client/default"
2
3
 
3
4
  require "retry_on_error"
4
5
 
@@ -29,17 +30,15 @@ module Imap::Backup
29
30
  def folders
30
31
  @folders ||=
31
32
  begin
32
- root = provider_root
33
- mailbox_lists = imap.list(root, "*")
33
+ folders = client.list
34
34
 
35
- if mailbox_lists.nil?
35
+ if folders.empty?
36
36
  message = "Unable to get folder list for account #{username}"
37
37
  Imap::Backup.logger.info message
38
38
  raise message
39
39
  end
40
40
 
41
- utf7_encoded = mailbox_lists.map(&:name)
42
- utf7_encoded.map { |n| Net::IMAP.decode_utf7(n) }
41
+ folders
43
42
  end
44
43
  end
45
44
 
@@ -54,7 +53,7 @@ module Imap::Backup
54
53
  def run_backup
55
54
  Imap::Backup.logger.debug "Running backup of account: #{username}"
56
55
  # start the connection so we get logging messages in the right order
57
- imap
56
+ client
58
57
  each_folder do |folder, serializer|
59
58
  next if !folder.exist?
60
59
 
@@ -89,34 +88,36 @@ module Imap::Backup
89
88
  end
90
89
 
91
90
  def disconnect
92
- imap.disconnect if @imap
91
+ client.disconnect if @client
93
92
  end
94
93
 
95
94
  def reconnect
96
95
  disconnect
97
- @imap = nil
96
+ @client = nil
98
97
  end
99
98
 
100
- def imap
101
- @imap ||=
99
+ def client
100
+ @client ||=
102
101
  retry_on_error(errors: LOGIN_RETRY_CLASSES) do
103
102
  options = provider_options
104
103
  Imap::Backup.logger.debug(
105
104
  "Creating IMAP instance: #{server}, options: #{options.inspect}"
106
105
  )
107
- imap = Net::IMAP.new(server, options)
106
+ client =
107
+ if provider.is_a?(Email::Provider::AppleMail)
108
+ Client::AppleMail.new(server, options)
109
+ else
110
+ Client::Default.new(server, options)
111
+ end
108
112
  Imap::Backup.logger.debug "Logging in: #{username}/#{masked_password}"
109
- imap.login(username, password)
113
+ client.login(username, password)
110
114
  Imap::Backup.logger.debug "Login complete"
111
- imap
115
+ client
112
116
  end
113
117
  end
114
118
 
115
119
  def server
116
- return @server if @server
117
- return nil if provider.nil?
118
-
119
- @server = provider.host
120
+ @server ||= provider.host
120
121
  end
121
122
 
122
123
  private
@@ -186,16 +187,5 @@ module Imap::Backup
186
187
  def provider_options
187
188
  provider.options.merge(connection_options)
188
189
  end
189
-
190
- # 6.3.8. LIST Command
191
- # An empty ("" string) mailbox name argument is a special request to
192
- # return the hierarchy delimiter and the root name of the name given
193
- # in the reference.
194
- def provider_root
195
- return @provider_root if @provider_root
196
-
197
- root_info = imap.list("", "")[0]
198
- @provider_root = root_info.name
199
- end
200
190
  end
201
191
  end
@@ -11,13 +11,13 @@ module Imap::Backup
11
11
  extend Forwardable
12
12
  include RetryOnError
13
13
 
14
- REQUESTED_ATTRIBUTES = %w[RFC822 FLAGS INTERNALDATE].freeze
14
+ BODY_ATTRIBUTE = "BODY[]".freeze
15
15
  UID_FETCH_RETRY_CLASSES = [EOFError].freeze
16
16
 
17
17
  attr_reader :connection
18
18
  attr_reader :name
19
19
 
20
- delegate imap: :connection
20
+ delegate client: :connection
21
21
 
22
22
  def initialize(connection, name)
23
23
  @connection = connection
@@ -40,20 +40,20 @@ module Imap::Backup
40
40
  def create
41
41
  return if exist?
42
42
 
43
- imap.create(utf7_encoded_name)
43
+ client.create(utf7_encoded_name)
44
44
  end
45
45
 
46
46
  def uid_validity
47
47
  @uid_validity ||=
48
48
  begin
49
49
  examine
50
- imap.responses["UIDVALIDITY"][-1]
50
+ client.responses["UIDVALIDITY"][-1]
51
51
  end
52
52
  end
53
53
 
54
54
  def uids
55
55
  examine
56
- imap.uid_search(["ALL"]).sort
56
+ client.uid_search(["ALL"]).sort
57
57
  rescue FolderNotFound
58
58
  []
59
59
  rescue NoMethodError
@@ -72,15 +72,14 @@ module Imap::Backup
72
72
  examine
73
73
  fetch_data_items =
74
74
  retry_on_error(errors: UID_FETCH_RETRY_CLASSES) do
75
- imap.uid_fetch([uid.to_i], REQUESTED_ATTRIBUTES)
75
+ client.uid_fetch([uid.to_i], [BODY_ATTRIBUTE])
76
76
  end
77
77
  return nil if fetch_data_items.nil?
78
78
 
79
79
  fetch_data_item = fetch_data_items[0]
80
80
  attributes = fetch_data_item.attr
81
- return nil if !attributes.key?("RFC822")
82
81
 
83
- attributes
82
+ attributes[BODY_ATTRIBUTE]
84
83
  rescue FolderNotFound
85
84
  nil
86
85
  end
@@ -88,14 +87,14 @@ module Imap::Backup
88
87
  def append(message)
89
88
  body = message.imap_body
90
89
  date = message.date&.to_time
91
- response = imap.append(utf7_encoded_name, body, nil, date)
90
+ response = client.append(utf7_encoded_name, body, nil, date)
92
91
  extract_uid(response)
93
92
  end
94
93
 
95
94
  private
96
95
 
97
96
  def examine
98
- imap.examine(utf7_encoded_name)
97
+ client.examine(utf7_encoded_name)
99
98
  rescue Net::IMAP::NoResponseError
100
99
  Imap::Backup.logger.warn "Folder '#{name}' does not exist on server"
101
100
  raise FolderNotFound, "Folder '#{name}' does not exist on server"
@@ -0,0 +1,103 @@
1
+ module Imap::Backup
2
+ class Account
3
+ attr_reader :username
4
+ attr_reader :password
5
+ attr_reader :local_path
6
+ attr_reader :folders
7
+ attr_reader :server
8
+ attr_reader :connection_options
9
+ attr_reader :changes
10
+ attr_reader :marked_for_deletion
11
+
12
+ def initialize(options)
13
+ @username = options[:username]
14
+ @password = options[:password]
15
+ @local_path = options[:local_path]
16
+ @folders = options[:folders]
17
+ @server = options[:server]
18
+ @connection_options = options[:connection_options]
19
+ @changes = {}
20
+ @marked_for_deletion = false
21
+ end
22
+
23
+ def valid?
24
+ username && password
25
+ end
26
+
27
+ def modified?
28
+ changes.any?
29
+ end
30
+
31
+ def clear_changes!
32
+ @changes = {}
33
+ end
34
+
35
+ def mark_for_deletion!
36
+ @marked_for_deletion = true
37
+ end
38
+
39
+ def marked_for_deletion?
40
+ @marked_for_deletion
41
+ end
42
+
43
+ def to_h
44
+ h = {
45
+ username: @username,
46
+ password: @password,
47
+ }
48
+ h[:local_path] = @local_path if @local_path
49
+ h[:folders] = @folders if @folders
50
+ h[:server] = @server if @server
51
+ h[:connection_options] = @connection_options if @connection_options
52
+ h
53
+ end
54
+
55
+ def username=(value)
56
+ update(:username, value)
57
+ end
58
+
59
+ def password=(value)
60
+ update(:password, value)
61
+ end
62
+
63
+ def local_path=(value)
64
+ update(:local_path, value)
65
+ end
66
+
67
+ def folders=(value)
68
+ raise "folders must be an Array" if !value.is_a?(Array)
69
+ update(:folders, value)
70
+ end
71
+
72
+ def server=(value)
73
+ update(:server, value)
74
+ end
75
+
76
+ def connection_options=(value)
77
+ parsed = JSON.parse(value)
78
+ update(:connection_options, parsed)
79
+ end
80
+
81
+ private
82
+
83
+ def update(field, value)
84
+ if changes[field]
85
+ change = changes[field]
86
+ if change[:from] == value
87
+ changes.delete(field)
88
+ else
89
+ set_field!(field, value)
90
+ end
91
+ else
92
+ set_field!(field, value)
93
+ end
94
+ end
95
+
96
+ def set_field!(field, value)
97
+ key = :"@#{field}"
98
+ current = instance_variable_get(key)
99
+ changes[field] = {from: current, to: value}
100
+ instance_variable_set(key, value)
101
+ end
102
+ end
103
+ end
@@ -5,6 +5,20 @@ module Imap::Backup::CLI::Helpers
5
5
  options.each.with_object({}) { |(k, v), acc| acc[k.intern] = v }
6
6
  end
7
7
 
8
+ def account(email)
9
+ connections = Imap::Backup::Configuration::List.new
10
+ account = connections.accounts.find { |a| a[:username] == email }
11
+ raise "#{email} is not a configured account" if !account
12
+
13
+ account
14
+ end
15
+
16
+ def connection(email)
17
+ account = account(email)
18
+
19
+ Imap::Backup::Account::Connection.new(account)
20
+ end
21
+
8
22
  def each_connection(names)
9
23
  begin
10
24
  connections = Imap::Backup::Configuration::List.new(names)
@@ -6,49 +6,46 @@ module Imap::Backup
6
6
  desc "accounts", "List locally backed-up accounts"
7
7
  def accounts
8
8
  connections = Imap::Backup::Configuration::List.new
9
- connections.accounts.each { |a| puts a[:username] }
9
+ connections.accounts.each { |a| Kernel.puts a[:username] }
10
10
  end
11
11
 
12
12
  desc "folders EMAIL", "List account folders"
13
13
  def folders(email)
14
- connections = Imap::Backup::Configuration::List.new
15
- account = connections.accounts.find { |a| a[:username] == email }
16
- raise "#{email} is not a configured account" if !account
14
+ connection = connection(email)
17
15
 
18
- account_connection = Imap::Backup::Account::Connection.new(account)
19
- account_connection.local_folders.each do |_s, f|
20
- puts %("#{f.name}")
16
+ connection.local_folders.each do |_s, f|
17
+ Kernel.puts %("#{f.name}")
21
18
  end
22
19
  end
23
20
 
24
21
  desc "list EMAIL FOLDER", "List emails in a folder"
25
22
  def list(email, folder_name)
26
- connections = Imap::Backup::Configuration::List.new
27
- account = connections.accounts.find { |a| a[:username] == email }
28
- raise "#{email} is not a configured account" if !account
23
+ connection = connection(email)
29
24
 
30
- account_connection = Imap::Backup::Account::Connection.new(account)
31
- folder_serializer, _folder = account_connection.local_folders.find do |(_s, f)|
25
+ folder_serializer, _folder = connection.local_folders.find do |(_s, f)|
32
26
  f.name == folder_name
33
27
  end
34
28
  raise "Folder '#{folder_name}' not found" if !folder_serializer
35
29
 
36
30
  max_subject = 60
37
- puts format("%-10<uid>s %-#{max_subject}<subject>s - %<date>s", {uid: "UID", subject: "Subject", date: "Date"})
38
- puts "-" * (12 + max_subject + 28)
31
+ Kernel.puts format(
32
+ "%-10<uid>s %-#{max_subject}<subject>s - %<date>s",
33
+ {uid: "UID", subject: "Subject", date: "Date"}
34
+ )
35
+ Kernel.puts "-" * (12 + max_subject + 28)
39
36
 
40
37
  uids = folder_serializer.uids
41
38
 
42
39
  folder_serializer.each_message(uids).map do |uid, message|
43
40
  m = {
44
41
  uid: uid,
45
- date: message.parsed.date.to_s,
46
- subject: message.parsed.subject || ""
42
+ date: message.date.to_s,
43
+ subject: message.subject || ""
47
44
  }
48
45
  if m[:subject].length > max_subject
49
- puts format("% 10<uid>u: %.#{max_subject - 3}<subject>s... - %<date>s", m)
46
+ Kernel.puts format("% 10<uid>u: %.#{max_subject - 3}<subject>s... - %<date>s", m)
50
47
  else
51
- puts format("% 10<uid>u: %-#{max_subject}<subject>s - %<date>s", m)
48
+ Kernel.puts format("% 10<uid>u: %-#{max_subject}<subject>s - %<date>s", m)
52
49
  end
53
50
  end
54
51
  end
@@ -60,12 +57,9 @@ module Imap::Backup
60
57
  the UID.
61
58
  DESC
62
59
  def show(email, folder_name, uids)
63
- connections = Imap::Backup::Configuration::List.new
64
- account = connections.accounts.find { |a| a[:username] == email }
65
- raise "#{email} is not a configured account" if !account
60
+ connection = connection(email)
66
61
 
67
- account_connection = Imap::Backup::Account::Connection.new(account)
68
- folder_serializer, _folder = account_connection.local_folders.find do |(_s, f)|
62
+ folder_serializer, _folder = connection.local_folders.find do |(_s, f)|
69
63
  f.name == folder_name
70
64
  end
71
65
  raise "Folder '#{folder_name}' not found" if !folder_serializer
@@ -73,13 +67,13 @@ module Imap::Backup
73
67
  uid_list = uids.split(",")
74
68
  folder_serializer.each_message(uid_list).each do |uid, message|
75
69
  if uid_list.count > 1
76
- puts <<~HEADER
70
+ Kernel.puts <<~HEADER
77
71
  #{'-' * 80}
78
72
  #{format('| UID: %-71s |', uid)}
79
73
  #{'-' * 80}
80
74
  HEADER
81
75
  end
82
- puts message.supplied_body
76
+ Kernel.puts message.supplied_body
83
77
  end
84
78
  end
85
79
  end