imap-backup 4.0.1 → 4.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -1
  3. data/docs/development.md +5 -12
  4. data/imap-backup.gemspec +1 -4
  5. data/lib/email/mboxrd/message.rb +6 -2
  6. data/lib/email/provider/apple_mail.rb +7 -0
  7. data/lib/email/provider/base.rb +8 -0
  8. data/lib/email/provider/fastmail.rb +7 -0
  9. data/lib/email/provider/gmail.rb +7 -0
  10. data/lib/email/provider/unknown.rb +11 -0
  11. data/lib/email/provider.rb +16 -26
  12. data/lib/imap/backup/account/connection.rb +19 -29
  13. data/lib/imap/backup/account/folder.rb +9 -10
  14. data/lib/imap/backup/account.rb +103 -0
  15. data/lib/imap/backup/cli/helpers.rb +14 -0
  16. data/lib/imap/backup/cli/local.rb +19 -25
  17. data/lib/imap/backup/cli/utils.rb +67 -10
  18. data/lib/imap/backup/client/apple_mail.rb +11 -0
  19. data/lib/imap/backup/client/default.rb +51 -0
  20. data/lib/imap/backup/configuration/account.rb +3 -1
  21. data/lib/imap/backup/configuration/connection_tester.rb +1 -1
  22. data/lib/imap/backup/configuration/store.rb +10 -5
  23. data/lib/imap/backup/downloader.rb +3 -4
  24. data/lib/imap/backup/serializer/mbox.rb +5 -0
  25. data/lib/imap/backup/serializer/mbox_store.rb +8 -8
  26. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +58 -0
  27. data/lib/imap/backup/version.rb +1 -1
  28. data/lib/imap/backup.rb +1 -0
  29. data/lib/thunderbird/install.rb +16 -0
  30. data/lib/thunderbird/local_folder.rb +65 -0
  31. data/lib/thunderbird/profile.rb +30 -0
  32. data/lib/thunderbird/profiles.rb +71 -0
  33. data/lib/thunderbird/subdirectory.rb +96 -0
  34. data/lib/thunderbird/subdirectory_placeholder.rb +21 -0
  35. data/lib/thunderbird.rb +14 -0
  36. data/spec/features/restore_spec.rb +1 -1
  37. data/spec/features/support/email_server.rb +2 -2
  38. data/spec/unit/email/provider/apple_mail_spec.rb +7 -0
  39. data/spec/unit/email/provider/base_spec.rb +11 -0
  40. data/spec/unit/email/provider/fastmail_spec.rb +7 -0
  41. data/spec/unit/email/provider/gmail_spec.rb +7 -0
  42. data/spec/unit/email/provider_spec.rb +12 -25
  43. data/spec/unit/imap/backup/account/connection_spec.rb +26 -51
  44. data/spec/unit/imap/backup/account/folder_spec.rb +22 -22
  45. data/spec/unit/imap/backup/cli/local_spec.rb +70 -0
  46. data/spec/unit/imap/backup/cli/utils_spec.rb +50 -0
  47. data/spec/unit/imap/backup/client/default_spec.rb +22 -0
  48. data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +3 -3
  49. data/spec/unit/imap/backup/configuration/store_spec.rb +25 -12
  50. data/spec/unit/imap/backup/downloader_spec.rb +1 -2
  51. metadata +68 -30
@@ -152,7 +152,7 @@ RSpec.describe "restore", type: :feature, docker: true do
152
152
  it "maintains encodings" do
153
153
  message =
154
154
  server_messages(folder).
155
- first["RFC822"]
155
+ first["BODY[]"]
156
156
 
157
157
  expect(message).to eq(server_message)
158
158
  end
@@ -1,5 +1,5 @@
1
1
  module EmailServerHelpers
2
- REQUESTED_ATTRIBUTES = %w(RFC822 FLAGS INTERNALDATE).freeze
2
+ REQUESTED_ATTRIBUTES = ["BODY[]"].freeze
3
3
  DEFAULT_EMAIL = "address@example.org".freeze
4
4
 
5
5
  def send_email(folder, options)
@@ -28,7 +28,7 @@ module EmailServerHelpers
28
28
  end
29
29
 
30
30
  def server_message_to_body(message)
31
- message["RFC822"]
31
+ message["BODY[]"]
32
32
  end
33
33
 
34
34
  def server_fetch_email(folder, uid)
