imap-backup 4.0.1 → 4.0.5

Sign up to get free protection for your applications and to get access to all the features.
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