imap-backup 0.0.5 → 1.0.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.
Files changed (35) hide show
  1. data/README.md +43 -6
  2. data/bin/imap-backup +0 -1
  3. data/imap-backup.gemspec +1 -1
  4. data/lib/email/mboxrd/message.rb +37 -0
  5. data/lib/imap/backup.rb +2 -0
  6. data/lib/imap/backup/account/connection.rb +2 -4
  7. data/lib/imap/backup/account/folder.rb +0 -2
  8. data/lib/imap/backup/configuration/account.rb +0 -2
  9. data/lib/imap/backup/configuration/asker.rb +0 -2
  10. data/lib/imap/backup/configuration/folder_chooser.rb +0 -2
  11. data/lib/imap/backup/configuration/list.rb +17 -16
  12. data/lib/imap/backup/configuration/setup.rb +1 -3
  13. data/lib/imap/backup/configuration/store.rb +19 -13
  14. data/lib/imap/backup/downloader.rb +0 -2
  15. data/lib/imap/backup/serializer/base.rb +17 -0
  16. data/lib/imap/backup/serializer/directory.rb +3 -7
  17. data/lib/imap/backup/serializer/mbox.rb +96 -0
  18. data/lib/imap/backup/utils.rb +6 -3
  19. data/lib/imap/backup/version.rb +2 -2
  20. data/spec/unit/account/connection_spec.rb +12 -13
  21. data/spec/unit/account/folder_spec.rb +1 -9
  22. data/spec/unit/configuration/account_spec.rb +1 -16
  23. data/spec/unit/configuration/asker_spec.rb +1 -9
  24. data/spec/unit/configuration/connection_tester_spec.rb +1 -5
  25. data/spec/unit/configuration/folder_chooser_spec.rb +1 -7
  26. data/spec/unit/configuration/list_spec.rb +24 -20
  27. data/spec/unit/configuration/setup_spec.rb +3 -9
  28. data/spec/unit/configuration/store_spec.rb +11 -20
  29. data/spec/unit/downloader_spec.rb +1 -11
  30. data/spec/unit/email/mboxrd/message_spec.rb +51 -0
  31. data/spec/unit/serializer/base_spec.rb +19 -0
  32. data/spec/unit/serializer/directory_spec.rb +51 -74
  33. data/spec/unit/serializer/mbox_spec.rb +113 -0
  34. data/spec/unit/utils_spec.rb +3 -9
  35. metadata +29 -4
@@ -1,22 +1,18 @@
1
1
  # encoding: utf-8
2
- load File.expand_path( '../../spec_helper.rb', File.dirname(__FILE__) )
2
+ require 'spec_helper'
3
3
 
4
4
  describe Imap::Backup::Configuration::Setup do
5
-
6
5
  include HighLineTestHelpers
7
6
 
8
7
  context '#initialize' do
9
-
10
8
  it 'should not require the config file to exist' do
11
- Imap::Backup::Configuration::Store.should_receive(:new).with(false)
9
+ Imap::Backup::Configuration::Store.should_receive(:new)
12
10
 
13
11
  Imap::Backup::Configuration::Setup.new
14
12
  end
15
-
16
13
  end
17
14
 
18
15
  context '#run' do
19
-
20
16
  before :each do
21
17
  prepare_store
22
18
  @input, @output = prepare_highline
@@ -26,7 +22,7 @@ describe Imap::Backup::Configuration::Setup do
26
22
  @account1 = { :username => 'account@example.com' }
27
23
  @data = { :accounts => [ @account1 ] }
28
24
  @store = stub('Imap::Backup::Configuration::Store', :data => @data, :path => '/base/path')
29
- Imap::Backup::Configuration::Store.stub!(:new).with(false).and_return(@store)
25
+ Imap::Backup::Configuration::Store.stub!(:new).and_return(@store)
30
26
  end
31
27
 
32
28
  subject { Imap::Backup::Configuration::Setup.new }
@@ -109,8 +105,6 @@ describe Imap::Backup::Configuration::Setup do
109
105
 
110
106
  subject.run
111
107
  end
112
-
113
108
  end
114
-
115
109
  end
116
110
 
@@ -1,8 +1,7 @@
1
1
  # encoding: utf-8
2
- load File.expand_path( '../../spec_helper.rb', File.dirname(__FILE__) )
2
+ require 'spec_helper'
3
3
 