@@ -0,0 +1,7 @@
1
+ describe Email::Provider::AppleMail do
2
+ describe "#host" do
3
+ it "returns host" do
4
+ expect(subject.host).to eq("imap.mail.me.com")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ describe Email::Provider::Default do
2
+ describe "#options" do
3
+ it "returns options" do
4
+ expect(subject.options).to be_a(Hash)
5
+ end
6
+
7
+ it "forces TLSv1_2" do
8
+ expect(subject.options[:ssl][:ssl_version]).to eq(:TLSv1_2)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ describe Email::Provider::Fastmail do
2
+ describe "#host" do
3
+ it "returns host" do
4
+ expect(subject.host).to eq("imap.fastmail.com")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ describe Email::Provider::GMail do
2
+ describe "#host" do
3
+ it "returns host" do
4
+ expect(subject.host).to eq("imap.gmail.com")
5
+ end
6
+ end
7
+ end
@@ -1,40 +1,27 @@
1
1
  describe Email::Provider do
2
- subject { described_class.new(:gmail) }
3
-
4
2
  describe ".for_address" do
5
3
  context "with known providers" do
6
4
  [
7
- ["gmail.com", :gmail],
8
- ["fastmail.fm", :fastmail]
9
- ].each do |domain, provider|
10
- it "recognizes #{provider}" do
5
+ ["fastmail.com", "Fastmail .com", Email::Provider::Fastmail],
6
+ ["fastmail.fm", "Fastmail .fm", Email::Provider::Fastmail],
7
+ ["gmail.com", "GMail", Email::Provider::GMail],
8
+ ["icloud.com", "Apple Mail icloud.com", Email::Provider::AppleMail],
9
+ ["mac.com", "Apple Mail mac.com", Email::Provider::AppleMail],
10
+ ["me.com", "Apple Mail me.com", Email::Provider::AppleMail]
11
+ ].each do |domain, name, klass|
12
+ it "recognizes #{name} addresses" do
11
13
  address = "foo@#{domain}"
12
- expect(described_class.for_address(address).provider).to eq(provider)
14
+ expect(described_class.for_address(address)).to be_a(klass)
13
15
  end
14
16
  end
15
17
  end
16
18
 
17
19
  context "with unknown providers" do
18
20
  it "returns a default provider" do
19
- result = described_class.for_address("foo@unknown.com").provider
20
- expect(result).to eq(:default)
21
- end
22
- end
23
- end
24
-
25
- describe "#options" do
26
- it "returns options" do
27
- expect(subject.options).to be_a(Hash)
28
- end
21
+ result = described_class.for_address("foo@unknown.com")
29
22
 
30
- it "forces TLSv1_2" do
31
- expect(subject.options[:ssl][:ssl_version]).to eq(:TLSv1_2)
32
- end
33
- end
34
-
35
- describe "#host" do
36
- it "returns host" do
37
- expect(subject.host).to eq("imap.gmail.com")
23
+ expect(result).to be_a(Email::Provider::Default)
24
+ end
38
25
  end
39
26
  end
40
27
  end
@@ -14,8 +14,10 @@ describe Imap::Backup::Account::Connection do
14
14
 
15
15
  subject { described_class.new(options) }
16
16
 
17
- let(:imap) do
18
- instance_double(Net::IMAP, authenticate: nil, login: nil, disconnect: nil)
17
+ let(:client) do
18
+ instance_double(
19
+ Imap::Backup::Client::Default, authenticate: nil, login: nil, disconnect: nil
20
+ )
19
21
  end
20
22
  let(:imap_folders) { [] }
21
23
  let(:options) do
@@ -45,15 +47,14 @@ describe Imap::Backup::Account::Connection do
45
47
  let(:new_uid_validity) { nil }
46
48
 
47
49
  before do
48
- allow(Net::IMAP).to receive(:new) { imap }
49
- allow(imap).to receive(:list).with("", "") { [root_info] }
50
- allow(imap).to receive(:list).with(ROOT_NAME, "*") { imap_folders }
50
+ allow(Imap::Backup::Client::Default).to receive(:new) { client }
51
+ allow(client).to receive(:list) { imap_folders }
51
52
  allow(Imap::Backup::Utils).to receive(:make_folder)
52
53
  end
53
54
 
54
55
  shared_examples "connects to IMAP" do
55
56
  it "logs in to the imap server" do
56
- expect(imap).to have_received(:login)
57
+ expect(client).to have_received(:login)
57
58
  end
58
59
  end
59
60
 
@@ -76,48 +77,34 @@ describe Imap::Backup::Account::Connection do
76
77
  end
