imap-backup 0.0.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+