imap-backup 6.0.0.rc2 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/imap-backup.gemspec +5 -1
  3. data/lib/cli_coverage.rb +11 -11
  4. data/lib/email/provider/apple_mail.rb +4 -0
  5. data/lib/email/provider/base.rb +6 -0
  6. data/lib/email/provider/purelymail.rb +11 -0
  7. data/lib/email/provider/unknown.rb +2 -0
  8. data/lib/email/provider.rb +5 -0
  9. data/lib/imap/backup/account/connection/backup_folders.rb +27 -0
  10. data/lib/imap/backup/account/connection/client_factory.rb +55 -0
  11. data/lib/imap/backup/account/connection/folder_names.rb +26 -0
  12. data/lib/imap/backup/account/connection.rb +16 -96
  13. data/lib/imap/backup/account/folder.rb +31 -9
  14. data/lib/imap/backup/account.rb +15 -6
  15. data/lib/imap/backup/cli/backup.rb +1 -3
  16. data/lib/imap/backup/cli/helpers.rb +24 -22
  17. data/lib/imap/backup/cli/local.rb +20 -13
  18. data/lib/imap/backup/cli/migrate.rb +4 -10
  19. data/lib/imap/backup/cli/restore.rb +8 -7
  20. data/lib/imap/backup/cli/setup.rb +10 -8
  21. data/lib/imap/backup/cli/stats.rb +78 -0
  22. data/lib/imap/backup/cli/status.rb +2 -2
  23. data/lib/imap/backup/cli/utils.rb +4 -6
  24. data/lib/imap/backup/cli.rb +24 -3
  25. data/lib/imap/backup/configuration.rb +9 -11
  26. data/lib/imap/backup/downloader.rb +75 -31
  27. data/lib/imap/backup/migrator.rb +5 -5
  28. data/lib/imap/backup/sanitizer.rb +3 -2
  29. data/lib/imap/backup/serializer/appender.rb +49 -0
  30. data/lib/imap/backup/serializer/imap.rb +27 -3
  31. data/lib/imap/backup/serializer/mbox.rb +18 -2
  32. data/lib/imap/backup/serializer/message_enumerator.rb +29 -0
  33. data/lib/imap/backup/serializer/unused_name_finder.rb +25 -0
  34. data/lib/imap/backup/serializer.rb +64 -84
  35. data/lib/imap/backup/setup/account/header.rb +81 -0
  36. data/lib/imap/backup/setup/account.rb +28 -91
  37. data/lib/imap/backup/setup/asker.rb +4 -15
  38. data/lib/imap/backup/setup/backup_path.rb +45 -0
  39. data/lib/imap/backup/setup/email.rb +45 -0
  40. data/lib/imap/backup/setup/folder_chooser.rb +3 -3
  41. data/lib/imap/backup/setup/helpers.rb +1 -1
  42. data/lib/imap/backup/setup.rb +7 -6
  43. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +39 -20
  44. data/lib/imap/backup/uploader.rb +46 -8
  45. data/lib/imap/backup/utils.rb +1 -1
  46. data/lib/imap/backup/version.rb +2 -2
  47. data/lib/imap/backup.rb +0 -1
  48. metadata +32 -134
  49. data/spec/features/backup_spec.rb +0 -100
  50. data/spec/features/configuration/minimal_configuration.rb +0 -15
  51. data/spec/features/configuration/missing_configuration.rb +0 -14
  52. data/spec/features/folders_spec.rb +0 -36
  53. data/spec/features/helper.rb +0 -2
  54. data/spec/features/local/list_accounts_spec.rb +0 -12
  55. data/spec/features/local/list_emails_spec.rb +0 -21
  56. data/spec/features/local/list_folders_spec.rb +0 -21
  57. data/spec/features/local/show_an_email_spec.rb +0 -34
  58. data/spec/features/migrate_spec.rb +0 -35
  59. data/spec/features/remote/list_account_folders_spec.rb +0 -16
  60. data/spec/features/restore_spec.rb +0 -162
  61. data/spec/features/status_spec.rb +0 -43
  62. data/spec/features/support/aruba.rb +0 -78
  63. data/spec/features/support/backup_directory.rb +0 -43
  64. data/spec/features/support/email_server.rb +0 -110
  65. data/spec/features/support/shared/connection_context.rb +0 -14
  66. data/spec/features/support/shared/message_fixtures.rb +0 -16
  67. data/spec/fixtures/connection.yml +0 -7
  68. data/spec/spec_helper.rb +0 -15
  69. data/spec/support/fixtures.rb +0 -11
  70. data/spec/support/higline_test_helpers.rb +0 -8
  71. data/spec/support/silence_logging.rb +0 -7
  72. data/spec/unit/email/mboxrd/message_spec.rb +0 -177
  73. data/spec/unit/email/provider/apple_mail_spec.rb +0 -7
  74. data/spec/unit/email/provider/base_spec.rb +0 -11
  75. data/spec/unit/email/provider/fastmail_spec.rb +0 -7
  76. data/spec/unit/email/provider/gmail_spec.rb +0 -7
  77. data/spec/unit/email/provider_spec.rb +0 -27
  78. data/spec/unit/imap/backup/account/connection_spec.rb +0 -433
  79. data/spec/unit/imap/backup/account/folder_spec.rb +0 -261
  80. data/spec/unit/imap/backup/account_spec.rb +0 -246
  81. data/spec/unit/imap/backup/cli/accounts_spec.rb +0 -58
  82. data/spec/unit/imap/backup/cli/backup_spec.rb +0 -19
  83. data/spec/unit/imap/backup/cli/folders_spec.rb +0 -39
  84. data/spec/unit/imap/backup/cli/helpers_spec.rb +0 -87
  85. data/spec/unit/imap/backup/cli/local_spec.rb +0 -100
  86. data/spec/unit/imap/backup/cli/migrate_spec.rb +0 -80
  87. data/spec/unit/imap/backup/cli/restore_spec.rb +0 -67
  88. data/spec/unit/imap/backup/cli/setup_spec.rb +0 -17
  89. data/spec/unit/imap/backup/cli/utils_spec.rb +0 -125
  90. data/spec/unit/imap/backup/cli_spec.rb +0 -93
  91. data/spec/unit/imap/backup/client/apple_mail_spec.rb +0 -9
  92. data/spec/unit/imap/backup/client/default_spec.rb +0 -22
  93. data/spec/unit/imap/backup/configuration_spec.rb +0 -238
  94. data/spec/unit/imap/backup/downloader_spec.rb +0 -96
  95. data/spec/unit/imap/backup/logger_spec.rb +0 -48
  96. data/spec/unit/imap/backup/migrator_spec.rb +0 -58
  97. data/spec/unit/imap/backup/sanitizer_spec.rb +0 -42
  98. data/spec/unit/imap/backup/serializer/directory_spec.rb +0 -37
  99. data/spec/unit/imap/backup/serializer/imap_spec.rb +0 -218
  100. data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +0 -45
  101. data/spec/unit/imap/backup/serializer/mbox_spec.rb +0 -101
  102. data/spec/unit/imap/backup/serializer_spec.rb +0 -296
  103. data/spec/unit/imap/backup/setup/account_spec.rb +0 -461
  104. data/spec/unit/imap/backup/setup/asker_spec.rb +0 -137
  105. data/spec/unit/imap/backup/setup/connection_tester_spec.rb +0 -51
  106. data/spec/unit/imap/backup/setup/folder_chooser_spec.rb +0 -146
  107. data/spec/unit/imap/backup/setup/helpers_spec.rb +0 -15
  108. data/spec/unit/imap/backup/setup_spec.rb +0 -301
  109. data/spec/unit/imap/backup/thunderbird/mailbox_exporter_spec.rb +0 -116
  110. data/spec/unit/imap/backup/uploader_spec.rb +0 -54
  111. data/spec/unit/imap/backup/utils_spec.rb +0 -92
  112. data/spec/unit/retry_on_error_spec.rb +0 -34