77
78
  end
78
79
 
79
- describe "#imap" do
80
- let(:result) { subject.imap }
80
+ describe "#client" do
81
+ let(:result) { subject.client }
81
82
 
82
83
  it "returns the IMAP connection" do
83
- expect(result).to eq(imap)
84
+ expect(result).to eq(client)
84
85
  end
85
86
 
86
87
  it "uses the password" do
87
88
  result
88
89
 
89
- expect(imap).to have_received(:login).with(USERNAME, PASSWORD)
90
- end
91
-
92
- context "with the GMail IMAP server" do
93
- let(:server) { GMAIL_IMAP_SERVER }
94
- let(:refresh_token) { true }
95
- let(:result) { nil }
96
-
97
- context "when the password is not our copy of a GMail refresh token" do
98
- it "uses the password" do
99
- subject.imap
100
-
101
- expect(imap).to have_received(:login).with(USERNAME, PASSWORD)
102
- end
103
- end
90
+ expect(client).to have_received(:login).with(USERNAME, PASSWORD)
104
91
  end
105
92
 
106
93
  context "when the first login attempt fails" do
107
94
  before do
108
95
  outcomes = [-> { raise EOFError }, -> { true }]
109
- allow(imap).to receive(:login) { outcomes.shift.call }
96
+ allow(client).to receive(:login) { outcomes.shift.call }
110
97
  end
111
98
 
112
99
  it "retries" do
113
- subject.imap
100
+ subject.client
114
101
 
115
- expect(imap).to have_received(:login).twice
102
+ expect(client).to have_received(:login).twice
116
103
  end
117
104
  end
118
105
 
119
106
  context "when run" do
120
- before { subject.imap }
107
+ before { subject.client }
121
108
 
122
109
  include_examples "connects to IMAP"
123
110
  end
@@ -125,22 +112,12 @@ describe Imap::Backup::Account::Connection do
125
112
 
126
113
  describe "#folders" do
127
114
  let(:imap_folders) do
128
- [instance_double(Net::IMAP::MailboxList, name: BACKUP_FOLDER)]
115
+ [BACKUP_FOLDER]
129
116
  end
130
117
 
131
118
  it "returns the list of folders" do
132
119
  expect(subject.folders).to eq([BACKUP_FOLDER])
133
120
  end
134
-
135
- context "with non-ASCII folder names" do
136
- let(:imap_folders) do
137
- [instance_double(Net::IMAP::MailboxList, name: "Gel&APY-scht")]
138
- end
139
-
140
- it "converts them to UTF-8" do
141
- expect(subject.folders).to eq(["Gelöscht"])
142
- end
143
- end
144
121
  end
145
122
 
146
123
  describe "#status" do
@@ -208,9 +185,7 @@ describe Imap::Backup::Account::Connection do
208
185
  end
209
186
 
210
187
  context "without supplied config_folders" do
211
- let(:imap_folders) do
212
- [instance_double(Net::IMAP::MailboxList, name: ROOT_NAME)]
213
- end
188
+ let(:imap_folders) { [ROOT_NAME] }
214
189
 
215
190
  before do
216
191
  allow(Imap::Backup::Account::Folder).to receive(:new).
@@ -241,7 +216,7 @@ describe Imap::Backup::Account::Connection do
241
216
 
242
217
  context "when the imap server doesn't return folders" do
243
218
  let(:config_folders) { nil }
244
- let(:imap_folders) { nil }
219
+ let(:imap_folders) { [] }
245
220
 
246
221
  it "fails" do
247
222
  expect do
@@ -389,10 +364,10 @@ describe Imap::Backup::Account::Connection do
389
364
 
390
365
  describe "#reconnect" do
391
366
  context "when the IMAP connection has been used" do
392
- before { subject.imap }
367
+ before { subject.client }
393
368
 
394
369
  it "disconnects from the server" do
395
- expect(imap).to receive(:disconnect)
370
+ expect(client).to receive(:disconnect)
396
371
 
397
372
  subject.reconnect
398
373
  end
@@ -400,26 +375,26 @@ describe Imap::Backup::Account::Connection do
400
375
 
401
376
  context "when the IMAP connection has not been used" do
402
377
  it "does not disconnect from the server" do
403
- expect(imap).to_not receive(:disconnect)
378
+ expect(client).to_not receive(:disconnect)
404
379
 
405
380
  subject.reconnect
406
381
  end
407
382
  end
408
383
 
409
384
  it "causes reconnection on future access" do
