imap-backup 14.4.4 → 14.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +67 -137
  3. data/docs/documentation.md +19 -0
  4. data/lib/imap/backup/account/backup.rb +2 -0
  5. data/lib/imap/backup/account/backup_folders.rb +7 -1
  6. data/lib/imap/backup/account/client_factory.rb +1 -0
  7. data/lib/imap/backup/account/folder.rb +26 -0
  8. data/lib/imap/backup/account/folder_backup.rb +4 -1
  9. data/lib/imap/backup/account/folder_ensurer.rb +3 -0
  10. data/lib/imap/backup/account/local_only_folder_deleter.rb +2 -0
  11. data/lib/imap/backup/account/restore.rb +2 -0
  12. data/lib/imap/backup/account/serialized_folders.rb +5 -1
  13. data/lib/imap/backup/account.rb +15 -11
  14. data/lib/imap/backup/cli/backup.rb +3 -0
  15. data/lib/imap/backup/cli/folder_enumerator.rb +6 -0
  16. data/lib/imap/backup/cli/helpers.rb +13 -0
  17. data/lib/imap/backup/cli/local/check.rb +3 -0
  18. data/lib/imap/backup/cli/local.rb +13 -0
  19. data/lib/imap/backup/cli/remote.rb +7 -0
  20. data/lib/imap/backup/cli/restore.rb +4 -0
  21. data/lib/imap/backup/cli/setup.rb +3 -0
  22. data/lib/imap/backup/cli/single/backup.rb +3 -0
  23. data/lib/imap/backup/cli/single.rb +4 -0
  24. data/lib/imap/backup/cli/stats.rb +3 -0
  25. data/lib/imap/backup/cli/transfer.rb +8 -0
  26. data/lib/imap/backup/cli/utils.rb +6 -0
  27. data/lib/imap/backup/cli.rb +8 -0
  28. data/lib/imap/backup/client/apple_mail.rb +2 -0
  29. data/lib/imap/backup/client/automatic_login_wrapper.rb +9 -1
  30. data/lib/imap/backup/client/default.rb +15 -4
  31. data/lib/imap/backup/configuration.rb +13 -0
  32. data/lib/imap/backup/configuration_not_found.rb +1 -0
  33. data/lib/imap/backup/downloader.rb +4 -0
  34. data/lib/imap/backup/email/mboxrd/message.rb +14 -0
  35. data/lib/imap/backup/email/provider/apple_mail.rb +2 -0
  36. data/lib/imap/backup/email/provider/base.rb +2 -0
  37. data/lib/imap/backup/email/provider/fastmail.rb +2 -0
  38. data/lib/imap/backup/email/provider/gmail.rb +2 -0
  39. data/lib/imap/backup/email/provider/purelymail.rb +2 -0
  40. data/lib/imap/backup/email/provider/unknown.rb +2 -6
  41. data/lib/imap/backup/email/provider.rb +5 -0
  42. data/lib/imap/backup/file_mode.rb +2 -0
  43. data/lib/imap/backup/flag_refresher.rb +4 -0
  44. data/lib/imap/backup/local_only_message_deleter.rb +2 -0
  45. data/lib/imap/backup/logger.rb +18 -0
  46. data/lib/imap/backup/migrator.rb +3 -0
  47. data/lib/imap/backup/mirror/map.rb +21 -0
  48. data/lib/imap/backup/mirror.rb +8 -0
  49. data/lib/imap/backup/naming.rb +10 -1
  50. data/lib/imap/backup/retry_on_error.rb +9 -0
  51. data/lib/imap/backup/serializer/appender.rb +9 -0
  52. data/lib/imap/backup/serializer/delayed_metadata_serializer.rb +4 -0
  53. data/lib/imap/backup/serializer/folder_maker.rb +1 -0
  54. data/lib/imap/backup/serializer/imap.rb +38 -2
  55. data/lib/imap/backup/serializer/integrity_checker.rb +1 -0
  56. data/lib/imap/backup/serializer/mbox.rb +26 -0
  57. data/lib/imap/backup/serializer/message.rb +13 -0
  58. data/lib/imap/backup/serializer/message_enumerator.rb +10 -2
  59. data/lib/imap/backup/serializer/permission_checker.rb +6 -0
  60. data/lib/imap/backup/serializer/transaction.rb +18 -0
  61. data/lib/imap/backup/serializer/unused_name_finder.rb +4 -0
  62. data/lib/imap/backup/serializer/version2_migrator.rb +4 -0
  63. data/lib/imap/backup/serializer.rb +56 -2
  64. data/lib/imap/backup/setup/account/header.rb +6 -0
  65. data/lib/imap/backup/setup/account.rb +6 -0
  66. data/lib/imap/backup/setup/asker.rb +16 -0
  67. data/lib/imap/backup/setup/backup_path.rb +6 -0
  68. data/lib/imap/backup/setup/connection_tester.rb +5 -0
  69. data/lib/imap/backup/setup/email_changer.rb +6 -0
  70. data/lib/imap/backup/setup/folder_chooser.rb +4 -0
  71. data/lib/imap/backup/setup/global_options/download_strategy_chooser.rb +4 -0
  72. data/lib/imap/backup/setup/global_options.rb +4 -0
  73. data/lib/imap/backup/setup/helpers.rb +3 -0
  74. data/lib/imap/backup/setup.rb +5 -0
  75. data/lib/imap/backup/text/sanitizer.rb +9 -0
  76. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +7 -0
  77. data/lib/imap/backup/uploader.rb +5 -0
  78. data/lib/imap/backup/version.rb +6 -1
  79. metadata +3 -5
  80. data/docs/api.md +0 -20
  81. data/docs/development.md +0 -110
  82. 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: e492fd50201bbf2424231905b4cdb6fe3d44d99fa446c624b851c9ef50eb686f
