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.
- checksums.yaml +4 -4
- data/README.md +67 -137
- data/docs/documentation.md +19 -0
- data/lib/imap/backup/account/backup.rb +2 -0
- data/lib/imap/backup/account/backup_folders.rb +7 -1
- data/lib/imap/backup/account/client_factory.rb +1 -0
- data/lib/imap/backup/account/folder.rb +26 -0
- data/lib/imap/backup/account/folder_backup.rb +4 -1
- data/lib/imap/backup/account/folder_ensurer.rb +3 -0
- data/lib/imap/backup/account/local_only_folder_deleter.rb +2 -0
- data/lib/imap/backup/account/restore.rb +2 -0
- data/lib/imap/backup/account/serialized_folders.rb +5 -1
- data/lib/imap/backup/account.rb +15 -11
- data/lib/imap/backup/cli/backup.rb +3 -0
- data/lib/imap/backup/cli/folder_enumerator.rb +6 -0
- data/lib/imap/backup/cli/helpers.rb +13 -0
- data/lib/imap/backup/cli/local/check.rb +3 -0
- data/lib/imap/backup/cli/local.rb +13 -0
- data/lib/imap/backup/cli/remote.rb +7 -0
- data/lib/imap/backup/cli/restore.rb +4 -0
- data/lib/imap/backup/cli/setup.rb +3 -0
- data/lib/imap/backup/cli/single/backup.rb +3 -0
- data/lib/imap/backup/cli/single.rb +4 -0
- data/lib/imap/backup/cli/stats.rb +3 -0
- data/lib/imap/backup/cli/transfer.rb +8 -0
- data/lib/imap/backup/cli/utils.rb +6 -0
- data/lib/imap/backup/cli.rb +8 -0
- data/lib/imap/backup/client/apple_mail.rb +2 -0
- data/lib/imap/backup/client/automatic_login_wrapper.rb +9 -1
- data/lib/imap/backup/client/default.rb +15 -4
- data/lib/imap/backup/configuration.rb +13 -0
- data/lib/imap/backup/configuration_not_found.rb +1 -0
- data/lib/imap/backup/downloader.rb +4 -0
- data/lib/imap/backup/email/mboxrd/message.rb +14 -0
- data/lib/imap/backup/email/provider/apple_mail.rb +2 -0
- data/lib/imap/backup/email/provider/base.rb +2 -0
- data/lib/imap/backup/email/provider/fastmail.rb +2 -0
- data/lib/imap/backup/email/provider/gmail.rb +2 -0
- data/lib/imap/backup/email/provider/purelymail.rb +2 -0
- data/lib/imap/backup/email/provider/unknown.rb +2 -6
- data/lib/imap/backup/email/provider.rb +5 -0
- data/lib/imap/backup/file_mode.rb +2 -0
- data/lib/imap/backup/flag_refresher.rb +4 -0
- data/lib/imap/backup/local_only_message_deleter.rb +2 -0
- data/lib/imap/backup/logger.rb +18 -0
- data/lib/imap/backup/migrator.rb +3 -0
- data/lib/imap/backup/mirror/map.rb +21 -0
- data/lib/imap/backup/mirror.rb +8 -0
- data/lib/imap/backup/naming.rb +10 -1
- data/lib/imap/backup/retry_on_error.rb +9 -0
- data/lib/imap/backup/serializer/appender.rb +9 -0
- data/lib/imap/backup/serializer/delayed_metadata_serializer.rb +4 -0
- data/lib/imap/backup/serializer/folder_maker.rb +1 -0
- data/lib/imap/backup/serializer/imap.rb +38 -2
- data/lib/imap/backup/serializer/integrity_checker.rb +1 -0
- data/lib/imap/backup/serializer/mbox.rb +26 -0
- data/lib/imap/backup/serializer/message.rb +13 -0
- data/lib/imap/backup/serializer/message_enumerator.rb +10 -2
- data/lib/imap/backup/serializer/permission_checker.rb +6 -0
- data/lib/imap/backup/serializer/transaction.rb +18 -0
- data/lib/imap/backup/serializer/unused_name_finder.rb +4 -0
- data/lib/imap/backup/serializer/version2_migrator.rb +4 -0
- data/lib/imap/backup/serializer.rb +56 -2
- data/lib/imap/backup/setup/account/header.rb +6 -0
- data/lib/imap/backup/setup/account.rb +6 -0
- data/lib/imap/backup/setup/asker.rb +16 -0
- data/lib/imap/backup/setup/backup_path.rb +6 -0
- data/lib/imap/backup/setup/connection_tester.rb +5 -0
- data/lib/imap/backup/setup/email_changer.rb +6 -0
- data/lib/imap/backup/setup/folder_chooser.rb +4 -0
- data/lib/imap/backup/setup/global_options/download_strategy_chooser.rb +4 -0
- data/lib/imap/backup/setup/global_options.rb +4 -0
- data/lib/imap/backup/setup/helpers.rb +3 -0
- data/lib/imap/backup/setup.rb +5 -0
- data/lib/imap/backup/text/sanitizer.rb +9 -0
- data/lib/imap/backup/thunderbird/mailbox_exporter.rb +7 -0
- data/lib/imap/backup/uploader.rb +5 -0
- data/lib/imap/backup/version.rb +6 -1
- metadata +3 -5
- data/docs/api.md +0 -20
- data/docs/development.md +0 -110
- data/docs/migrate-server-keep-address.md +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e492fd50201bbf2424231905b4cdb6fe3d44d99fa446c624b851c9ef50eb686f
|
4
|
+
data.tar.gz: e2ed159ec5e92e7d97a685093456491afe94d34e70702d4e7a0449cf150009dd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
13
|
+
This is the developer documentation for imap-backup's **code**.
|
28
14
|
|
29
|
-
|
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
|
-
|
17
|
+
You can get an overview of the program's structure from the
|
18
|
+
{file:ARCHITECTURE.md ARCHITECTURE} file.
|
34
19
|
|
35
|
-
|
20
|
+
The {file:CHANGELOG.md CHANGELOG} has a history of the changes to the program.
|
36
21
|
|
37
|
-
|
22
|
+
# Design Goals
|
38
23
|
|
39
|
-
|
40
|
-
|
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
|
-
|
43
|
-
we'll use `./my-data` here.
|
28
|
+
# Repository
|
44
29
|
|
45
|
-
|
30
|
+
After cloning the repo, run the following command to get
|
31
|
+
better `git blame` output:
|
46
32
|
|
47
33
|
```sh
|
48
|
-
|
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
|
-
|
37
|
+
# Testing
|
55
38
|
|
56
|
-
|
39
|
+
## Feature Specs
|
57
40
|
|
58
|
-
|
59
|
-
|
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
|
-
|
45
|
+
Start them before running the test suite
|
62
46
|
|
63
47
|
```sh
|
64
|
-
|
65
|
-
imap-backup setup -c /config/imap-backup.json
|
48
|
+
$ podman-compose -f dev/compose.yml up -d
|
66
49
|
```
|
67
50
|
|
68
|
-
|
51
|
+
or, with Docker
|
69
52
|
|
70
53
|
```sh
|
71
|
-
docker
|
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
|
-
|
60
|
+
$ rspec
|
84
61
|
```
|
85
62
|
|
86
|
-
|
63
|
+
To exclude container-based tests
|
87
64
|
|
88
65
|
```sh
|
89
|
-
|
66
|
+
$ rspec --tag ~docker
|
90
67
|
```
|
91
68
|
|
92
|
-
|
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
|
-
|
72
|
+
rspec spec/features/**/*_spec.rb
|
109
73
|
```
|
110
74
|
|
111
|
-
|
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
|
-
|
122
|
-
|
123
|
-
Manually, from the command line:
|
77
|
+
The full test run includes RSpec specs **and** Rubocop checks
|
124
78
|
|
125
79
|
```sh
|
126
|
-
|
80
|
+
rake
|
127
81
|
```
|
128
82
|
|
129
|
-
|
83
|
+
# Test Debugging
|
130
84
|
|
131
|
-
|
132
|
-
|
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
|
-
#
|
89
|
+
# Older Rubies
|
135
90
|
|
136
|
-
|
137
|
-
|
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
|
-
|
94
|
+
# Performance Specs
|
152
95
|
|
153
96
|
```sh
|
154
|
-
|
97
|
+
PERFORMANCE=1 rspec --order=defined
|
155
98
|
```
|
156
99
|
|
157
|
-
|
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
|
-
#
|
103
|
+
# Access Docker imap server
|
164
104
|
|
165
|
-
|
166
|
-
|
105
|
+
```ruby
|
106
|
+
require "net/imap"
|
107
|
+
require_relative "spec/features/support/30_email_server_helpers"
|
167
108
|
|
168
|
-
|
109
|
+
include EmailServerHelpers
|
169
110
|
|
170
|
-
|
171
|
-
* Account setting "Multi-fetch size".
|
111
|
+
test_connection = test_server_connection_parameters
|
172
112
|
|
173
|
-
|
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
|
-
#
|
116
|
+
message = "From: #{test_connection[:username]}\nSubject: Some Subject\n\nHello!\n"
|
117
|
+
response = test_imap.append("INBOX", message, nil, nil)
|
176
118
|
|
177
|
-
|
119
|
+
test_imap.examine("INBOX")
|
120
|
+
uids = test_imap.uid_search(["ALL"]).sort
|
178
121
|
|
179
|
-
|
180
|
-
|
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
|
-
|
193
|
-
* [Code Documentation]
|
194
|
-
* [Rubygem]
|
195
|
-
* [CI Status]
|
125
|
+
# Contributing
|
196
126
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
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
|
+
```
|
@@ -5,7 +5,7 @@ module Imap; end
|
|
5
5
|
module Imap::Backup
|
6
6
|
class Account; end
|
7
7
|
|
8
|
-
#
|
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)
|
@@ -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
|
-
#
|
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
|
|
@@ -9,7 +9,7 @@ module Imap; end
|
|
9
9
|
module Imap::Backup
|
10
10
|
class Account; end
|
11
11
|
|
12
|
-
# Enumerates over
|
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
|
|
data/lib/imap/backup/account.rb
CHANGED
@@ -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
|
-
#
|
17
|
+
# @return [String] password of the Account
|
18
18
|
attr_reader :password
|
19
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
|