410
- expect(Net::IMAP).to receive(:new)
385
+ expect(Imap::Backup::Client::Default).to receive(:new)
411
386
 
412
387
  subject.reconnect
413
- subject.imap
388
+ subject.client
414
389
  end
415
390
  end
416
391
 
417
392
  describe "#disconnect" do
418
393
  context "when the IMAP connection has been used" do
419
394
  it "disconnects from the server" do
420
- subject.imap
395
+ subject.client
421
396
 
422
- expect(imap).to receive(:disconnect)
397
+ expect(client).to receive(:disconnect)
423
398
 
424
399
  subject.disconnect
425
400
  end
@@ -427,7 +402,7 @@ describe Imap::Backup::Account::Connection do
427
402
 
428
403
  context "when the IMAP connection has not been used" do
429
404
  it "does not disconnect from the server" do
430
- expect(imap).to_not receive(:disconnect)
405
+ expect(client).to_not receive(:disconnect)
431
406
 
432
407
  subject.disconnect
433
408
  end
@@ -6,9 +6,9 @@ describe Imap::Backup::Account::Folder do
6
6
 
7
7
  subject { described_class.new(connection, FOLDER_NAME) }
8
8
 
9
- let(:imap) do
9
+ let(:client) do
10
10
  instance_double(
11
- Net::IMAP,
11
+ Imap::Backup::Client::Default,
12
12
  append: append_response,
13
13
  create: nil,
14
14
  examine: nil,
@@ -16,7 +16,7 @@ describe Imap::Backup::Account::Folder do
16
16
  )
17
17
  end
18
18
  let(:connection) do
19
- instance_double(Imap::Backup::Account::Connection, imap: imap)
19
+ instance_double(Imap::Backup::Account::Connection, client: client)
20
20
  end
21
21
  let(:missing_mailbox_data) do
22
22
  OpenStruct.new(text: "Unknown Mailbox: #{FOLDER_NAME}")
@@ -31,7 +31,7 @@ describe Imap::Backup::Account::Folder do
31
31
  describe "#uids" do
32
32
  let(:uids) { [5678, 123] }
33
33
 
34
- before { allow(imap).to receive(:uid_search) { uids } }
34
+ before { allow(client).to receive(:uid_search) { uids } }
35
35
 
36
36
  it "lists available messages" do
37
37
  expect(subject.uids).to eq(uids.reverse)
@@ -39,7 +39,7 @@ describe Imap::Backup::Account::Folder do
39
39
 
40
40
  context "with missing mailboxes" do
41
41
  before do
42
- allow(imap).to receive(:examine).
42
+ allow(client).to receive(:examine).
43
43
  with(ENCODED_FOLDER_NAME).and_raise(missing_mailbox_error)
44
44
  end
45
45
 
@@ -54,7 +54,7 @@ describe Imap::Backup::Account::Folder do
54
54
  end
55
55
 
56
56
  before do
57
- allow(imap).to receive(:examine).
57
+ allow(client).to receive(:examine).
58
58
  with(ENCODED_FOLDER_NAME).and_raise(missing_mailbox_error)
59
59
  end
60
60
 
@@ -66,19 +66,19 @@ describe Imap::Backup::Account::Folder do
66
66
 
67
67
  describe "#fetch" do
68
68
  let(:message_body) { instance_double(String, force_encoding: nil) }
69
- let(:attributes) { {"RFC822" => message_body, "other" => "xxx"} }
69
+ let(:attributes) { {"BODY[]" => message_body, "other" => "xxx"} }
70
70
  let(:fetch_data_item) do
71
71
  instance_double(Net::IMAP::FetchData, attr: attributes)
72
72
  end
73
73
 
74
- before { allow(imap).to receive(:uid_fetch) { [fetch_data_item] } }
74
+ before { allow(client).to receive(:uid_fetch) { [fetch_data_item] } }
75
75
 
76
76
  it "returns the message" do
77
- expect(subject.fetch(123)).to eq(attributes)
77
+ expect(subject.fetch(123)).to eq(message_body)
78
78
  end
79
79
 
80
80
  context "when the server responds with nothing" do
81
- before { allow(imap).to receive(:uid_fetch) { nil } }
81
+ before { allow(client).to receive(:uid_fetch) { nil } }
82
82
 
83
83
  it "is nil" do
84
84
  expect(subject.fetch(123)).to be_nil
@@ -87,7 +87,7 @@ describe Imap::Backup::Account::Folder do
87
87
 
88
88
  context "when the mailbox doesn't exist" do