4
+ data.tar.gz: e2ed159ec5e92e7d97a685093456491afe94d34e70702d4e7a0449cf150009dd
5
5
  SHA512:
6
- metadata.gz: 0004c4453debba185805fdce233f450570b6bf5a11ae6976641abf91b3adbbc33f62c8da195bcc3eccf99119203cf270bd1506c6620564a81f0c64197814c738
7
- data.tar.gz: 378acbd1e668f87b76ebd2db0649344e2904f8992ee4c60aff2f5cf539a145b411fc39bdca962fc4c60e81ed444919b84bf3c305a0199b09fbbd1eb1c87d5d72
6
+ metadata.gz: d0f4acc27fa79b789c83298af7788c01e9b8c837aa5086d1675e98b7ef80abd7fe1b3decb4b36c3f586126f7d9dc54499358bc05f7e65e0de3cbc29207233188
7
+ data.tar.gz: e036ad78bff71f98012907444f5eb36c56e01f3a3a8d2f37fbb0b06f5c1850eaddd26a4be86a8581a8f25e322731eac06a25a18853ac4433a2793cbd603b8727
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 ~docker
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
+ ```
@@ -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,6 +14,8 @@ 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
@@ -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
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
 
@@ -14,10 +14,9 @@ module Imap::Backup
14
14
  # The username of the account (usually the same as the email address)
15
15
  # @return [String]
16
16
  attr_reader :username
17
- # The password of the Account
17
+ # @return [String] password of the Account
18
18
  attr_reader :password
19
- # The path where backups will be saved
20
- # @return [String]
19
+ # @return [String] the path where backups will be saved
21
20
  attr_reader :local_path
22
21
  # @overload folders
23
22
  # The list of folders that have been configured for the Account
@@ -38,6 +37,7 @@ module Imap::Backup
38
37
  attr_reader :folder_blacklist
39
38
  # Should all emails be backed up progressively, or should emails
40
39
  # which are deleted from the server be deleted locally?
40
+ # @return [Boolean]
41
41
  attr_reader :mirror_mode
42
42
  # The address of the IMAP server
43
43
  # @return [String]
@@ -61,8 +61,6 @@ module Imap::Backup
61
61
  # mark messages as '\Seen' when accessed).
62
62
  # @return [Boolean]
63
63
  attr_reader :reset_seen_flags_after_fetch
64
- # Tracks changes to the Account's attributes
65
- attr_reader :changes
66
64
 
67
65
  def initialize(options)
68
66
  @username = options[:username]
@@ -123,6 +121,7 @@ module Imap::Backup
123
121
  end
124
122
 
125
123
  # Resets the store of changes, indicating that the current state is the saved state
124
+ # @return [void]
126
125
  def clear_changes
127
126
  @changes = {}
128
127
  end
@@ -134,16 +133,12 @@ module Imap::Backup
134
133
  @marked_for_deletion = true
135
134
  end
136
135
 
137
- # Indicates whether the account has been flagged for deletion during setup
138
- #
139
- # @return [Boolean]
136
+ # @return [Boolean] whether the account has been flagged for deletion during setup
140
137
  def marked_for_deletion?
141
138
  @marked_for_deletion
142
139
  end
143
140
 
144
- # Returns all Account data for serialization
145
- #
146
- # @return [Hash]
141
+ # @return [Hash] all Account data for serialization
147
142
  def to_h
148
143
  h = {username: @username, password: @password}
149
144
  h[:local_path] = @local_path if @local_path
@@ -180,24 +175,30 @@ module Imap::Backup
180
175
  update(:local_path, value)
181
176
  end
182
177
 
178
+ # @raise [RuntimeError] if the supplied value is not an Array
179
+ # @return [void]
183
180
  def folders=(value)
184
181
  raise "folders must be an Array" if !value.is_a?(Array)
185
182
 
186
183
  update(:folders, value)
187
184
  end
188
185
 
186
+ # @return [void]
189
187
  def folder_blacklist=(value)
190
188
  update(:folder_blacklist, value)
191
189
  end
192
190
 
191
+ # @return [void]
193
192
  def mirror_mode=(value)
194
193
  update(:mirror_mode, value)
195
194
  end
196
195
 
196
+ # @return [void]
197
197
  def server=(value)
198
198
  update(:server, value)
199
199
  end
200
200
 
201
+ # @return [void]
201
202
  def connection_options=(value)
202
203
  parsed =
203
204
  if value == ""
@@ -232,12 +233,15 @@ module Imap::Backup
232
233
  update(:multi_fetch_size, parsed)
233
234
  end
234
235
 
236
+ # @return [void]
235
237
  def reset_seen_flags_after_fetch=(value)
236
238
  update(:reset_seen_flags_after_fetch, value)
237
239
  end
238
240
 
239
241
  private
240
242
 
243
+ attr_reader :changes
244
+
241
245
  def update(field, value)
242
246
  key = :"@#{field}"
243
247
  if changes[field]
@@ -10,6 +10,7 @@ module Imap; end
10
10
  module Imap::Backup
11
11
  class CLI < Thor; end
12
12
 
13
+ # Runs backups of configured accounts
13
14
  class CLI::Backup < Thor
14
15
  include Thor::Actions
15
16
  include CLI::Helpers
@@ -19,6 +20,8 @@ module Imap::Backup
19
20
  @options = options
20
21
  end
21
22
 
23
+ # @!method run
24
+ # @return [void]
22
25
  no_commands do
23
26
  def run
24
27
  config = load_config(**options)
@@ -9,6 +9,7 @@ module Imap; end
9
9
  module Imap::Backup
10
10
  class CLI < Thor; end
11
11
 
12
+ # Implements a folder enumerator for backed-up accounts
12
13
  class CLI::FolderEnumerator
13
14
  def initialize(
14
15
  destination:,
@@ -26,6 +27,11 @@ module Imap::Backup
26
27
  @source_prefix = source_prefix
27
28
  end
28
29
 
30
+ # Enumerates backed-up folders
31
+ # When called without a block, returns an Enumerator
32
+ # @yieldparam serializer [Serializer] the folder's serializer
33
+ # @yieldparam folder [Account::Folder] the online folder
34
+ # @return [Enumerator, void]
29
35
  def each
30
36
  return enum_for(:each) if !block_given?
31
37