4
4
  describe Imap::Backup::Configuration::Store do
5
-
6
5
  before :all do
7
6
  @configuration_directory = Imap::Backup::Configuration::Store::CONFIGURATION_DIRECTORY
8
7
  Imap::Backup::Configuration::Store.instance_eval { remove_const :'CONFIGURATION_DIRECTORY' }
@@ -14,27 +13,25 @@ describe Imap::Backup::Configuration::Store do
14
13
  Imap::Backup::Configuration::Store::CONFIGURATION_DIRECTORY = @configuration_directory
15
14
  end
16
15
 
17
- context '#initialize' do
16
+ context '.exist?' do
17
+ it 'checks if the file exists' do
18
+ File.should_receive(:exist?).with('/base/path/config.json').and_return(true)
19
+
20
+ Imap::Backup::Configuration::Store.exist?
21
+ end
22
+ end
18
23
 
24
+ context '#initialize' do
19
25
  before :each do
20
26
  Imap::Backup::Utils.stub!(:check_permissions => nil)
21
27
  end
22
28
 
23
- it 'by default, should fail if the config file is missing' do
29
+ it 'should not fail if the configuration file is missing' do
24
30
  File.should_receive(:directory?).with('/base/path').and_return(true)
25
31
  File.should_receive(:exist?).with('/base/path/config.json').and_return(false)
26
32
 
27
33
  expect do
28
34
  Imap::Backup::Configuration::Store.new
29
- end.to raise_error(Imap::Backup::ConfigurationNotFound, /not found/)
30
- end
31
-
32
- it 'should not fail if fail_if_missing is false' do
33
- File.should_receive(:directory?).with('/base/path').and_return(true)
34
- File.should_receive(:exist?).with('/base/path/config.json').and_return(false)
35
-
36
- expect do
37
- Imap::Backup::Configuration::Store.new(false)
38
35
  end.to_not raise_error
39
36
  end
40
37
 
@@ -57,11 +54,9 @@ describe Imap::Backup::Configuration::Store do
57
54
 
58
55
  Imap::Backup::Configuration::Store.new
59
56
  end
60
-
61
57
  end
62
58
 
63
59
  context '#save' do
64
-
65
60
  before :each do
66
61
  # initialize
67
62
  File.stub!(:directory?).with('/base/path').and_return(false)
@@ -78,7 +73,7 @@ describe Imap::Backup::Configuration::Store do
78
73
  FileUtils.stub!(:chmod).with(0600, '/base/path/config.json')
79
74
  end
80
75
 
81
- subject { Imap::Backup::Configuration::Store.new(false) }
76
+ subject { Imap::Backup::Configuration::Store.new }
82
77
 
83
78
  it 'should create the config directory' do
84
79
  File.should_receive(:directory?).with('/base/path').and_return(false)
@@ -100,7 +95,6 @@ describe Imap::Backup::Configuration::Store do
100
95
  end
101
96
 
102
97
  context 'saving accounts' do
103
-
104
98
  before :each do
105
99
  # initialize
106
100
  File.stub!(:exist?).with('/base/path/config.json').and_return(true)
@@ -164,10 +158,7 @@ describe Imap::Backup::Configuration::Store do
164
158
 
165
159
  subject.save
166
160
  end
167
-
168
161
  end
169
-
170
162
  end
171
-
172
163
  end
173
164
 
@@ -1,10 +1,8 @@
1
1
  # encoding: utf-8
2
- load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
2
+ require 'spec_helper'
3
3
 
4
4
  describe Imap::Backup::Downloader do
5
-
6
5
  context 'with account and downloader' do
7
-
8
6
  before :each do
9
7
  local_path = '/base/path'
10
8
  stat = stub('File::Stat', :mode => 0700)
@@ -24,9 +22,7 @@ describe Imap::Backup::Downloader do
24
22
  subject { Imap::Backup::Downloader.new(@folder, @serializer) }
25
23
 
26
24
  context '#run' do
27
-
28
25
  context 'with folder' do
29
-
30
26
  it 'should list messages' do
31
27
  @folder.should_receive(:uids).and_return([])
32
28
 
@@ -70,16 +66,10 @@ describe Imap::Backup::Downloader do
70
66
 
71
67
  subject.run
72
68
  end
73
-
74
69
  end
75
-
76
70
  end
77
-
78
71
  end
79
-
80
72
  end
81
-
82
73
  end
83
-
84
74
  end