@@ -1,100 +0,0 @@
1
- describe Imap::Backup::CLI::Local do
2
- let(:accounts) do
3
- instance_double(
4
- Imap::Backup::CLI::Accounts,
5
- find: ->(&block) { [account].find { |a| block.call(a) } }
6
- )
7
- end
8
- let(:account) do
9
- instance_double(
10
- Imap::Backup::Account,
11
- username: email,
12
- marked_for_deletion?: false,
13
- modified?: false
14
- )
15
- end
16
- let(:connection) do
17
- instance_double(
18
- Imap::Backup::Account::Connection,
19
- local_folders: local_folders
20
- )
21
- end
22
- let(:local_folders) { [[serializer, folder]] }
23
- let(:folder) { instance_double(Imap::Backup::Account::Folder, name: "bar") }
24
- let(:serializer) do
25
- instance_double(
26
- Imap::Backup::Serializer,
27
- uids: uids,
28
- each_message: each_message
29
- )
30
- end
31
- let(:uids) { ["123"] }
32
- let(:each_message) { [[123, message]] }
33
- let(:message) do
34
- instance_double(
35
- Email::Mboxrd::Message,
36
- date: Date.today,
37
- subject: message_subject,
38
- supplied_body: "Supplied"
39
- )
40
- end
41
- let(:message_subject) { "Ciao" }
42
- let(:email) { "foo@example.com" }
43
-
44
- before do
45
- allow(Kernel).to receive(:puts)
46
- allow(Imap::Backup::CLI::Accounts).to receive(:new) { accounts }
47
- allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
48
- allow(Mail).to receive(:new) { mail }
49
- allow(accounts).to receive(:each).and_yield(account)
50
- end
51
-
52
- describe "accounts" do
53
- it "lists configured emails" do
54
- subject.accounts
55
-
56
- expect(Kernel).to have_received(:puts).with(email)
57
- end
58
- end
59
-
60
- describe "folders" do
61
- it "lists downloaded folders in quotes" do
62
- subject.folders(email)
63
-
64
- expect(Kernel).to have_received(:puts).with(%("bar"))
65
- end
66
- end
67
-
68
- describe "list" do
69
- before { subject.list(email, "bar") }
70
-
71
- it "lists downloaded emails" do
72
- expect(Kernel).to have_received(:puts).with(/Ciao/)
73
- end
74
-
75
- context "when the subject line is too long" do
76
- let(:message_subject) { "A" * 70 }
77
-
78
- it "is shortened" do
79
- expect(Kernel).to have_received(:puts).with(/\sA{57}\.\.\./)
80
- end
81
- end
82
- end
83
-
84
- describe "show" do
85
- before { subject.show(email, "bar", uids.join(",")) }
86
-
87
- it "prints a downloaded email" do
88
- expect(Kernel).to have_received(:puts).with("Supplied")
89
- end
90
-
91
- context "when more than one email is requested" do
92
- let(:uids) { %w(123 456) }
93
- let(:each_message) { [[123, message], [456, message]] }
94
-
95
- it "prints a header" do
96
- expect(Kernel).to have_received(:puts).with(/\| UID: 123 /)
97
- end
98
- end
99
- end
100
- end
@@ -1,80 +0,0 @@
1
- module Imap::Backup
2
- describe CLI::Migrate do
3
- subject { described_class.new(source, destination, **options) }
4
-
5
- let(:source) { "source" }
6
- let(:destination) { "destination" }
7
- let(:options) { {} }
8
- let(:config) { instance_double(Configuration, accounts: [account1, account2]) }
9
- let(:account1) { instance_double(Account, username: "source", local_path: "path") }
10
- let(:account2) { instance_double(Account, username: "destination", connection: connection) }
11
- let(:connection) { instance_double(Account::Connection) }
12
- let(:migrator) { instance_double(Migrator, run: nil) }
13
- let(:imap_pathname) { Pathname.new("path/foo.imap") }
14
-
15
- before do
16
- allow(Configuration).to receive(:new) { config }
17
- allow(Pathname).to receive(:glob).and_yield(imap_pathname)
18
- allow(Migrator).to receive(:new) { migrator }
19
- allow(Account::Folder).to receive(:new).and_call_original
20
- end
21
-
22
- it "migrates each folder" do
23
- subject.run
24
-
25
- expect(migrator).to have_received(:run)
26
- end
27
-
28
- context "when source and destination emails are the same" do
29
- let(:destination) { "source" }
30
-
31
- it "fails" do
32
- expect do
33
- subject.run
34
- end.to raise_error(RuntimeError, /cannot be the same/)
35
- end
36
- end
37
-
38
- context "when the source account is not found" do
39
- let(:source) { "unknown" }
40
-
41
- it "fails" do
42
- expect do
43
- subject.run
44
- end.to raise_error(RuntimeError, /does not exist/)
45
- end
46
- end
47
-
48
- context "when the destination account is not found" do
49
- let(:destination) { "unknown" }
50
-
51
- it "fails" do
52
- expect do
53
- subject.run
54
- end.to raise_error(RuntimeError, /does not exist/)
55
- end
56
- end
57
-
58
- context "when source_prefix is supplied" do
59
- let(:options) { {source_prefix: "src/"} }
60
- let(:imap_pathname) { Pathname.new("path/src/foo.imap") }
61
-
62
- it "removes the prefix" do
63
- subject.run
64
-
65
- expect(Account::Folder).to have_received(:new).with(anything, "foo")
66
- end
67
- end
68
-
69
- context "when destination_prefix is supplied" do
70
- let(:options) { {destination_prefix: "dest/"} }
71
- let(:imap_pathname) { Pathname.new("path/foo.imap") }
72
-
73
- it "removes the prefix" do
74
- subject.run
75
-
76
- expect(Account::Folder).to have_received(:new).with(anything, "dest/foo")
77
- end
78
- end
79
- end
80
- end
@@ -1,67 +0,0 @@
1
- # rubocop:disable RSpec/SubjectStub
2
- module Imap::Backup
3
- describe CLI::Restore do
4
- subject { described_class.new(email, options) }
5
-
6
- let(:connection) { instance_double(Account::Connection, restore: nil) }
7
-
8
- describe "#run" do
9
- context "when an email is provided" do
10
- let(:email) { "email" }
11
- let(:options) { {} }
12
-
13
- before do
14
- allow(subject).to receive(:connection).with(email) { connection }
15
-
16
- subject.run
17
- end
18
-
19
- it "runs restore on the account" do
20
- expect(connection).to have_received(:restore)
21
- end
22
- end
23
-
24
- context "when neither an email nor a list of account names is provided" do
25
- let(:email) { nil }
26
- let(:options) { {} }
27
-
28
- before do
29
- allow(subject).to receive(:each_connection).with([]).and_yield(connection)
30
-
31
- subject.run
32
- end
33
-
34
- it "runs restore on each account" do
35
- expect(connection).to have_received(:restore)
36
- end
37
- end
38
-
39
- context "when an email and a list of account names is provided" do
40
- let(:email) { "email" }
41
- let(:options) { {accounts: "email2"} }
42
-
43
- it "fails" do
44
- expect do
45
- subject.run
46
- end.to raise_error(RuntimeError, /Pass either an email or the --accounts option/)
47
- end
48
- end
49
-
50
- context "when just a list of account names is provided" do
51
- let(:email) { nil }
52
- let(:options) { {accounts: "email2"} }
53
-
54
- before do
55
- allow(subject).to receive(:each_connection).with(["email2"]).and_yield(connection)
56
-
57
- subject.run
58
- end
59
-
60
- it "runs restore on each account" do
61
- expect(connection).to have_received(:restore)
62
- end
63
- end
64
- end
65
- end
66
- end
67
- # rubocop:enable RSpec/SubjectStub
@@ -1,17 +0,0 @@
1
- module Imap::Backup
2
- describe CLI::Setup do
3
- subject { described_class.new }
4
-
5
- let(:setup) { instance_double(Setup, run: nil) }
6
-
7
- before do
8
- allow(Setup).to receive(:new) { setup }
9
- end
10
-
11
- it "reruns the setup process" do
12
- subject.run
13
-
14
- expect(setup).to have_received(:run)
15
- end
16
- end
17
- end
@@ -1,125 +0,0 @@
1
- module Imap::Backup
2
- describe CLI::Utils do
3
- let(:accounts) do
4
- instance_double(
5
- CLI::Accounts,
6
- find: ->(&block) { [account].find { |a| block.call(a) } }
7
- )
8
- end
9
- let(:account) { instance_double(Account, username: email) }
10
- let(:connection) do
11
- instance_double(
12
- Account::Connection,
13
- account: account,
14
- backup_folders: [folder],
15
- local_folders: ["folder"]
16
- )
17
- end
18
- let(:account) do
19
- instance_double(
20
- Account,
21
- local_path: "path"
22
- )
23
- end
24
- let(:folder) do
25
- instance_double(
26
- Account::Folder,
27
- exist?: true,
28
- name: "name",
29
- uid_validity: "uid_validity",
30
- uids: %w(123 456)
31
- )
32
- end
33
- let(:serializer) do
34
- instance_double(
35
- Serializer,
36
- uids: %w(123 789),
37
- apply_uid_validity: nil,
38
- append: nil
39
- )
40
- end
41
- let(:exporter) { instance_double(Thunderbird::MailboxExporter, run: nil) }
42
- let(:email) { "foo@example.com" }
43
-
44
- before do
45
- allow(CLI::Accounts).to receive(:new) { accounts }
46
- allow(Account::Connection).to receive(:new) { connection }
47
- allow(Serializer).to receive(:new) { serializer }
48
- end
49
-
50
- describe "#export_to_thunderbird" do
51
- let(:command) { subject.export_to_thunderbird(email) }
52
- let(:options) { {} }
53
- let(:profiles) { instance_double(Thunderbird::Profiles, installs: installs, profile: named_profile) }
54
- let(:installs) { [install1] }
55
- let(:install1) { instance_double(Thunderbird::Install, default: default_install) }
56
- let(:default_install) { "default" }
57
- let(:named_profile) { "named" }
58
-
59
- before do
60
- allow(Thunderbird::MailboxExporter).to receive(:new) { exporter }
61
- allow(Thunderbird::Profiles).to receive(:new) { profiles }
62
- # rubocop:disable RSpec/SubjectStub
63
- allow(subject).to receive(:options) { options }
64
- # rubocop:enable RSpec/SubjectStub
65
- end
66
-
67
- context "when no profile_name is supplied" do
68
- context "when no default Thunderbird profile is found" do
69
- let(:default_install) { nil }
70
-
71
- it "fails" do
72
- expect do
73
- command
74
- end.to raise_error(RuntimeError, /Default .*? not found/)
75
- end
76
- end
77
-
78
- context "when there is more than one install" do
79
- let(:installs) { [install1, install2] }
80
- let(:install2) { instance_double(Thunderbird::Install, default: default_install) }
81
-
82
- it "fails" do
83
- expect do
84
- command
85
- end.to raise_error(RuntimeError, /multiple installs.*?supply a profile name/m)
86
- end
87
- end
88
- end
89
-
90
- context "when a profile_name is supplied" do
91
- let(:options) { {"profile" => "profile"} }
92
-
93
- context "when the supplied profile_name is not found" do
94
- let(:named_profile) { nil }
95
-
96
- it "fails" do
97
- expect do
98
- command
99
- end.to raise_error(RuntimeError, /profile 'profile' not found/)
100
- end
101
- end
102
- end
103
-
104
- it "exports the profile" do
105
- command
106
-
107
- expect(exporter).to have_received(:run)
108
- end
109
- end
110
-
111
- describe "ignore_history" do
112
- it "ensures the local UID validity matches the server" do
113
- subject.ignore_history(email)
114
-
115
- expect(serializer).to have_received(:apply_uid_validity).with("uid_validity")
116
- end
117
-
118
- it "fills the local folder with fake emails" do
119
- subject.ignore_history(email)
120
-
121
- expect(serializer).to have_received(:append).with("456", /From: fake@email.com/)
122
- end
123
- end
124
- end
125
- end
@@ -1,93 +0,0 @@
1
- module Imap::Backup
2
- RSpec.describe CLI do
3
- describe ".exit_on_failure?" do
4
- it "is true" do
5
- expect(described_class.exit_on_failure?).to be true
6
- end
7
- end
8
-
9
- describe "#backup" do
10
- let(:backup) { instance_double(CLI::Backup, run: nil) }
11
-
12
- before do
13
- allow(CLI::Backup).to receive(:new) { backup }
14
-
15
- subject.backup
16
- end
17
-
18
- it "runs Backup" do
19
- expect(backup).to have_received(:run)
20
- end
21
- end
22
-
23
- describe "#folders" do
24
- let(:folders) { instance_double(CLI::Folders, run: nil) }
25
-
26
- before do
27
- allow(CLI::Folders).to receive(:new) { folders }
28
-
29
- subject.folders
30
- end
31
-
32
- it "runs folders" do
33
- expect(folders).to have_received(:run)
34
- end
35
- end
36
-
37
- describe "#migrate" do
38
- let(:migrate) { instance_double(CLI::Migrate, run: nil) }
39
-
40
- before do
41
- allow(CLI::Migrate).to receive(:new) { migrate }
42
-
43
- subject.migrate("source", "destination")
44
- end
45
-
46
- it "runs migrate" do
47
- expect(migrate).to have_received(:run)
48
- end
49
- end
50
-
51
- describe "#restore" do
52
- let(:restore) { instance_double(CLI::Restore, run: nil) }
53
-
54
- before do
55
- allow(CLI::Restore).to receive(:new) { restore }
56
-
57
- subject.restore
58
- end
59
-
60
- it "runs restore" do
61
- expect(restore).to have_received(:run)
62
- end
63
- end
64
-
65
- describe "#setup" do
66
- let(:setup) { instance_double(CLI::Setup, run: nil) }
67
-
68
- before do
69
- allow(CLI::Setup).to receive(:new) { setup }
70
-
71
- subject.setup
72
- end
73
-
74
- it "runs setup" do
75
- expect(setup).to have_received(:run)
76
- end
77
- end
78
-
79
- describe "#status" do
80
- let(:status) { instance_double(CLI::Status, run: nil) }
81
-
82
- before do
83
- allow(CLI::Status).to receive(:new) { status }
84
-
85
- subject.status
86
- end
87
-
88
- it "runs status" do
89
- expect(status).to have_received(:run)
90
- end
91
- end
92
- end
93
- end
@@ -1,9 +0,0 @@
1
- module Imap::Backup
2
- RSpec.describe Client::AppleMail do
3
- describe "#provider_root" do
4
- it "is an empty string" do
5
- expect(subject.provider_root).to eq("")
6
- end
7
- end
8
- end
9
- end
@@ -1,22 +0,0 @@
1
- describe Imap::Backup::Client::Default do
2
- subject { described_class.new("server", {}) }
3
-
4
- let(:imap) { instance_double(Net::IMAP, list: imap_folders) }
5
- let(:imap_folders) { [] }
6
-
7
- before do
8
- allow(Net::IMAP).to receive(:new) { imap }
9
- end
10
-
11
- describe "#list" do
12
- context "with non-ASCII folder names" do
13
- let(:imap_folders) do
14
- [instance_double(Net::IMAP::MailboxList, name: "Gel&APY-scht")]
15
- end
16
-
17
- it "converts them to UTF-8" do
18
- expect(subject.list).to eq(["Gelöscht"])
19
- end
20
- end
21
- end
22
- end