89
89
  before do
90
- allow(imap).to receive(:examine).
90
+ allow(client).to receive(:examine).
91
91
  with(ENCODED_FOLDER_NAME).and_raise(missing_mailbox_error)
92
92
  end
93
93
 
@@ -96,7 +96,7 @@ describe Imap::Backup::Account::Folder do
96
96
  end
97
97
  end
98
98
 
99
- context "when the response doesn't have RFC822" do
99
+ context "when the response doesn't include 'BODY[]'" do
100
100
  let(:attributes) { {} }
101
101
 
102
102
  it "is nil" do
@@ -107,13 +107,13 @@ describe Imap::Backup::Account::Folder do
107
107
  context "when the first fetch_uid attempts fail" do
108
108
  before do
109
109
  outcomes = [-> { raise EOFError }, -> { [fetch_data_item] }]
110
- allow(imap).to receive(:uid_fetch) { outcomes.shift.call }
110
+ allow(client).to receive(:uid_fetch) { outcomes.shift.call }
111
111
  end
112
112
 
113
113
  it "retries" do
114
114
  subject.fetch(123)
115
115
 
116
- expect(imap).to have_received(:uid_fetch).twice
116
+ expect(client).to have_received(:uid_fetch).twice
117
117
  end
118
118
 
119
119
  it "succeeds" do
@@ -137,7 +137,7 @@ describe Imap::Backup::Account::Folder do
137
137
 
138
138
  context "when the folder doesn't exist" do
139
139
  before do
140
- allow(imap).to receive(:examine).
140
+ allow(client).to receive(:examine).
141
141
  with(ENCODED_FOLDER_NAME).and_raise(missing_mailbox_error)
142
142
  end
143
143
 
@@ -150,7 +150,7 @@ describe Imap::Backup::Account::Folder do
150
150
  describe "#create" do
151
151
  context "when the folder exists" do
152
152
  it "is does not create the folder" do
153
- expect(imap).to_not receive(:create)
153
+ expect(client).to_not receive(:create)
154
154
 
155
155
  subject.create
156
156
  end
@@ -158,18 +158,18 @@ describe Imap::Backup::Account::Folder do
158
158
 
159
159
  context "when the folder doesn't exist" do
160
160
  before do
161
- allow(imap).to receive(:examine).
161
+ allow(client).to receive(:examine).
162
162
  with(ENCODED_FOLDER_NAME).and_raise(missing_mailbox_error)
163
163
  end
164
164
 
165
165
  it "creates the folder" do
166
- expect(imap).to receive(:create)
166
+ expect(client).to receive(:create)
167
167
 
168
168
  subject.create
169
169
  end
170
170
 
171
171
  it "encodes the folder name" do
172
- expect(imap).to receive(:create).with(ENCODED_FOLDER_NAME)
172
+ expect(client).to receive(:create).with(ENCODED_FOLDER_NAME)
173
173
 
174
174
  subject.create
175
175
  end
@@ -185,7 +185,7 @@ describe Imap::Backup::Account::Folder do
185
185
 
186
186
  context "when the folder doesn't exist" do
187
187
  before do
188
- allow(imap).to receive(:examine).
188
+ allow(client).to receive(:examine).
189
189
  with(ENCODED_FOLDER_NAME).and_raise(missing_mailbox_error)
190
190
  end
191
191
 
@@ -211,13 +211,13 @@ describe Imap::Backup::Account::Folder do
211
211
  end
212
212
 
213
213
  it "appends the message" do
214
- expect(imap).to receive(:append)
214
+ expect(client).to receive(:append)
215
215
 
216
216
  subject.append(message)
217
217
  end
218
218
 
219
219
  it "sets the date and time" do
220
- expect(imap).to receive(:append).
220
+ expect(client).to receive(:append).
221
221
  with(anything, anything, anything, message_date)
222
222
 
223
223
  subject.append(message)