85
75
 
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Email::Mboxrd::Message do
6
+ let(:from) { 'me@example.com' }
7
+ let(:date) { DateTime.new(2012, 12, 13, 18, 23, 45) }
8
+ let(:message_body) { "Foo\nBar\nFrom at the beginning of the line\n>>From quoted" }
9
+ subject { Email::Mboxrd::Message.new(message_body) }
10
+
11
+ context '#to_s' do
12
+ let(:mail) do
13
+ mail = stub('Mail')
14
+ mail.stub(:from).and_return([from])
15
+ mail.stub(:date).and_return(date)
16
+ mail
17
+ end
18
+
19
+ before do
20
+ Mail.stub(:new).with(message_body).and_return(mail)
21
+ end
22
+
23
+ it 'does not modify the message' do
24
+ message_body2 = message_body.clone
25
+
26
+ message_body.should_receive(:clone).and_return(message_body2)
27
+ message_body.should_not_receive(:force_encoding).with('binary')
28
+
29
+ subject.to_s
30
+ end
31
+
32
+ it 'parses the message' do
33
+ Mail.should_receive(:new).with(message_body).and_return(mail)
34
+
35
+ subject.to_s
36
+ end
37
+
38
+ it "adds a 'From ' line at the start" do
39
+ expect(subject.to_s).to start_with('From ' + from + ' ' + date.asctime + "\n")
40
+ end
41
+
42
+ it "replaces existing 'From ' with '>From '" do
43
+ expect(subject.to_s).to include("\n>From at the beginning")
44
+ end
45
+
46
+ it "appends > before '>+From '" do
47
+ expect(subject.to_s).to include("\n>>>From quoted")
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Imap::Backup::Serializer::Base do
6
+ context '#initialize' do
7
+ let(:stat) { stub('File::Stat', :mode => 0345) }
8
+
9
+ it 'should fail if file permissions are to lax' do
10
+ File.stub!(:exist?).with('/base/path').and_return(true)
11
+ File.should_receive(:stat).with('/base/path').and_return(stat)
12
+
13
+ expect do
14
+ Imap::Backup::Serializer::Base.new('/base/path', 'my_folder')
15
+ end.to raise_error(RuntimeError, "Permissions on '/base/path' should be 0700, not 0345")
16
+ end
17
+ end
18
+ end
19
+
@@ -1,102 +1,79 @@
1
1
  # encoding: utf-8
2
-
3
- load File.expand_path('../../spec_helper.rb', File.dirname(__FILE__))
2
+ require 'spec_helper'
4
3
 
5
4
  describe Imap::Backup::Serializer::Directory do
5
+ let(:stat) { stub('File::Stat', :mode => 0700) }
6
+ let(:files) { ['00000123.json', '000001.json'] }
7
+
8
+ before do
9
+ File.stub!(:stat).with('/base/path').and_return(stat)
10
+ FileUtils.stub!(:mkdir_p).with('/base/path/my_folder')
11
+ FileUtils.stub!(:chmod).with(0700, '/base/path/my_folder')
12
+ File.stub!(:exist?).with('/base/path').and_return(true)
13
+ end
6
14
 
7
- context '#initialize' do
15
+ subject { Imap::Backup::Serializer::Directory.new('/base/path', 'my_folder') }
8
16
 
9
- it 'should fail if download path file permissions are to lax' do
10
- File.stub!(:exist?).with('/base/path').and_return(true)
11
- stat = stub('File::Stat', :mode => 0345)
12
- File.should_receive(:stat).with('/base/path').and_return(stat)
17
+ context '#uids' do
18
+ it 'should return the backed-up uids' do
19
+ File.should_receive(:exist?).with('/base/path/my_folder').and_return(true)
20
+ Dir.should_receive(:open).with('/base/path/my_folder').and_return(files)
13
21
 
14
- expect do
15
- Imap::Backup::Serializer::Directory.new('/base/path', 'my_folder')
16
- end.to raise_error(RuntimeError, "Permissions on '/base/path' should be 0700, not 0345")
22
+ subject.uids.should == [1, 123]
17
23
  end
18
24
 
19
- end
20
-
21
- context 'with object' do
25
+ it 'should return an empty Array if the directory does not exist' do
26
+ File.should_receive(:exist?).with('/base/path/my_folder').and_return(false)
22
27
 
