imap-backup 4.0.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85e081f686a106384d27ffc91cb21965832edd629da671261bda69b668776d5e
4
- data.tar.gz: 8253587491a279e76ebed2268a66b60d9aab4f517cdafadb8c9494e7c3f3648b
3
+ metadata.gz: 97ae9089aa19dee6fcf7a1c211091671a6befe882d5b664654a25d6d10e81704
4
+ data.tar.gz: 2677746ed662c457a738033224da11a40a76367e4031e7636b33391d51ee4659
5
5
  SHA512:
6
- metadata.gz: e2b3806cedfe124c286477f50690781c4593db1f3b12d53281c666d3d5771f9a42aa4cc24851fb88f9205a2f11a8e299c74a331a606de1aab056e56b753e3cf1
7
- data.tar.gz: fc96edce37dd33793d04da272f2aea087ad7a16aa409726c83d6cf453bd386e3673a75b8d4e0eee90f352fc1e9168d611865dd87f79c05ff0cf132278bf59df3
6
+ metadata.gz: 5e97ba8ab64e27924166609c1cb80e52dbfa8136b4248324a7589e143d64ebddbb415ad6c4c7a0e472732db55c717d14e08be47c7640efcb36029c80b10938ef
7
+ data.tar.gz: 2fd74f2b86946b79d07a1354a55b00444022838fcd4968a6a2f0dc15494f4c2d80d0ea06b1e0290b921e7f2242566a56fb8e9bd6bf03b5a88595871c91d08604
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
@@ -178,6 +178,7 @@ If you have problems:
178
178
  "debug": true
179
179
  }
