imap-backup 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +3 -0
- data/.rubocop.yml +2 -1
- data/.travis.yml +1 -1
- data/README.md +12 -0
- data/bin/imap-backup +11 -6
- data/docker-compose.yml +15 -0
- data/imap-backup.gemspec +3 -2
- data/lib/email/mboxrd/message.rb +30 -4
- data/lib/email/provider.rb +2 -2
- data/lib/imap/backup.rb +0 -1
- data/lib/imap/backup/account/connection.rb +29 -15
- data/lib/imap/backup/account/folder.rb +3 -3
- data/lib/imap/backup/configuration/account.rb +15 -12
- data/lib/imap/backup/configuration/asker.rb +3 -1
- data/lib/imap/backup/configuration/folder_chooser.rb +5 -2
- data/lib/imap/backup/configuration/list.rb +12 -9
- data/lib/imap/backup/configuration/setup.rb +5 -3
- data/lib/imap/backup/configuration/store.rb +4 -4
- data/lib/imap/backup/downloader.rb +6 -2
- data/lib/imap/backup/serializer/base.rb +2 -2
- data/lib/imap/backup/serializer/mbox.rb +16 -7
- data/lib/imap/backup/utils.rb +8 -3
- data/lib/imap/backup/version.rb +1 -1
- data/spec/features/backup_spec.rb +27 -0
- data/spec/features/helper.rb +2 -0
- data/spec/features/support/backup_directory.rb +27 -0
- data/spec/features/support/email_server.rb +40 -0
- data/spec/features/support/shared/connection_context.rb +12 -0
- data/spec/features/support/shared/message_fixtures.rb +6 -0
- data/spec/fixtures/connection.yml +7 -0
- data/spec/support/fixtures.rb +6 -0
- data/spec/unit/account/connection_spec.rb +19 -7
- data/spec/unit/account/folder_spec.rb +15 -5
- data/spec/unit/configuration/account_spec.rb +18 -8
- data/spec/unit/configuration/asker_spec.rb +6 -3
- data/spec/unit/configuration/connection_tester_spec.rb +1 -1
- data/spec/unit/configuration/folder_chooser_spec.rb +21 -11
- data/spec/unit/configuration/list_spec.rb +13 -6
- data/spec/unit/configuration/setup_spec.rb +5 -3
- data/spec/unit/configuration/store_spec.rb +13 -8
- data/spec/unit/downloader_spec.rb +3 -1
- data/spec/unit/email/mboxrd/message_spec.rb +32 -13
- data/spec/unit/email/provider_spec.rb +7 -3
- data/spec/unit/serializer/base_spec.rb +3 -2
- data/spec/unit/serializer/mbox_spec.rb +9 -6
- data/spec/unit/utils_spec.rb +15 -13
- metadata +35 -5
- data/lib/imap/backup/serializer/directory.rb +0 -43
- data/spec/unit/serializer/directory_spec.rb +0 -69
@@ -1,7 +1,7 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Imap::Backup::Serializer::Mbox do
|
4
|
-
let(:stat) { double("File::Stat", mode:
|
4
|
+
let(:stat) { double("File::Stat", mode: 0o700) }
|
5
5
|
let(:base_path) { "/base/path" }
|
6
6
|
let(:mbox_pathname) { "/base/path/my/folder.mbox" }
|
7
7
|
let(:mbox_exists) { true }
|
@@ -20,7 +20,8 @@ describe Imap::Backup::Serializer::Mbox do
|
|
20
20
|
it "creates the containing directory" do
|
21
21
|
described_class.new(base_path, "my/folder")
|
22
22
|
|
23
|
-
expect(Imap::Backup::Utils).
|
23
|
+
expect(Imap::Backup::Utils).
|
24
|
+
to have_received(:make_folder).with(base_path, "my", 0o700)
|
24
25
|
end
|
25
26
|
|
26
27
|
context "mbox and imap files" do
|
@@ -73,14 +74,16 @@ describe Imap::Backup::Serializer::Mbox do
|
|
73
74
|
context "#save" do
|
74
75
|
let(:mbox_formatted_message) { "message in mbox format" }
|
75
76
|
let(:message_uid) { "999" }
|
76
|
-
let(:message)
|
77
|
+
let(:message) do
|
78
|
+
double("Email::Mboxrd::Message", to_serialized: mbox_formatted_message)
|
79
|
+
end
|
77
80
|
let(:mbox_file) { double("File - mbox", write: nil, close: nil) }
|
78
81
|
let(:imap_file) { double("File - imap", write: nil, close: nil) }
|
79
82
|
|
80
83
|
before do
|
81
84
|
allow(Email::Mboxrd::Message).to receive(:new).and_return(message)
|
82
|
-
allow(File).to receive(:open).with(mbox_pathname, "ab")
|
83
|
-
allow(File).to receive(:open).with(imap_pathname, "ab")
|
85
|
+
allow(File).to receive(:open).with(mbox_pathname, "ab") { mbox_file }
|
86
|
+
allow(File).to receive(:open).with(imap_pathname, "ab") { imap_file }
|
84
87
|
end
|
85
88
|
|
86
89
|
it "saves the message to the mbox" do
|
@@ -97,7 +100,7 @@ describe Imap::Backup::Serializer::Mbox do
|
|
97
100
|
|
98
101
|
context "when the message causes parsing errors" do
|
99
102
|
before do
|
100
|
-
allow(message).to receive(:
|
103
|
+
allow(message).to receive(:to_serialized).and_raise(ArgumentError)
|
101
104
|
end
|
102
105
|
|
103
106
|
it "skips the message" do
|
data/spec/unit/utils_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require "spec_helper"
|
|
3
3
|
describe Imap::Backup::Utils do
|
4
4
|
let(:filename) { "foobar" }
|
5
5
|
let(:stat) { double("File::Stat", mode: mode) }
|
6
|
-
let(:mode) {
|
6
|
+
let(:mode) { 0o777 }
|
7
7
|
let(:exists) { true }
|
8
8
|
|
9
9
|
before do
|
@@ -12,13 +12,13 @@ describe Imap::Backup::Utils do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
context ".check_permissions" do
|
15
|
-
let(:requested) {
|
15
|
+
let(:requested) { 0o345 }
|
16
16
|
|
17
17
|
context "with existing files" do
|
18
18
|
[
|
19
|
-
[
|
20
|
-
[
|
21
|
-
[
|
19
|
+
[0o100, "less than the limit", true],
|
20
|
+
[0o345, "equal to the limit", true],
|
21
|
+
[0o777, "over the limit", false]
|
22
22
|
].each do |mode, description, success|
|
23
23
|
context "when permissions are #{description}" do
|
24
24
|
let(:mode) { mode }
|
@@ -29,9 +29,10 @@ describe Imap::Backup::Utils do
|
|
29
29
|
end
|
30
30
|
else
|
31
31
|
it "fails" do
|
32
|
+
message = /Permissions on '.*?' should be .*?, not .*?/
|
32
33
|
expect do
|
33
34
|
described_class.check_permissions(filename, requested)
|
34
|
-
end.to raise_error(RuntimeError,
|
35
|
+
end.to raise_error(RuntimeError, message)
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
@@ -40,7 +41,7 @@ describe Imap::Backup::Utils do
|
|
40
41
|
|
41
42
|
context "with non-existent files" do
|
42
43
|
let(:exists) { false }
|
43
|
-
let(:mode) {
|
44
|
+
let(:mode) { 0o111 }
|
44
45
|
|
45
46
|
it "succeeds" do
|
46
47
|
described_class.check_permissions(filename, requested)
|
@@ -50,10 +51,10 @@ describe Imap::Backup::Utils do
|
|
50
51
|
|
51
52
|
context ".stat" do
|
52
53
|
context "with existing files" do
|
53
|
-
let(:mode) {
|
54
|
+
let(:mode) { 0o2345 }
|
54
55
|
|
55
56
|
it "is the last 9 bits of the file mode" do
|
56
|
-
expect(described_class.stat(filename)).to eq(
|
57
|
+
expect(described_class.stat(filename)).to eq(0o345)
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
@@ -73,21 +74,22 @@ describe Imap::Backup::Utils do
|
|
73
74
|
end
|
74
75
|
|
75
76
|
it "does nothing if an empty path is supplied" do
|
76
|
-
described_class.make_folder("aaa", "",
|
77
|
+
described_class.make_folder("aaa", "", 0o222)
|
77
78
|
|
78
79
|
expect(FileUtils).to_not have_received(:mkdir_p)
|
79
80
|
end
|
80
81
|
|
81
82
|
it "creates the path" do
|
82
|
-
described_class.make_folder("/base/path", "new/folder",
|
83
|
+
described_class.make_folder("/base/path", "new/folder", 0o222)
|
83
84
|
|
84
85
|
expect(FileUtils).to have_received(:mkdir_p).with("/base/path/new/folder")
|
85
86
|
end
|
86
87
|
|
87
88
|
it "sets permissions on the path" do
|
88
|
-
described_class.make_folder("/base/path/new", "folder",
|
89
|
+
described_class.make_folder("/base/path/new", "folder", 0o222)
|
89
90
|
|
90
|
-
expect(FileUtils).
|
91
|
+
expect(FileUtils).
|
92
|
+
to have_received(:chmod).with(0o222, "/base/path/new/folder")
|
91
93
|
end
|
92
94
|
end
|
93
95
|
end
|
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: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Yates
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.4.8
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rspec
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,6 +131,7 @@ extensions: []
|
|
117
131
|
extra_rdoc_files: []
|
118
132
|
files:
|
119
133
|
- ".gitignore"
|
134
|
+
- ".rspec"
|
120
135
|
- ".rubocop.yml"
|
121
136
|
- ".travis.yml"
|
122
137
|
- Gemfile
|
@@ -124,6 +139,7 @@ files:
|
|
124
139
|
- README.md
|
125
140
|
- Rakefile
|
126
141
|
- bin/imap-backup
|
142
|
+
- docker-compose.yml
|
127
143
|
- imap-backup.gemspec
|
128
144
|
- lib/email/mboxrd/message.rb
|
129
145
|
- lib/email/provider.rb
|
@@ -139,12 +155,19 @@ files:
|
|
139
155
|
- lib/imap/backup/configuration/store.rb
|
140
156
|
- lib/imap/backup/downloader.rb
|
141
157
|
- lib/imap/backup/serializer/base.rb
|
142
|
-
- lib/imap/backup/serializer/directory.rb
|
143
158
|
- lib/imap/backup/serializer/mbox.rb
|
144
159
|
- lib/imap/backup/utils.rb
|
145
160
|
- lib/imap/backup/version.rb
|
161
|
+
- spec/features/backup_spec.rb
|
162
|
+
- spec/features/helper.rb
|
163
|
+
- spec/features/support/backup_directory.rb
|
164
|
+
- spec/features/support/email_server.rb
|
165
|
+
- spec/features/support/shared/connection_context.rb
|
166
|
+
- spec/features/support/shared/message_fixtures.rb
|
167
|
+
- spec/fixtures/connection.yml
|
146
168
|
- spec/gather_rspec_coverage.rb
|
147
169
|
- spec/spec_helper.rb
|
170
|
+
- spec/support/fixtures.rb
|
148
171
|
- spec/support/higline_test_helpers.rb
|
149
172
|
- spec/support/shared_examples/account_flagging.rb
|
150
173
|
- spec/support/silence_logging.rb
|
@@ -161,9 +184,9 @@ files:
|
|
161
184
|
- spec/unit/email/mboxrd/message_spec.rb
|
162
185
|
- spec/unit/email/provider_spec.rb
|
163
186
|
- spec/unit/serializer/base_spec.rb
|
164
|
-
- spec/unit/serializer/directory_spec.rb
|
165
187
|
- spec/unit/serializer/mbox_spec.rb
|
166
188
|
- spec/unit/utils_spec.rb
|
189
|
+
- tmp/.gitkeep
|
167
190
|
homepage: https://github.com/joeyates/imap-backup
|
168
191
|
licenses: []
|
169
192
|
metadata: {}
|
@@ -188,8 +211,16 @@ signing_key:
|
|
188
211
|
specification_version: 4
|
189
212
|
summary: Backup GMail (or other IMAP) accounts to disk
|
190
213
|
test_files:
|
214
|
+
- spec/features/backup_spec.rb
|
215
|
+
- spec/features/helper.rb
|
216
|
+
- spec/features/support/backup_directory.rb
|
217
|
+
- spec/features/support/email_server.rb
|
218
|
+
- spec/features/support/shared/connection_context.rb
|
219
|
+
- spec/features/support/shared/message_fixtures.rb
|
220
|
+
- spec/fixtures/connection.yml
|
191
221
|
- spec/gather_rspec_coverage.rb
|
192
222
|
- spec/spec_helper.rb
|
223
|
+
- spec/support/fixtures.rb
|
193
224
|
- spec/support/higline_test_helpers.rb
|
194
225
|
- spec/support/shared_examples/account_flagging.rb
|
195
226
|
- spec/support/silence_logging.rb
|
@@ -206,6 +237,5 @@ test_files:
|
|
206
237
|
- spec/unit/email/mboxrd/message_spec.rb
|
207
238
|
- spec/unit/email/provider_spec.rb
|
208
239
|
- spec/unit/serializer/base_spec.rb
|
209
|
-
- spec/unit/serializer/directory_spec.rb
|
210
240
|
- spec/unit/serializer/mbox_spec.rb
|
211
241
|
- spec/unit/utils_spec.rb
|
@@ -1,43 +0,0 @@
|
|
1
|
-
require "fileutils"
|
2
|
-
|
3
|
-
module Imap::Backup
|
4
|
-
module Serializer; end
|
5
|
-
|
6
|
-
class Serializer::Directory < Serializer::Base
|
7
|
-
def initialize(path, folder)
|
8
|
-
super
|
9
|
-
Utils.make_folder(@path, @folder, Serializer::DIRECTORY_PERMISSIONS)
|
10
|
-
end
|
11
|
-
|
12
|
-
def uids
|
13
|
-
return [] if !File.exist?(directory)
|
14
|
-
|
15
|
-
d = Dir.open(directory)
|
16
|
-
as_strings = d.map do |file|
|
17
|
-
file[/^0*(\d+).json$/, 1]
|
18
|
-
end.compact
|
19
|
-
as_strings.map(&:to_i).sort
|
20
|
-
end
|
21
|
-
|
22
|
-
def exist?(uid)
|
23
|
-
message_filename = filename(uid)
|
24
|
-
File.exist?(message_filename)
|
25
|
-
end
|
26
|
-
|
27
|
-
def save(uid, message)
|
28
|
-
message_filename = filename(uid)
|
29
|
-
File.open(message_filename, "w") { |f| f.write message.to_json }
|
30
|
-
FileUtils.chmod 0600, message_filename
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def directory
|
36
|
-
File.join(@path, @folder)
|
37
|
-
end
|
38
|
-
|
39
|
-
def filename(uid)
|
40
|
-
"#{directory}/%012u.json" % uid.to_i
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe Imap::Backup::Serializer::Directory do
|
4
|
-
let(:stat) { double("File::Stat", mode: 0700) }
|
5
|
-
let(:files) { ["00000123.json", "000001.json"] }
|
6
|
-
let(:base) { "/base/path" }
|
7
|
-
let(:folder) { "/base/path/my_folder" }
|
8
|
-
let(:folder_exists) { true }
|
9
|
-
|
10
|
-
before do
|
11
|
-
allow(FileUtils).to receive(:mkdir_p)
|
12
|
-
allow(FileUtils).to receive(:chmod)
|
13
|
-
allow(File).to receive(:stat).with(base).and_return(stat)
|
14
|
-
allow(File).to receive(:exist?).with(base).and_return(true)
|
15
|
-
allow(File).to receive(:exist?).with(folder).and_return(folder_exists)
|
16
|
-
end
|
17
|
-
|
18
|
-
subject { described_class.new(base, "my_folder") }
|
19
|
-
|
20
|
-
context "#uids" do
|
21
|
-
before do
|
22
|
-
allow(Dir).to receive(:open).with(folder).and_return(files)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "returns the backed-up uids" do
|
26
|
-
expect(subject.uids).to eq([1, 123])
|
27
|
-
end
|
28
|
-
|
29
|
-
context "if the directory does not exist" do
|
30
|
-
let(:folder_exists) { false }
|
31
|
-
|
32
|
-
it "returns an empty array" do
|
33
|
-
expect(subject.uids).to eq([])
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
context "#exist?" do
|
39
|
-
it "checks if the file exists" do
|
40
|
-
allow(File).to receive(:exist?).with(%r{/base/path/my_folder/0+123.json}).and_return(true)
|
41
|
-
|
42
|
-
expect(subject.exist?(123)).to be_truthy
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context "#save" do
|
47
|
-
let(:message) { {"RFC822" => "the body", "other" => "xxx"} }
|
48
|
-
let(:file) { double("File", write: nil) }
|
49
|
-
|
50
|
-
before do
|
51
|
-
allow(File).to receive(:exist?).with(%r{/base/path/my_folder/0+1234.json}).and_return(true)
|
52
|
-
allow(File).to receive(:open) do |&block|
|
53
|
-
block.call file
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
it "saves messages" do
|
58
|
-
subject.save("1234", message)
|
59
|
-
|
60
|
-
expect(file).to have_received(:write).with(message.to_json)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "sets file permissions" do
|
64
|
-
subject.save(1234, message)
|
65
|
-
|
66
|
-
expect(FileUtils).to have_received(:chmod).with(0600, /0+1234.json$/)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|