23
- before :each do
24
- stat = stub('File::Stat', :mode => 0700)
25
- File.stub!(:stat).with('/base/path').and_return(stat)
26
- FileUtils.stub!(:mkdir_p).with('/base/path/my_folder')
27
- FileUtils.stub!(:chmod).with(0700, '/base/path/my_folder')
28
- File.stub!(:exist?).with('/base/path').and_return(true)
28
+ subject.uids.should == []
29
29
  end
30
+ end
30
31
 
31
- subject { Imap::Backup::Serializer::Directory.new('/base/path', 'my_folder') }
32
-
33
- context '#uids' do
34
-
35
- it 'should return the backed-up uids' do
36
- files = ['00000123.json', '000001.json']
37
-
38
- File.should_receive(:exist?).with('/base/path/my_folder').and_return(true)
39
- Dir.should_receive(:open).with('/base/path/my_folder').and_return(files)
40
-
41
- subject.uids.should == [1, 123]
42
- end
43
-
44
- it 'should return an empty Array if the directory does not exist' do
45
- File.should_receive(:exist?).with('/base/path/my_folder').and_return(false)
46
-
47
- subject.uids.should == []
48
- end
32
+ context '#exist?' do
33
+ it 'should check if the file exists' do
34
+ File.should_receive(:exist?).with(%r{/base/path/my_folder/0+123.json}).and_return(true)
49
35
 
36
+ subject.exist?(123).should be_true
50
37
  end
38
+ end
51
39
 
52
- context '#exist?' do
53
-
54
- it 'should check if the file exists' do
55
- File.should_receive(:exist?).with(%r{/base/path/my_folder/0+123.json}).and_return(true)
40
+ context '#save' do
41
+ let(:message) do
42
+ {
43
+ 'RFC822' => 'the body',
44
+ 'other' => 'xxx'
45
+ }
46
+ end
47
+ let(:file) { stub('File', :write => nil) }
56
48
 
57
- subject.exist?(123).should be_true
49
+ before do
50
+ File.stub!(:exist?).with(%r{/base/path/my_folder/0+1234.json}).and_return(true)
51
+ FileUtils.stub!(:chmod).with(0600, /0+1234.json$/)
52
+ File.stub!(:open) do |&block|
53
+ block.call file
58
54
  end
59
-
60
55
  end
61
56
 
62
- context '#save' do
63
-
64
- before :each do
65
- File.stub!(:exist?).with(%r{/base/path/my_folder/0+1234.json}).and_return(true)
66
- FileUtils.stub!(:chmod).with(0600, /0+1234.json$/)
67
- @message = {
68
- 'RFC822' => 'the body',
69
- 'other' => 'xxx'
70
- }
71
- @file = stub('File', :write => nil)
72
- File.stub!(:open) do |&block|
73
- block.call @file
74
- end
57
+ it 'should save messages' do
58
+ File.should_receive(:open) do |&block|
59
+ block.call file
75
60
  end
61
+ file.should_receive(:write).with(/the body/)
76
62
 
77
- it 'should save messages' do
78
- File.should_receive(:open) do |&block|
79
- block.call @file
80
- end
81
- @file.should_receive(:write).with(/the body/)
82
-
83
- subject.save('1234', @message)
84
- end
63
+ subject.save('1234', message)
64
+ end
85
65
 
86
- it 'should JSON encode messages' do
87
- @message.should_receive(:to_json)
66
+ it 'should JSON encode messages' do
67
+ message.should_receive(:to_json)
88
68
 
89
- subject.save('1234', @message)
90
- end
69
+ subject.save('1234', message)
70
+ end
91
71
 
92
- it 'should set file permissions' do
93
- FileUtils.should_receive(:chmod).with(0600, /0+1234.json$/)
72
+ it 'should set file permissions' do
73
+ FileUtils.should_receive(:chmod).with(0600, /0+1234.json$/)
94
74
 
95
- subject.save(1234, @message)
96
- end
75
+ subject.save(1234, message)
97
76
  end
98
-
99
77
  end
100
-
101
78
  end
102
79
 
