imap-backup 14.4.4 → 14.5.0

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +67 -137
  3. data/docs/documentation.md +19 -0
  4. data/imap-backup.gemspec +1 -1
  5. data/lib/imap/backup/account/backup.rb +2 -0
  6. data/lib/imap/backup/account/backup_folders.rb +7 -1
  7. data/lib/imap/backup/account/client_factory.rb +1 -0
  8. data/lib/imap/backup/account/folder.rb +26 -0
  9. data/lib/imap/backup/account/folder_backup.rb +4 -1
  10. data/lib/imap/backup/account/folder_ensurer.rb +3 -0
  11. data/lib/imap/backup/account/local_only_folder_deleter.rb +3 -1
  12. data/lib/imap/backup/account/restore.rb +2 -0
  13. data/lib/imap/backup/account/serialized_folders.rb +31 -1
  14. data/lib/imap/backup/account.rb +34 -18
  15. data/lib/imap/backup/cli/backup.rb +3 -0
  16. data/lib/imap/backup/cli/folder_enumerator.rb +6 -0
  17. data/lib/imap/backup/cli/helpers.rb +13 -0
  18. data/lib/imap/backup/cli/local/check.rb +3 -0
  19. data/lib/imap/backup/cli/local.rb +14 -1
  20. data/lib/imap/backup/cli/remote.rb +7 -0
  21. data/lib/imap/backup/cli/restore.rb +4 -0
  22. data/lib/imap/backup/cli/setup.rb +3 -0
  23. data/lib/imap/backup/cli/single/backup.rb +3 -0
  24. data/lib/imap/backup/cli/single.rb +4 -0
  25. data/lib/imap/backup/cli/stats.rb +3 -0
  26. data/lib/imap/backup/cli/transfer.rb +8 -0
  27. data/lib/imap/backup/cli/utils.rb +7 -1
  28. data/lib/imap/backup/cli.rb +8 -0
  29. data/lib/imap/backup/client/apple_mail.rb +2 -0
  30. data/lib/imap/backup/client/automatic_login_wrapper.rb +9 -1
  31. data/lib/imap/backup/client/default.rb +15 -4
  32. data/lib/imap/backup/configuration.rb +13 -0
  33. data/lib/imap/backup/configuration_not_found.rb +1 -0
  34. data/lib/imap/backup/downloader.rb +4 -0
  35. data/lib/imap/backup/email/mboxrd/message.rb +14 -0
  36. data/lib/imap/backup/email/provider/apple_mail.rb +2 -0
  37. data/lib/imap/backup/email/provider/base.rb +3 -3
  38. data/lib/imap/backup/email/provider/fastmail.rb +2 -0
  39. data/lib/imap/backup/email/provider/gmail.rb +2 -0
  40. data/lib/imap/backup/email/provider/purelymail.rb +2 -0
  41. data/lib/imap/backup/email/provider/unknown.rb +2 -6
  42. data/lib/imap/backup/email/provider.rb +5 -0
  43. data/lib/imap/backup/file_mode.rb +2 -0
  44. data/lib/imap/backup/flag_refresher.rb +4 -0
  45. data/lib/imap/backup/local_only_message_deleter.rb +2 -0
  46. data/lib/imap/backup/logger.rb +18 -0
  47. data/lib/imap/backup/migrator.rb +3 -0
  48. data/lib/imap/backup/mirror/map.rb +21 -0
  49. data/lib/imap/backup/mirror.rb +8 -0
  50. data/lib/imap/backup/naming.rb +10 -1
  51. data/lib/imap/backup/retry_on_error.rb +9 -0
  52. data/lib/imap/backup/serializer/appender.rb +9 -0
  53. data/lib/imap/backup/serializer/delayed_metadata_serializer.rb +4 -0
  54. data/lib/imap/backup/serializer/folder_maker.rb +1 -0
  55. data/lib/imap/backup/serializer/imap.rb +38 -2
  56. data/lib/imap/backup/serializer/integrity_checker.rb +1 -0
  57. data/lib/imap/backup/serializer/mbox.rb +26 -0
  58. data/lib/imap/backup/serializer/message.rb +13 -0
  59. data/lib/imap/backup/serializer/message_enumerator.rb +10 -2
  60. data/lib/imap/backup/serializer/permission_checker.rb +6 -0
  61. data/lib/imap/backup/serializer/transaction.rb +18 -0
  62. data/lib/imap/backup/serializer/unused_name_finder.rb +4 -0
  63. data/lib/imap/backup/serializer/version2_migrator.rb +4 -0
  64. data/lib/imap/backup/serializer.rb +56 -2
  65. data/lib/imap/backup/setup/account/header.rb +6 -0
  66. data/lib/imap/backup/setup/account.rb +6 -0
  67. data/lib/imap/backup/setup/asker.rb +16 -0
  68. data/lib/imap/backup/setup/backup_path.rb +6 -0
  69. data/lib/imap/backup/setup/connection_tester.rb +5 -0
  70. data/lib/imap/backup/setup/email_changer.rb +6 -0
  71. data/lib/imap/backup/setup/folder_chooser.rb +4 -0
  72. data/lib/imap/backup/setup/global_options/download_strategy_chooser.rb +4 -0
  73. data/lib/imap/backup/setup/global_options.rb +4 -0
  74. data/lib/imap/backup/setup/helpers.rb +3 -0
  75. data/lib/imap/backup/setup.rb +5 -0
  76. data/lib/imap/backup/text/sanitizer.rb +9 -0
  77. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +8 -1
  78. data/lib/imap/backup/uploader.rb +5 -0
  79. data/lib/imap/backup/version.rb +7 -2
  80. metadata +11 -13
  81. data/docs/api.md +0 -20
  82. data/docs/development.md +0 -110
  83. data/docs/migrate-server-keep-address.md +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc28eee3a2ef71157ebe6e50490488ce92b101bb3c4e02a46964b398ddc85d83
