imap-backup 4.0.0 → 4.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -49
  3. data/docs/development.md +53 -0
  4. data/docs/restore.md +17 -0
  5. data/imap-backup.gemspec +4 -7
  6. data/lib/email/mboxrd/message.rb +6 -2
  7. data/lib/email/provider/apple_mail.rb +7 -0
  8. data/lib/email/provider/default.rb +12 -0
  9. data/lib/email/provider/fastmail.rb +7 -0
  10. data/lib/email/provider/gmail.rb +7 -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/cli/helpers.rb +14 -1
  15. data/lib/imap/backup/cli/local.rb +22 -28
  16. data/lib/imap/backup/cli/setup.rb +1 -1
  17. data/lib/imap/backup/cli/utils.rb +98 -0
  18. data/lib/imap/backup/cli.rb +5 -1
  19. data/lib/imap/backup/client/apple_mail.rb +11 -0
  20. data/lib/imap/backup/client/default.rb +51 -0
  21. data/lib/imap/backup/configuration/account.rb +3 -1
  22. data/lib/imap/backup/configuration/connection_tester.rb +1 -1
  23. data/lib/imap/backup/configuration/store.rb +10 -5
  24. data/lib/imap/backup/downloader.rb +3 -4
  25. data/lib/imap/backup/serializer/mbox.rb +5 -0
  26. data/lib/imap/backup/serializer/mbox_store.rb +8 -8
  27. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +58 -0
  28. data/lib/imap/backup/version.rb +1 -1
  29. data/lib/imap/backup.rb +1 -0
  30. data/lib/thunderbird/install.rb +16 -0
  31. data/lib/thunderbird/local_folder.rb +65 -0
  32. data/lib/thunderbird/profile.rb +30 -0
  33. data/lib/thunderbird/profiles.rb +71 -0
  34. data/lib/thunderbird/subdirectory.rb +96 -0
  35. data/lib/thunderbird/subdirectory_placeholder.rb +21 -0
  36. data/lib/thunderbird.rb +14 -0
  37. data/spec/features/restore_spec.rb +1 -1
  38. data/spec/features/support/email_server.rb +2 -2
  39. data/spec/spec_helper.rb +1 -0
  40. data/spec/unit/email/provider/apple_mail_spec.rb +7 -0
  41. data/spec/unit/email/provider/default_spec.rb +17 -0
  42. data/spec/unit/email/provider/fastmail_spec.rb +7 -0
  43. data/spec/unit/email/provider/gmail_spec.rb +7 -0
  44. data/spec/unit/email/provider_spec.rb +12 -25
  45. data/spec/unit/imap/backup/account/connection_spec.rb +26 -51
  46. data/spec/unit/imap/backup/account/folder_spec.rb +22 -22
  47. data/spec/unit/imap/backup/cli/local_spec.rb +70 -0
  48. data/spec/unit/imap/backup/cli/utils_spec.rb +50 -0
  49. data/spec/unit/imap/backup/client/default_spec.rb +22 -0
  50. data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +3 -3
  51. data/spec/unit/imap/backup/configuration/store_spec.rb +25 -12
  52. data/spec/unit/imap/backup/downloader_spec.rb +1 -2
  53. metadata +71 -28
  54. data/docs/docker-imap.md +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85e081f686a106384d27ffc91cb21965832edd629da671261bda69b668776d5e
4
- data.tar.gz: 8253587491a279e76ebed2268a66b60d9aab4f517cdafadb8c9494e7c3f3648b
3
+ metadata.gz: 69ed28d85dda7c3d30cd6c8d4a9888e9f477eedd6f8ff08741fcc7d27cf087f8
4
+ data.tar.gz: 1a99e7143052a1d0b1b2d58381c5f9da0db2b1e0e3882c24e56036cebead043f
5
5
  SHA512:
6
- metadata.gz: e2b3806cedfe124c286477f50690781c4593db1f3b12d53281c666d3d5771f9a42aa4cc24851fb88f9205a2f11a8e299c74a331a606de1aab056e56b753e3cf1
7
- data.tar.gz: fc96edce37dd33793d04da272f2aea087ad7a16aa409726c83d6cf453bd386e3673a75b8d4e0eee90f352fc1e9168d611865dd87f79c05ff0cf132278bf59df3
6
+ metadata.gz: deb80ed5d629c81253574d96a7da0dcc6382eb6d5216c1f317b8083ca0f4dac80a3188cbc0b7f46ffbc01229dad9ab913858649558ca7b3a29bf7b81395bcce3
7
+ data.tar.gz: 2e6b2b8d2c67c6bc1e3ff5dcbb91c4eec92d0edb87ff33ad6e8a360b6635895c72cc7eb4cc68a7ff24bcfbad5a3533bda0a916e3c4d0c40ee67de70a010d4b2b
data/README.md CHANGED
@@ -16,10 +16,6 @@
16
16
  [Rubygem]: http://rubygems.org/gems/imap-backup "Ruby gem at rubygems.org"