@@ -0,0 +1,113 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Imap::Backup::Serializer::Mbox do
6
+ let(:stat) { stub('File::Stat', :mode => 0700) }
7
+ let(:mbox_pathname) { '/base/path/my/folder.mbox' }
8
+ let(:imap_pathname) { '/base/path/my/folder.imap' }
9
+
10
+ before do
11
+ File.stub(:exist?).with('/base/path').and_return(true)
12
+ File.stub!(:stat).with('/base/path').and_return(stat)
13
+ Imap::Backup::Utils.stub(:make_folder)
14
+ end
15
+
16
+ context '#initialize' do
17
+ before do
18
+ File.stub(:exist?).with(mbox_pathname).and_return(true)
19
+ File.stub(:exist?).with(imap_pathname).and_return(true)
20
+ end
21
+
22
+ it 'creates the containing directory' do
23
+ Imap::Backup::Utils.should_receive(:make_folder).with('/base/path', 'my', 0700)
24
+
25
+ Imap::Backup::Serializer::Mbox.new('/base/path', 'my/folder')
26
+ end
27
+
28
+ context 'mbox and imap files' do
29
+ it 'checks if they exist' do
30
+ File.should_receive(:exist?).with(mbox_pathname).and_return(true)
31
+ File.should_receive(:exist?).with(imap_pathname).and_return(true)
32
+
33
+ Imap::Backup::Serializer::Mbox.new('/base/path', 'my/folder')
34
+ end
35
+
36
+ it "fails if mbox exists and imap doesn't" do
37
+ File.stub(:exist?).with(imap_pathname).and_return(false)
38
+
39
+ expect {
40
+ Imap::Backup::Serializer::Mbox.new('/base/path', 'my/folder')
41
+ }.to raise_error(RuntimeError, '.imap file missing')
42
+ end
43
+
44
+ it "fails if imap exists and mbox doesn't" do
45
+ File.stub(:exist?).with(mbox_pathname).and_return(false)
46
+
47
+ expect {
48
+ Imap::Backup::Serializer::Mbox.new('/base/path', 'my/folder')
49
+ }.to raise_error(RuntimeError, '.mbox file missing')
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'instance methods' do
55
+ before do
56
+ File.stub(:exist?).with(mbox_pathname).and_return(true)
57
+ File.stub(:exist?).with(imap_pathname).and_return(true)
58
+ CSV.stub(:foreach) do |&block|
59
+ block.call ['1']
60
+ block.call ['123']
61
+ end
62
+ end
63
+
64
+ subject { Imap::Backup::Serializer::Mbox.new('/base/path', 'my/folder') }
65
+
66
+ context '#uids' do
67
+ it 'returns the backed-up uids' do
68
+ File.should_receive(:exist?).with(mbox_pathname).and_return(true)
69
+ File.should_receive(:exist?).with(imap_pathname).and_return(true)
70
+
71
+ expect(subject.uids).to eq(['1', '123'])
72
+ end
73
+
74
+ it 'returns an empty Array if the mbox does not exist' do
75
+ File.stub(:exist?).with(mbox_pathname).and_return(false)
76
+ File.stub(:exist?).with(imap_pathname).and_return(false)
77
+ File.should_receive(:exist?).with(mbox_pathname).and_return(false)
78
+ File.should_receive(:exist?).with(imap_pathname).and_return(false)
79
+
80
+ expect(subject.uids).to eq([])
81
+ end
82
+ end
83
+
84
+ context '#save' do
85
+ let(:mbox_formatted_message) { 'message in mbox format' }
86
+ let(:message_uid) { '999' }
87
+ let(:message) { stub('Email::Mboxrd::Message', :to_s => mbox_formatted_message) }
88
+ let(:mbox_file) { stub('File - mbox', :close => nil) }
89
+ let(:imap_file) { stub('File - imap', :close => nil) }
90
+
91
+ before do
92
+ Email::Mboxrd::Message.stub(:new => message)
93
+ File.stub(:open).with(mbox_pathname, 'ab').and_return(mbox_file)
94
+ File.stub(:open).with(imap_pathname, 'ab').and_return(imap_file)
95
+ mbox_file.stub(:write).with(mbox_formatted_message)
96
+ imap_file.stub(:write).with(message_uid + "\n")
97
+ end
98
+
99
+ it 'saves the message to the mbox' do
100
+ mbox_file.should_receive(:write).with(mbox_formatted_message)
101
+
102
+ subject.save(message_uid, "The\nemail\n")
103
+ end
104
+
105
+ it 'saves the uid to the imap file' do
106
+ imap_file.should_receive(:write).with(message_uid + "\n")
107
+
108
+ subject.save(message_uid, "The\nemail\n")
109
+ end
110
+ end
111
+ end
112
+ end
113
+