4
- data.tar.gz: e6ee9d519463a25bf391fb71bf426d59aeaf27072afdf6306bbe631703a82dfb
3
+ metadata.gz: ee294a8f4d7c0af90c725939b3f4cd7826ac521194460af3446e7cf5378629f4
4
+ data.tar.gz: c67cac7ddfb2448a9cb22b642b53be02b157959d51f3677bc37ec891da2471c8
5
5
  SHA512:
6
- metadata.gz: 0004c4453debba185805fdce233f450570b6bf5a11ae6976641abf91b3adbbc33f62c8da195bcc3eccf99119203cf270bd1506c6620564a81f0c64197814c738
7
- data.tar.gz: 378acbd1e668f87b76ebd2db0649344e2904f8992ee4c60aff2f5cf539a145b411fc39bdca962fc4c60e81ed444919b84bf3c305a0199b09fbbd1eb1c87d5d72
6
+ metadata.gz: e1b2f9affe114ea775b4f7f7d4d2db4349e03b3ccb842885b3423c28c2b84ff6e8872b224a520654e0cef8eb353e9f0ea268e9d0dcda2666b07709f5071a0db7
7
+ data.tar.gz: 2feab585634685c45606d6e4668e52190af3fd193cf3c8468ea5b306a8834257c2944ca4c668ee5e1f9423ebfb3cf605de9d6c8052a983d57f3fe0df07d105c8
data/README.md CHANGED
@@ -1,201 +1,131 @@
1
+ # imap-backup API Documentation
2
+
1
3
  ![Version](https://img.shields.io/gem/v/imap-backup?label=Version&logo=rubygems)
2
4
  [![Build Status](https://github.com/joeyates/imap-backup/actions/workflows/main.yml/badge.svg)][CI Status]
3
5
  ![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/joeyates/b54fe758bfb405c04bef72dad293d707/raw/coverage.json)
4
6
  ![License](https://img.shields.io/github/license/joeyates/imap-backup?color=brightgreen&label=License)
5
7
  [![Stars](https://img.shields.io/github/stars/joeyates/imap-backup?style=social)][GitHub Stars]
8
+ ![Activity](https://img.shields.io/github/last-commit/joeyates/imap-backup/main)
6
9
 
7
- # imap-backup
8
-
9
- Backup, restore and migrate email accounts.
10
-
11
- # Quick Start
12
-
13
- ```sh
14
- brew install imap-backup # for macOS
15
- gem install imap-backup --no-document # for Linux
16
- imap-backup setup
17
- imap-backup
18
- ```
19
-
20
- # Modes
21
-
22
- There are two types of backups:
23
-
24
- * Keep all (the default) - progressively saves a local copy of all emails,
25
- * Mirror - adds and deletes emails from the local copy to keep it up to date with the account.
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"
26
12
 
27
- # What You Can Do with a Backup
13
+ This is the developer documentation for imap-backup's **code**.
28
14
 
29
- * Migrate - use the local copy to populate emails on another account. This is a once-only action that deletes any existing emails on the destination account.
30
- * Mirror - make a destination account match the local copy. This action can be repeated.
31
- * Restore - push the local copy back to the original account.
15
+ Usage documentation is on [GitHub](https://github.com/joeyates/imap-backup).
32
16
 
33
- See below for a [full list of commands](#commands).
17
+ You can get an overview of the program's structure from the
18
+ {file:ARCHITECTURE.md ARCHITECTURE} file.
34
19
 
35
- # Installation
20
+ The {file:CHANGELOG.md CHANGELOG} has a history of the changes to the program.
36
21
 
37
- ## Docker or Podman
22
+ # Design Goals
38
23
 
39
- If you have Docker or Podman installed, the easist way to use imap-backup
40
- is via the container image.
24
+ * Secure - use a local configuration file protected by permissions
25
+ * Restartable - calculate start point based on already downloaded messages
26
+ * Standalone - do not rely on an email client or MTA
41
27
 
42
- You'll need to choose a path on your computer where your backups will be saved,
43
- we'll use `./my-data` here.
28
+ # Repository
44
29
 
45
- If you have just one account, you can do as follows
30
+ After cloning the repo, run the following command to get
31
+ better `git blame` output:
46
32
 
47
33
  ```sh
48
- docker run -v ./my-data:/data -ti ghcr.io/joeyates/imap-backup:latest \
49
- imap-backup single backup \
50
- --email me@example.com --password mysecret --server imap.example.com \
51
- --path /data/me_example.com
34
+ git config --local blame.ignoreRevsFile .git-blame-ignore-revs
52
35
  ```
53
36
 
54
- Podman will work exactly the same.
37
+ # Testing
55
38
 
56
- If you have multiple accounts, you can create a configuration file.
39
+ ## Feature Specs
57
40
 
58
- You'll need to choose a path on your computer where your configuration will be saved,
59
- we'll use `./my-config` here.
41
+ Specs under `specs/features` are integration specs.
42
+ Some of these specs run against two local IMAP servers
43
+ controlled by Podman (or Docker) Compose.
60
44
 
61
- First, run the menu-driven setup program to configure your accounts
45
+ Start them before running the test suite
62
46
 
63
47
  ```sh
64
- docker run -ti -v ./my-config:/config -v ./my-data:/data -ti ghcr.io/joeyates/imap-backup:latest \
65
- imap-backup setup -c /config/imap-backup.json
48
+ $ podman-compose -f dev/compose.yml up -d
66
49
  ```
67
50
 
68
- Then, run the backup
51
+ or, with Docker
69
52
 
70
53
  ```sh
71
- docker run -v ./my-config:/config -v ./my-data:/data -ti ghcr.io/joeyates/imap-backup:latest \
72
- imap-backup backup -c /config/imap-backup.json
54
+ $ docker-compose -f dev/compose.yml up -d
73
55
  ```
74
56
 
75
-
76
- ## Homebrew (macOS)
77
-
78
- ![Homebrew installs](https://img.shields.io/homebrew/installs/dm/imap-backup?label=Homebrew%20installs)
79
-
80
- If you have [Homebrew](https://brew.sh/), do this:
57
+ Then, run all specs
81
58
 
82
59
  ```sh
83
- brew install imap-backup
60
+ $ rspec
84
61
  ```
85
62
 
86
- ## As a Ruby Gem
63
+ To exclude container-based tests
87
64
 
88
65
  ```sh
89
- gem install imap-backup --no-document
66
+ $ rspec --tag ~container
90
67
  ```
91
68
 
92
- If that doesn't work, see the [detailed installation instructions](docs/installation/rubygem.md).
93
-
94
- ## From Source Code
95
-
96
- If you want to use imap-backup directly from the source code, see [here](docs/installation/source.md).
97
-
98
- # Setup
99
-
100
- Normally you will want to backup a number of email accounts.
101
- Doing so requires the creation of a config file.
102
-
103
- You do this via a menu-driven command line program:
104
-
105
- Run:
69
+ To run **just** the feature specs
106
70
 
107
71
  ```sh
108
- imap-backup setup
72
+ rspec spec/features/**/*_spec.rb
109
73
  ```
110
74
 
111
- As an alternative, if you only want to backup a single account,
112
- you can pass all the necessary parameters directly to the `single backup` command
113
- (see the [`single backup`](docs/commands/single-backup.md) docs).
114
-
115
- ## GMail
116
-
117
- To use imap-backup with GMail, Office 365 and other services that require
118
- OAuth2 authentication, you can use [email-oauth2-proxy](https://github.com/simonrob/email-oauth2-proxy).
119
- See [this blog post about using imap-backup with email-oauth2-proxy](https://joeyates.info/posts/back-up-gmail-accounts-with-imap-backup-using-email-oauth2-proxy/).
75
+ ## Full Test Run
120
76
 
121
- # Backup
122
-
123
- Manually, from the command line:
77
+ The full test run includes RSpec specs **and** Rubocop checks
124
78
 
125
79
  ```sh
126
- imap-backup
80
+ rake
127
81
  ```
128
82
 
129
- Alternatively, add it to your crontab.
83
+ # Test Debugging
130
84
 
131
- Backups can also be inspected, for example via [`local show`](docs/commands/local-show.md)
132
- and exported via [`utils export-to-thunderbird`](docs/commands/utils-export-to-thunderbird.md).
85
+ The feature specs are run 'out of process' via the Aruba gem.
86
+ In order to see debugging output from the process,
87
+ use `last_command_started.output`.
133
88
 
134
- # Commands
89
+ # Older Rubies
135
90
 
136
- * [`backup`](docs/commands/backup.md)
137
- * [`local accounts`](docs/commands/local-accounts.md)
138
- * [`local check`](docs/commands/local-check.md)
139
- * [`local folders`](docs/commands/local-folders.md)
140
- * [`local list`](docs/commands/local-list.md)
141
- * [`local show`](docs/commands/local-show.md)
142
- * [`migrate`](docs/commands/migrate.md)
143
- * [`mirror`](docs/commands/mirror.md)
144
- * [`remote folders`](docs/commands/remote-folders.md)
145
- * [`restore`](docs/commands/restore.md)
146
- * [`setup`](docs/commands/setup.md)
147
- * [`single backup`](docs/commands/single-backup.md)
148
- * [`utils export-to-thunderbird`](docs/commands/utils-export-to-thunderbird.md)
149
- * [`utils ignore-history`](docs/commands/utils-ignore-history.md)
91
+ A Containerfile is available to allow testing with all available Ruby versions,
92
+ see the README in the `dev` directory.
150
93
 
151
- For a full list of available commands, run
94
+ # Performance Specs
152
95
 
153
96
  ```sh
154
- imap-backup help
97
+ PERFORMANCE=1 rspec --order=defined
155
98
  ```
156
99
 
157
- For more information about a command, run
158
-
159
- ```sh
160
- imap-backup help COMMAND
161
- ```
100
+ Beware: the performance spec (just backup for now) takes a very
101
+ long time to run, approximately 24 hours!
162
102
 
163
- # Performance
103
+ # Access Docker imap server
164
104
 
165
- There are a couple of performance tweaks that you can use
166
- to improve backup speed.
105
+ ```ruby
106
+ require "net/imap"
107
+ require_relative "spec/features/support/30_email_server_helpers"
167
108
 
168
- These are activated via two settings:
109
+ include EmailServerHelpers
169
110
 
170
- * Global setting "Delay download writes",
171
- * Account setting "Multi-fetch size".
111
+ test_connection = test_server_connection_parameters
172
112
 
173
- See [the performance document](docs/performance.md) for more information.
113
+ test_imap = Net::IMAP.new(test_connection[:server], test_connection[:connection_options])
114
+ test_imap.login(test_connection[:username], test_connection[:password])
174
115
 
175
- # Troubleshooting
116
+ message = "From: #{test_connection[:username]}\nSubject: Some Subject\n\nHello!\n"
117
+ response = test_imap.append("INBOX", message, nil, nil)
176
118
 
177
- If you have problems:
119
+ test_imap.examine("INBOX")
120
+ uids = test_imap.uid_search(["ALL"]).sort
178
121
 
179
- 1. ensure that you have the latest release,
180
- 2. run `imap-backup` with the `-v` or `--verbose` parameter.
181
-
182
- # Development
183
-
184
- ![Activity](https://img.shields.io/github/last-commit/joeyates/imap-backup/main)
185
-
186
- See the [Development documentation](./docs/development.md) for notes
187
- on development and testing.
188
-
189
- See [the CHANGELOG](./CHANGELOG.md) for a list of changes that have been
190
- made in each release.
122
+ fetch_data_items = test_imap.uid_fetch(uids, ["BODY[]"])
123
+ ```
191
124
 
192
- * [Source Code]
193
- * [Code Documentation]
194
- * [Rubygem]
195
- * [CI Status]
125
+ # Contributing
196
126
 
197
- [Source Code]: https://github.com/joeyates/imap-backup "Source code at GitHub"
198
- [GitHub Stars]: https://github.com/joeyates/imap-backup/stargazers "GitHub Stars"
199
- [Code Documentation]: https://rubydoc.info/gems/imap-backup/frames "Code Documentation at Rubydoc.info"
200
- [Rubygem]: https://rubygems.org/gems/imap-backup "Ruby gem at rubygems.org"
201
- [CI Status]: https://github.com/joeyates/imap-backup/actions/workflows/main.yml
127
+ 1. Fork it
128
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
129
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
130
+ 4. Push to the branch (`git push origin my-new-feature`)
131
+ 5. Create new Pull Request
@@ -0,0 +1,19 @@
1
+ # Documentation
2
+
3
+ This project uses [yard](https://yardoc.org/) to generate its documentation.
4
+
5
+ # Development
6
+
7
+ Run an autoreloading document viewer
8
+
9
+ ```
10
+ yard server --reload
11
+ ```
12
+
13
+ # Coverage
14
+
15
+ See what's not documented
16
+
17
+ ```
18
+ yard stats --list-undoc
19
+ ```
data/imap-backup.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |gem|
27
27
  gem.add_runtime_dependency "os"
28
28
  gem.add_runtime_dependency "rake"
29
29
  gem.add_runtime_dependency "thor", "~> 1.1"
30
- gem.add_runtime_dependency "thunderbird", ">= 0.0.0"
30
+ gem.add_runtime_dependency "thunderbird", "0.3.0"
31
31
 
32
32
  gem.metadata = {
33
33
  "rubygems_mfa_required" => "true"
@@ -15,6 +15,8 @@ module Imap::Backup
15
15
  @refresh = refresh
16
16
  end
17
17
 
18
+ # Runs the backup
19
+ # @return [void]
18
20
  def run
19
21
  Logger.logger.info "Running backup of account: #{account.username}"
20
22
  # start the connection so we get logging messages in the right order
@@ -5,7 +5,7 @@ module Imap; end
5
5
  module Imap::Backup
6
6
  class Account; end
7
7
 
8
- # Iterates over the account folders that are to be backed up
8
+ # Enumerates over the account folders that are to be backed up
9
9
  class Account::BackupFolders
10
10
  include Enumerable
11
11
 
@@ -14,6 +14,9 @@ module Imap::Backup
14
14
  @account = account
15
15
  end
16
16
 
17
+ # Runs the enumeration
18
+ # @yieldparam folder [Account::Folder] the online folder
19
+ # @return [void]
17
20
  def each(&block)
18
21
  return enum_for(:each) if !block
19
22
 
@@ -39,6 +42,9 @@ module Imap::Backup
39
42
  names.each { |name| block.call(Account::Folder.new(client, name)) }
40
43
  end
41
44
 
45
+ # Runs a map operation over the folders
46
+ # @yieldparam folder [Account::Folder] the online folder
47
+ # @return The results of the map operation
42
48
  def map(&block)
43
49
  each.map do |folder|
44
50
  block.call(folder)
@@ -18,6 +18,7 @@ module Imap::Backup
18
18
  @server = nil
19
19
  end
20
20
 
21
+ # @return [Client::AutomaticLoginWrapper] a client for the account
21
22
  def run
22
23
  options = provider_options
23
24
  Logger.logger.debug(
@@ -12,12 +12,15 @@ module Imap::Backup
12
12
 
13
13
  # Handles access to a folder on an IMAP server
14
14
  class Account::Folder
15
+ # An error that is thrown if a requestd folder does not exist
15
16
  class FolderNotFound < StandardError; end
16
17
 
17
18
  extend Forwardable
18
19
  include RetryOnError
19
20
 
21
+ # @return [Client::Default]
20
22
  attr_reader :client
23
+ # @return [String] the name of the folder
21
24
  attr_reader :name
22
25
 
23
26
  def initialize(client, name)
@@ -26,6 +29,7 @@ module Imap::Backup
26
29
  @uid_validity = nil
27
30
  end
28
31
 
32
+ # @raise any error that occurs more than 10 times
29
33
  def exist?
30
34
  previous_level = Imap::Backup::Logger.logger.level
31
35
  previous_debug = Net::IMAP.debug
@@ -42,6 +46,8 @@ module Imap::Backup
42
46
  Net::IMAP.debug = previous_debug
43
47
  end
44
48
 
49
+ # Creates the folder on the server
50
+ # @return [void]
45
51
  def create
46
52
  return if exist?
47
53
 
@@ -50,6 +56,8 @@ module Imap::Backup
50
56
  end
51
57
  end
52
58
 
59
+ # @raise any error that occurs more than 10 times
60
+ # @return [Integer] the folder's UID validity
53
61
  def uid_validity
54
62
  @uid_validity ||=
55
63
  begin
@@ -58,6 +66,8 @@ module Imap::Backup
58
66
  end
59
67
  end
60
68
 
69
+ # @raise any error that occurs more than 10 times
70
+ # @return [Array<Integer>] the folders message UIDs
61
71
  def uids
62
72
  examine
63
73
  client.uid_search(["ALL"]).sort
@@ -75,6 +85,8 @@ module Imap::Backup
75
85
  []
76
86
  end
77
87
 
88
+ # @raise any error that occurs more than 10 times
89
+ # @return [Array<Hash>, nil] the requested messages
78
90
  def fetch_multi(uids, attr = [BODY_ATTRIBUTE, "FLAGS"])
79
91
  examine
80
92
  fetch_data_items =
@@ -96,6 +108,8 @@ module Imap::Backup
96
108
  nil
97
109
  end
98
110
 
111
+ # Uploads a message
112
+ # @return [void]
99
113
  def append(message)
100
114
  body = message.imap_body
101
115
  date = message.date&.to_time
@@ -106,17 +120,23 @@ module Imap::Backup
106
120
  end
107
121
  end
108
122
 
123
+ # Deletes multiple messages
124
+ # @return [void]
109
125
  def delete_multi(uids)
110
126
  add_flags(uids, [:Deleted])
111
127
  client.expunge
112
128
  end
113
129
 
130
+ # Sets one or more flags on a group of messages
131
+ # @return [void]
114
132
  def set_flags(uids, flags)
115
133
  client.select(utf7_encoded_name)
116
134
  flags.reject! { |f| f == :Recent }
117
135
  client.uid_store(uids, "FLAGS", flags)
118
136
  end
119
137
 
138
+ # Adds one or more flags to a group of messages
139
+ # @return [void]
120
140
  def add_flags(uids, flags)
121
141
  # Use read-write access, via `select`
122
142
  client.select(utf7_encoded_name)
@@ -124,11 +144,15 @@ module Imap::Backup
124
144
  client.uid_store(uids, "+FLAGS", flags)
125
145
  end
126
146
 
147
+ # Removes one or more flags from a group of messages
148
+ # @return [void]
127
149
  def remove_flags(uids, flags)
128
150
  client.select(utf7_encoded_name)
129
151
  client.uid_store(uids, "-FLAGS", flags)
130
152
  end
131
153
 
154
+ # Deletes all messages from the folder
155
+ # @return [void]
132
156
  def clear
133
157
  existing = uids
134
158
  return if existing.empty?
@@ -137,6 +161,8 @@ module Imap::Backup
137
161
  client.expunge
138
162
  end
139
163
 
164
+ # @raise any error that occurs more than 10 times
165
+ # @return [Array<Integer>] the UIDs of messages with the 'UNSEEN' flag
140
166
  def unseen(uids)
141
167
  messages = uids.map(&:to_s).join(",")
142
168
  examine
@@ -10,7 +10,7 @@ module Imap; end
10
10
  module Imap::Backup
11
11
  class Account; end
12
12
 
13
- # Runs a backup for a single account folder
13
+ # Implements backup for a single folder
14
14
  class Account::FolderBackup
15
15
  def initialize(account:, folder:, refresh: false)
16
16
  @account = account
@@ -18,6 +18,9 @@ module Imap::Backup
18
18
  @refresh = refresh
19
19
  end
20
20
 
21
+ # Runs the backup
22
+ # @raise [RuntimeError] if the configured download strategy is incorrect
23
+ # @return [void]
21
24
  def run
22
25
  folder_ok = folder_ok?
23
26
  return if !folder_ok
@@ -12,6 +12,9 @@ module Imap::Backup
12
12
  @account = account
13
13
  end
14
14
 
15
+ # Creates the account's base directory and sets its permissions
16
+ # @raise [RuntimeError] is the account's backup path is not set
17
+ # @return [void]
15
18
  def run
16
19
  raise "The backup path for #{account.username} is not set" if !account.local_path
17
20
 
@@ -14,13 +14,15 @@ module Imap::Backup
14
14
  @account = account
15
15
  end
16
16
 
17
+ # Runs the deletion operation
18
+ # @return [void]
17
19
  def run
18
20
  backup_folders = Account::BackupFolders.new(
19
21
  client: account.client, account: account
20
22
  )
21
23
  wanted = backup_folders.map(&:name)
22
24
  serialized_folders = Account::SerializedFolders.new(account: account)
23
- serialized_folders.each do |serializer, _folder|
25
+ serialized_folders.each_key do |serializer|
24
26
  serializer.delete if !wanted.include?(serializer.folder)
25
27
  end
26
28
  end
@@ -12,6 +12,8 @@ module Imap::Backup
12
12
  @account = account
13
13
  end
14
14
 
15
+ # Runs the restore operation
16
+ # @return [void]
15
17
  def run
16
18
  serialized_folders = Account::SerializedFolders.new(account: account)
17
19
  serialized_folders.each do |serializer, folder|
@@ -9,7 +9,7 @@ module Imap; end
9
9
  module Imap::Backup
10
10
  class Account; end
11
11
 
12
- # Enumerates over the folders that are backed up to an account
12
+ # Enumerates over an account's backed-up folders
13
13
  class Account::SerializedFolders
14
14
  include Enumerable
15
15
 
@@ -17,6 +17,10 @@ module Imap::Backup
17
17
  @account = account
18
18
  end
19
19
 
20
+ # Runs the enumeration over local serializers and remote folders
21
+ # @yieldparam serializer [Serializer] the folder's serializer
22
+ # @yieldparam folder [Account::Folder] the online folder
23
+ # @return [void]
20
24
  def each(&block)
21
25
  return enum_for(:each) if !block
22
26
 
@@ -28,6 +32,32 @@ module Imap::Backup
28
32
  end
29
33
  end
30
34
 
35
+ # Runs the enumeration over each local serializer
36
+ # @yieldparam serializer [Serializer] the folder's serializer
37
+ # @return [void]
38
+ def each_key(&block)
39
+ return enum_for(:each_key) if !block
40
+
41
+ glob.each do |path|
42
+ name = path.relative_path_from(base).to_s[0..-6]
43
+ serializer = Serializer.new(account.local_path, name)
44
+ block.call(serializer)
45
+ end
46
+ end
47
+
48
+ # Runs the enumeration over each remote folder
49
+ # @yieldparam folder [Account::Folder] the online folder
50
+ # @return [void]
51
+ def each_value(&block)
52
+ return enum_for(:each_value) if !block
53
+
54
+ glob.each do |path|
55
+ name = path.relative_path_from(base).to_s[0..-6]
56
+ folder = Account::Folder.new(account.client, name)
57
+ block.call(folder)
58
+ end
59
+ end
60
+
31
61
  private
32
62
 
33
63
  attr_reader :account