180
180
  ```
181
+
181
182
  # Restore
182
183
 
183
184
  All missing messages are pushed to the IMAP server.
@@ -206,48 +207,7 @@ $ imap-backup status
206
207
  * Restartable - calculate start point based on already downloaded messages
207
208
  * Standalone - do not rely on an email client or MTA
208
209
 
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
210
+ # Documentation
248
211
 
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
212
+ * [Development](./docs/development.md)
213
+ * [Restore](./docs/restore.md)
@@ -0,0 +1,60 @@
1
+ # Testing
2
+
3
+ ## Integration Tests
4
+
5
+ Integration tests (feature specs) are run against a Docker image
6
+ (antespi/docker-imap-devel:latest).
7
+
8
+ In one shell, run the Docker image:
9
+
10
+ ```sh
11
+ $ docker run \
12
+ --env MAIL_ADDRESS=address@example.org \
13
+ --env MAIL_PASS=pass \
14
+ --env MAILNAME=example.org \
15
+ --publish 8993:993 \
16
+ antespi/docker-imap-devel:latest
17
+ ```
18
+
19
+ ```sh
20
+ $ rake
21
+ ```
22
+
23
+ To exclude Docker-based tests:
24
+
25
+ ```sh
26
+ rake no-docker
27
+ ```
28
+
29
+ or
30
+
31
+ ```sh
32
+ $ rspec --tag ~docker
33
+ ```
34
+
35
+ ## Access Docker imap server
36
+
37
+ ```ruby
38
+ require "net/imap"
39
+
40
+ imap = Net::IMAP.new("localhost", {port: 8993, ssl: {verify_mode: 0}})
41
+ username = "address@example.org"
42
+ imap.login(username, "pass")
43
+
44
+ message = "From: #{username}\nSubject: Some Subject\n\nHello!\n"
45
+ response = imap.append("INBOX", message, nil, nil)
46
+
47
+ imap.examine("INBOX")
48
+ uids = imap.uid_search(["ALL"]).sort
49
+
50
+ REQUESTED_ATTRIBUTES = ["RFC822", "FLAGS", "INTERNALDATE"].freeze
51
+ fetch_data_items = imap.uid_fetch(uids, REQUESTED_ATTRIBUTES)
52
+ ```
53
+
54
+ # Contributing
55
+
56
+ 1. Fork it
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 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,21 +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
 
20
+ gem.extra_rdoc_files += Dir.glob("README.md")
21
+ gem.extra_rdoc_files += Dir.glob("docs/*.md")
22
+ gem.rdoc_options = ["--main", "README.md"]
23
+
23
24
  gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
24
- gem.test_files = gem.files.grep(%r{^spec/})
25
+ gem.test_files = Dir.glob("spec/**/*{.rb,.yml}")
25
26
  gem.require_paths = ["lib"]
26
27
  gem.required_ruby_version = ">= 2.5"
27
- gem.version = Imap::Backup::VERSION
28
28
 
29
29
  gem.add_runtime_dependency "highline"
30
30
  gem.add_runtime_dependency "mail"
@@ -10,7 +10,6 @@ module Imap::Backup::CLI::Helpers
10
10
  connections = Imap::Backup::Configuration::List.new(names)
11
11
  rescue Imap::Backup::ConfigurationNotFound
12
12
  raise "imap-backup is not configured. Run `imap-backup setup`"
13
- return
14
13
  end
15
14
 
16
15
  connections.each_connection do |connection|
@@ -28,7 +28,7 @@ module Imap::Backup
28
28
  raise "#{email} is not a configured account" if !account
29
29
 
30
30
  account_connection = Imap::Backup::Account::Connection.new(account)
31
- folder_serializer, folder = account_connection.local_folders.find do |(_s, f)|
31
+ folder_serializer, _folder = account_connection.local_folders.find do |(_s, f)|
32
32
  f.name == folder_name
33
33
  end
34
34
  raise "Folder '#{folder_name}' not found" if !folder_serializer
@@ -74,9 +74,9 @@ module Imap::Backup
74
74
  folder_serializer.each_message(uid_list).each do |uid, message|
75
75
  if uid_list.count > 1
76
76
  puts <<~HEADER
77
- #{"-" * 80}
78
- #{format("| UID: %-71s |", uid)}
79
- #{"-" * 80}
77
+ #{'-' * 80}
78
+ #{format('| UID: %-71s |', uid)}
79
+ #{'-' * 80}
80
80
  HEADER
81
81
  end
82
82
  puts message.supplied_body
@@ -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
 
@@ -0,0 +1,41 @@
1
+ module Imap::Backup
2
+ class CLI::Utils < Thor
3
+ include Thor::Actions
4
+
5
+ FAKE_EMAIL = "fake@email.com"
6
+
7
+ desc "ignore-history EMAIL", "Skip downloading emails up to today for all configured folders"
8
+ def ignore_history(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
+ connection = Imap::Backup::Account::Connection.new(account)
14
+
15
+ connection.local_folders.each do |_s, f|
16
+ next if !folder.exist?
17
+ do_ignore_folder_history(connection, folder)
18
+ end
19
+ end
20
+
21
+ no_commands do
22
+ def do_ignore_folder_history(connection, folder)
23
+ serializer = Imap::Backup::Serializer::Mbox.new(connection.local_path, folder.name)
24
+ uids = folder.uids - serializer.uids
25
+ Imap::Backup.logger.info "Folder '#{folder.name}' - #{uids.length} messages"
26
+
27
+ serializer.apply_uid_validity(folder.uid_validity)
28
+
29
+ uids.each do |uid|
30
+ message = <<~MESSAGE
31
+ From: #{FAKE_EMAIL}
32
+ Subject: Message #{uid} not backed up
33
+ Skipped #{uid}
34
+ MESSAGE
35
+
36
+ serializer.save(uid, message)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -13,6 +13,7 @@ module Imap::Backup
13
13
  autoload :Restore, "imap/backup/cli/restore"
14
14
  autoload :Setup, "imap/backup/cli/setup"
15
15
  autoload :Status, "imap/backup/cli/status"
16
+ autoload :Utils, "imap/backup/cli/utils"
16
17
 
17
18
  include Helpers
18
19
 
@@ -73,7 +74,7 @@ module Imap::Backup
73
74
  Configure email accounts to back up.
74
75
  DESC
75
76
  def setup
76
- Setup.new().run
77
+ Setup.new.run
77
78
  end
78
79
 
79
80
  desc "status", "Show backup status"
@@ -87,5 +88,8 @@ module Imap::Backup
87
88
 
88
89
  desc "local SUBCOMMAND [OPTIONS]", "View local info"
89
90
  subcommand "local", Local
91
+
92
+ desc "utils SUBCOMMAND [OPTIONS]", "Various utilities"
93
+ subcommand "utils", Utils
90
94
  end
91
95
  end
@@ -3,7 +3,7 @@ module Imap; end
3
3
  module Imap::Backup
4
4
  MAJOR = 4
5
5
  MINOR = 0
6
- REVISION = 0
6
+ REVISION = 1
7
7
  PRE = nil
8
8
  VERSION = [MAJOR, MINOR, REVISION, PRE].compact.map(&:to_s).join(".")
9
9
  end
data/spec/spec_helper.rb CHANGED
@@ -15,5 +15,6 @@ SimpleCov.start do
15
15
  end
16
16
 
17
17
  require "imap/backup"
18
+ require "imap/backup/cli"
18
19
 
19
20
  silence_logging
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imap-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Yates
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-22 00:00:00.000000000 Z
11
+ date: 2021-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: highline
@@ -156,12 +156,16 @@ email:
156
156
  executables:
157
157
  - imap-backup
158
158
  extensions: []
159
- extra_rdoc_files: []
159
+ extra_rdoc_files:
160
+ - README.md
161
+ - docs/setup.md
162
+ - docs/restore.md
163
+ - docs/development.md
160
164
  files:
161
165
  - LICENSE
162
166
  - README.md
163
167
  - bin/imap-backup
164
- - docs/docker-imap.md
168
+ - docs/development.md
165
169
  - docs/restore.md
166
170
  - docs/setup.md
167
171
  - imap-backup.gemspec
@@ -178,6 +182,7 @@ files:
178
182
  - lib/imap/backup/cli/restore.rb
179
183
  - lib/imap/backup/cli/setup.rb
180
184
  - lib/imap/backup/cli/status.rb
185
+ - lib/imap/backup/cli/utils.rb
181
186
  - lib/imap/backup/configuration/account.rb
182
187
  - lib/imap/backup/configuration/asker.rb
183
188
  - lib/imap/backup/configuration/connection_tester.rb
@@ -231,7 +236,9 @@ licenses:
231
236
  - MIT
232
237
  metadata: {}
233
238
  post_install_message:
234
- rdoc_options: []
239
+ rdoc_options:
240
+ - "--main"
241
+ - README.md
235
242
  require_paths:
236
243
  - lib
237
244
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -250,35 +257,35 @@ signing_key:
250
257
  specification_version: 4
251
258
  summary: Backup GMail (or other IMAP) accounts to disk
252
259
  test_files:
253
- - spec/features/backup_spec.rb
254
- - spec/features/helper.rb
255
- - spec/features/restore_spec.rb
256
- - spec/features/support/backup_directory.rb
257
- - spec/features/support/email_server.rb
258
- - spec/features/support/shared/connection_context.rb
259
- - spec/features/support/shared/message_fixtures.rb
260
- - spec/fixtures/connection.yml
261
- - spec/gather_rspec_coverage.rb
262
260
  - spec/spec_helper.rb
263
- - spec/support/fixtures.rb
264
- - spec/support/higline_test_helpers.rb
265
- - spec/support/shared_examples/account_flagging.rb
266
- - spec/support/silence_logging.rb
267
- - spec/unit/email/mboxrd/message_spec.rb
268
- - spec/unit/email/provider_spec.rb
269
- - spec/unit/imap/backup/account/connection_spec.rb
270
- - spec/unit/imap/backup/account/folder_spec.rb
261
+ - spec/unit/imap/backup_spec.rb
271
262
  - spec/unit/imap/backup/configuration/account_spec.rb
272
- - spec/unit/imap/backup/configuration/asker_spec.rb
273
- - spec/unit/imap/backup/configuration/connection_tester_spec.rb
274
- - spec/unit/imap/backup/configuration/folder_chooser_spec.rb
275
263
  - spec/unit/imap/backup/configuration/list_spec.rb
264
+ - spec/unit/imap/backup/configuration/connection_tester_spec.rb
276
265
  - spec/unit/imap/backup/configuration/setup_spec.rb
266
+ - spec/unit/imap/backup/configuration/asker_spec.rb
267
+ - spec/unit/imap/backup/configuration/folder_chooser_spec.rb
277
268
  - spec/unit/imap/backup/configuration/store_spec.rb
278
- - spec/unit/imap/backup/downloader_spec.rb
279
- - spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb
280
269
  - spec/unit/imap/backup/serializer/mbox_spec.rb
281
270
  - spec/unit/imap/backup/serializer/mbox_store_spec.rb
271
+ - spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb
272
+ - spec/unit/imap/backup/downloader_spec.rb
282
273
  - spec/unit/imap/backup/uploader_spec.rb
274
+ - spec/unit/imap/backup/account/folder_spec.rb
275
+ - spec/unit/imap/backup/account/connection_spec.rb
283
276
  - spec/unit/imap/backup/utils_spec.rb
284
- - spec/unit/imap/backup_spec.rb
277
+ - spec/unit/email/mboxrd/message_spec.rb
278
+ - spec/unit/email/provider_spec.rb
279
+ - spec/features/backup_spec.rb
280
+ - spec/features/helper.rb
281
+ - spec/features/restore_spec.rb
282
+ - spec/features/support/email_server.rb
283
+ - spec/features/support/backup_directory.rb
284
+ - spec/features/support/shared/connection_context.rb
285
+ - spec/features/support/shared/message_fixtures.rb
286
+ - spec/support/fixtures.rb
287
+ - spec/support/silence_logging.rb
288
+ - spec/support/higline_test_helpers.rb
289
+ - spec/support/shared_examples/account_flagging.rb
290
+ - spec/fixtures/connection.yml
291
+ - spec/gather_rspec_coverage.rb
data/docs/docker-imap.md DELETED
@@ -1,18 +0,0 @@
1
- # Access Docker imap server
2
-
3
- ```ruby
4
- require "net/imap"
5
-
6
- imap = Net::IMAP.new("localhost", {port: 8993, ssl: {verify_mode: 0}})
7
- username = "address@example.org"
8
- imap.login(username, "pass")
9
-
10
- message = "From: #{username}\nSubject: Some Subject\n\nHello!\n"
11
- response = imap.append("INBOX", message, nil, nil)
12
-
13
- imap.examine("INBOX")
14
- uids = imap.uid_search(["ALL"]).sort
15
-
16
- REQUESTED_ATTRIBUTES = ["RFC822", "FLAGS", "INTERNALDATE"].freeze
17
- fetch_data_items = imap.uid_fetch(uids, REQUESTED_ATTRIBUTES)
18
- ```