17
17
  [Continuous Integration]: https://circleci.com/gh/joeyates/imap-backup "Build status by CirceCI"
18
18
 
19
- # GMail
20
-
21
- To use imap-backup with GMail, you will need to enable 'App passwords' on your account.
22
-
23
19
  # Installation
24
20
 
25
21
  ```shell
@@ -51,6 +47,10 @@ Run:
51
47
  $ imap-backup setup
52
48
  ```
53
49
 
50
+ ## GMail
51
+
52
+ To use imap-backup with GMail, you will need to enable 'App passwords' on your account.
53
+
54
54
  ## Folders
55
55
 
56
56
  By default, all folders are backed-up. You can override this by choosing
@@ -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
 
@@ -178,6 +186,7 @@ If you have problems:
178
186
  "debug": true
179
187
  }
180
188
  ```
189
+
181
190
  # Restore
182
191
 
183
192
  All missing messages are pushed to the IMAP server.
@@ -206,48 +215,7 @@ $ imap-backup status
206
215
  * Restartable - calculate start point based on already downloaded messages
207
216
  * Standalone - do not rely on an email client or MTA
208
217
 
209
- # Similar Software
210
-
211
- * https://github.com/OfflineIMAP/offlineimap
212
-
213
- # Testing
214
-
215
- ## Integration Tests
216
-
217
- Integration tests (feature specs) are run against a Docker image
218
- (antespi/docker-imap-devel:latest).
219
-
220
- In one shell, run the Docker image:
221
-
222
- ```sh
223
- $ docker run \
224
- --env MAIL_ADDRESS=address@example.org \
225
- --env MAIL_PASS=pass \
226
- --env MAILNAME=example.org \
227
- --publish 8993:993 \
228
- antespi/docker-imap-devel:latest
229
- ```
230
-
231
- ```sh
232
- $ rake
233
- ```
234
-
235
- To exclude Docker-based tests:
236
-
237
- ```sh
238
- rake no-docker
239
- ```
240
-
241
- or
242
-
243
- ```sh
244
- $ rspec --tag ~docker
245
- ```
246
-
247
- ## Contributing
218
+ # Documentation
248
219
 
249
- 1. Fork it
250
- 2. Create your feature branch (`git checkout -b my-new-feature`)
251
- 3. Commit your changes (`git commit -am 'Added some feature'`)
252
- 4. Push to the branch (`git push origin my-new-feature`)
253
- 5. Create new Pull Request
220
+ * [Development](./docs/development.md)
221
+ * [Restore](./docs/restore.md)
@@ -0,0 +1,53 @@
1
+ # Testing
2
+
3
+ ## Integration Tests
4
+
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.
8
+
9
+ ```sh
10
+ $ docker-compose up -d
11
+ ```
12
+
13
+ ```sh
14
+ $ rake
15
+ ```
16
+
17
+ To exclude Docker-based tests:
18
+
19
+ ```sh
20
+ rake no-docker
21
+ ```
22
+
23
+ or
24
+
25
+ ```sh
26
+ $ rspec --tag ~docker
27
+ ```
28
+
29
+ ## Access Docker imap server
30
+
31
+ ```ruby
32
+ require "net/imap"
33
+
34
+ imap = Net::IMAP.new("localhost", {port: 8993, ssl: {verify_mode: 0}})
35
+ username = "address@example.org"
36
+ imap.login(username, "pass")
37
+
38
+ message = "From: #{username}\nSubject: Some Subject\n\nHello!\n"
39
+ response = imap.append("INBOX", message, nil, nil)
40
+
41
+ imap.examine("INBOX")
42
+ uids = imap.uid_search(["ALL"]).sort
43
+
44
+ fetch_data_items = imap.uid_fetch(uids, ["BODY[]"])
45
+ ```
46
+
47
+ # Contributing
48
+
49
+ 1. Fork it
50
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
51
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
52
+ 4. Push to the branch (`git push origin my-new-feature`)
53
+ 5. Create new Pull Request
data/docs/restore.md CHANGED
@@ -2,10 +2,27 @@
2
2
 
3
3
  # How does restore work?
4
4
 
5
+ Backed-up emails are pushed to the IMAP server.
6
+ If there are clashes, folders are renamed.
7
+
5
8
  # What are all these 'INBOX.12345' files?
6
9
 
10
+ If, when the backup is launched, the IMAP server contains a folder with
11
+ the same name, but different history to the local backup, the local
12
+ emails cannot simply be added to the existing folder.
13
+
14
+ In this case, a numeric suffix is added to the **local** folder,
15
+ before it is restored.
16
+
17
+ In this way, old and new emails are kept separate.
18
+
7
19
  # Will my email get overwritten?
8
20
 
21
+ No.
22
+
23
+ Emails are identified by folder and a specific email id. Any email that
24
+ is already on the server is skipped.
25
+
9
26
  ## How do I restore to a different service?
10
27
 
11
28
  1. Run setup and add the new server, (but don't run any backups),
data/imap-backup.gemspec CHANGED
@@ -1,6 +1,5 @@
1
1
  $LOAD_PATH.unshift(File.expand_path("lib", __dir__))
2
2
  require "imap/backup/version"
3
- require "rake/file_list"
4
3
 
5
4
  Gem::Specification.new do |gem|
6
5
  gem.name = "imap-backup"
@@ -10,24 +9,22 @@ Gem::Specification.new do |gem|
10
9
  gem.email = ["joe.g.yates@gmail.com"]
11
10
  gem.homepage = "https://github.com/joeyates/imap-backup"
12
11
  gem.licenses = ["MIT"]
12
+ gem.version = Imap::Backup::VERSION
13
13
 
14
- # Build list of files manually, see also
15
- # https://github.com/rubygems/rubygems/blob/master/bundler/bundler.gemspec#L37
16
14
  gem.files = %w[bin/imap-backup]
17
- gem.files += Dir.glob("docs/*{.png,.md}")
15
+ gem.files += Dir.glob("docs/*.md")
18
16
  gem.files += Dir.glob("lib/**/*.rb")
19
- gem.files += Dir.glob("spec/**/*{.rb,.yml}")
20
17
  gem.files += %w[imap-backup.gemspec]
21
18
  gem.files += %w[LICENSE README.md]
22
19
 
23
20
  gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
24
- gem.test_files = gem.files.grep(%r{^spec/})
21
+ gem.test_files = Dir.glob("spec/**/*{.rb,.yml}")
25
22
  gem.require_paths = ["lib"]
26
23
  gem.required_ruby_version = ">= 2.5"
27
- gem.version = Imap::Backup::VERSION
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/default"
2
+
3
+ class Email::Provider::AppleMail < Email::Provider::Default
4
+ def host
5
+ "imap.mail.me.com"
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Email; end
2
+ class Email::Provider; end
3
+
4
+ class Email::Provider::Default
5
+ # We don't know how to guess the IMAP server
6
+ def host
7
+ end
8
+
9
+ def options
10
+ {port: 993, ssl: {ssl_version: :TLSv1_2}}
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ require "email/provider/default"
2
+
3
+ class Email::Provider::Fastmail < Email::Provider::Default
4
+ def host
5
+ "imap.fastmail.com"
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require "email/provider/default"
2
+
3
+ class Email::Provider::GMail < Email::Provider::Default
4
+ def host
5
+ "imap.gmail.com"
6
+ end
7
+ end
@@ -1,37 +1,27 @@
1
+ require "email/provider/default"
2
+ require "email/provider/apple_mail"
3
+ require "email/provider/fastmail"
4
+ require "email/provider/gmail"
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::Default.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"
@@ -5,12 +5,25 @@ 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)
11
25
  rescue Imap::Backup::ConfigurationNotFound
12
26
  raise "imap-backup is not configured. Run `imap-backup setup`"
13
- return
14
27
  end
15
28
 
16
29
  connections.each_connection do |connection|
@@ -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
77
- #{"-" * 80}
78
- #{format("| UID: %-71s |", uid)}
79
- #{"-" * 80}
70
+ Kernel.puts <<~HEADER
71
+ #{'-' * 80}
72
+ #{format('| UID: %-71s |', uid)}
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
@@ -1,7 +1,7 @@
1
1
  class Imap::Backup::CLI::Setup < Thor
2
2
  include Thor::Actions
3
3
 
4
- def initialize()
4
+ def initialize
5
5
  super([])
6
6
  end
7
7