@@ -0,0 +1,70 @@
1
+ describe Imap::Backup::CLI::Local do
2
+ let(:list) do
3
+ instance_double(Imap::Backup::Configuration::List, accounts: accounts)
4
+ end
5
+ let(:accounts) { [{username: email}] }
6
+ let(:connection) do
7
+ instance_double(
8
+ Imap::Backup::Account::Connection,
9
+ local_folders: local_folders
10
+ )
11
+ end
12
+ let(:local_folders) { [[serializer, folder]] }
13
+ let(:folder) { instance_double(Imap::Backup::Account::Folder, name: "bar") }
14
+ let(:serializer) do
15
+ instance_double(
16
+ Imap::Backup::Serializer::Mbox,
17
+ uids: uids,
18
+ each_message: [[123, message]]
19
+ )
20
+ end
21
+ let(:uids) { ["123"] }
22
+ let(:message) do
23
+ instance_double(
24
+ Email::Mboxrd::Message,
25
+ date: Date.today,
26
+ subject: "Ciao",
27
+ supplied_body: "Supplied"
28
+ )
29
+ end
30
+ let(:email) { "foo@example.com" }
31
+
32
+ before do
33
+ allow(Kernel).to receive(:puts)
34
+ allow(Imap::Backup::Configuration::List).to receive(:new) { list }
35
+ allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
36
+ allow(Mail).to receive(:new) { mail }
37
+ end
38
+
39
+ describe "accounts" do
40
+ it "lists configured emails" do
41
+ subject.accounts
42
+
43
+ expect(Kernel).to have_received(:puts).with(email)
44
+ end
45
+ end
46
+
47
+ describe "folders" do
48
+ it "lists downloaded folders in quotes" do
49
+ subject.folders(email)
50
+
51
+ expect(Kernel).to have_received(:puts).with(%("bar"))
52
+ end
53
+ end
54
+
55
+ describe "list" do
56
+ it "lists downloaded emails" do
57
+ subject.list(email, "bar")
58
+
59
+ expect(Kernel).to have_received(:puts).with(/Ciao/)
60
+ end
61
+ end
62
+
63
+ describe "show" do
64
+ it "prints a downloaded email" do
65
+ subject.show(email, "bar", "123")
66
+
67
+ expect(Kernel).to have_received(:puts).with("Supplied")
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,50 @@
1
+ describe Imap::Backup::CLI::Utils do
2
+ let(:list) do
3
+ instance_double(Imap::Backup::Configuration::List, accounts: accounts)
4
+ end
5
+ let(:accounts) { [{username: email}] }
6
+ let(:connection) do
7
+ instance_double(
8
+ Imap::Backup::Account::Connection,
9
+ local_folders: local_folders
10
+ )
11
+ end
12
+ let(:local_folders) { [[serializer, folder]] }
13
+ let(:folder) do
14
+ instance_double(
15
+ Imap::Backup::Account::Folder,
16
+ exist?: true,
17
+ name: "name",
18
+ uid_validity: "uid_validity",
19
+ uids: %w(123 456)
20
+ )
21
+ end
22
+ let(:serializer) do
23
+ instance_double(
24
+ Imap::Backup::Serializer::Mbox,
25
+ uids: %w(123 789),
26
+ apply_uid_validity: nil,
27
+ save: nil
28
+ )
29
+ end
30
+ let(:email) { "foo@example.com" }
31
+
32
+ before do
33
+ allow(Imap::Backup::Configuration::List).to receive(:new) { list }
34
+ allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
35
+ end
36
+
37
+ describe "ignore_history" do
38
+ it "ensures the local UID validity matches the server" do
39
+ subject.ignore_history(email)
40
+
41
+ expect(serializer).to have_received(:apply_uid_validity).with("uid_validity")
42
+ end
43
+
44
+ it "fills the local folder with fake emails" do
45
+ subject.ignore_history(email)
46
+
47
+ expect(serializer).to have_received(:save).with("456", /From: fake@email.com/)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,22 @@
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
@@ -1,7 +1,7 @@
1
1
  describe Imap::Backup::Configuration::ConnectionTester do
2
2
  describe ".test" do
3
3
  let(:connection) do
4
- instance_double(Imap::Backup::Account::Connection, imap: nil)
4
+ instance_double(Imap::Backup::Account::Connection, client: nil)
5
5
  end
6
6
 
7
7
  before do
@@ -10,7 +10,7 @@ describe Imap::Backup::Configuration::ConnectionTester do
10
10
 
11
11
  describe "call" do
12
12
  it "tries to connect" do
13
- expect(connection).to receive(:imap)
13
+ expect(connection).to receive(:client)
14
14
 
15
15
  subject.test("foo")
16
16
  end
@@ -24,7 +24,7 @@ describe Imap::Backup::Configuration::ConnectionTester do
24
24
 
25
25
  describe "failure" do
26
26
  before do
27
- allow(connection).to receive(:imap).and_raise(error)
27
+ allow(connection).to receive(:client).and_raise(error)
28
28
  end
29
29
 
30
30
  context "with no connection" do