imap-backup 5.0.0 → 6.0.0.rc2
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/README.md +8 -7
- data/bin/imap-backup +4 -0
- data/docs/development.md +10 -4
- data/imap-backup.gemspec +2 -7
- data/lib/cli_coverage.rb +18 -0
- data/lib/imap/backup/account/connection.rb +7 -11
- data/lib/imap/backup/account/folder.rb +0 -16
- data/lib/imap/backup/account.rb +31 -11
- data/lib/imap/backup/cli/folders.rb +3 -3
- data/lib/imap/backup/cli/migrate.rb +3 -3
- data/lib/imap/backup/cli/restore.rb +20 -4
- data/lib/imap/backup/cli/utils.rb +2 -2
- data/lib/imap/backup/cli.rb +6 -7
- data/lib/imap/backup/configuration.rb +1 -11
- data/lib/imap/backup/downloader.rb +13 -9
- data/lib/imap/backup/serializer/directory.rb +37 -0
- data/lib/imap/backup/serializer/imap.rb +120 -0
- data/lib/imap/backup/serializer/mbox.rb +23 -94
- data/lib/imap/backup/serializer/mbox_enumerator.rb +2 -0
- data/lib/imap/backup/serializer.rb +180 -3
- data/lib/imap/backup/setup/account.rb +52 -29
- data/lib/imap/backup/setup/helpers.rb +1 -1
- data/lib/imap/backup/thunderbird/mailbox_exporter.rb +1 -1
- data/lib/imap/backup/version.rb +2 -2
- data/lib/imap/backup.rb +0 -1
- data/spec/features/backup_spec.rb +22 -29
- data/spec/features/restore_spec.rb +8 -6
- data/spec/features/support/aruba.rb +12 -3
- data/spec/features/support/backup_directory.rb +0 -4
- data/spec/features/support/email_server.rb +0 -1
- data/spec/spec_helper.rb +4 -9
- data/spec/unit/imap/backup/account/connection_spec.rb +36 -8
- data/spec/unit/imap/backup/account/folder_spec.rb +18 -16
- data/spec/unit/imap/backup/account_spec.rb +246 -0
- data/spec/unit/imap/backup/cli/accounts_spec.rb +12 -1
- data/spec/unit/imap/backup/cli/backup_spec.rb +19 -0
- data/spec/unit/imap/backup/cli/folders_spec.rb +39 -0
- data/spec/unit/imap/backup/cli/local_spec.rb +26 -7
- data/spec/unit/imap/backup/cli/migrate_spec.rb +80 -0
- data/spec/unit/imap/backup/cli/restore_spec.rb +67 -0
- data/spec/unit/imap/backup/cli/setup_spec.rb +17 -0
- data/spec/unit/imap/backup/cli/utils_spec.rb +68 -5
- data/spec/unit/imap/backup/cli_spec.rb +93 -0
- data/spec/unit/imap/backup/client/apple_mail_spec.rb +9 -0
- data/spec/unit/imap/backup/configuration_spec.rb +2 -2
- data/spec/unit/imap/backup/downloader_spec.rb +60 -8
- data/spec/unit/imap/backup/logger_spec.rb +1 -1
- data/spec/unit/imap/backup/migrator_spec.rb +1 -1
- data/spec/unit/imap/backup/sanitizer_spec.rb +42 -0
- data/spec/unit/imap/backup/serializer/directory_spec.rb +37 -0
- data/spec/unit/imap/backup/serializer/imap_spec.rb +218 -0
- data/spec/unit/imap/backup/serializer/mbox_spec.rb +62 -183
- data/spec/unit/imap/backup/serializer_spec.rb +296 -0
- data/spec/unit/imap/backup/setup/account_spec.rb +120 -25
- data/spec/unit/imap/backup/setup/helpers_spec.rb +15 -0
- data/spec/unit/imap/backup/thunderbird/mailbox_exporter_spec.rb +116 -0
- data/spec/unit/imap/backup/uploader_spec.rb +1 -1
- data/spec/unit/retry_on_error_spec.rb +34 -0
- metadata +44 -37
- data/lib/imap/backup/serializer/mbox_store.rb +0 -217
- data/lib/thunderbird/install.rb +0 -16
- data/lib/thunderbird/local_folder.rb +0 -65
- data/lib/thunderbird/profile.rb +0 -30
- data/lib/thunderbird/profiles.rb +0 -71
- data/lib/thunderbird/subdirectory.rb +0 -93
- data/lib/thunderbird/subdirectory_placeholder.rb +0 -21
- data/lib/thunderbird.rb +0 -14
- data/spec/gather_rspec_coverage.rb +0 -1
- data/spec/unit/imap/backup/serializer/mbox_store_spec.rb +0 -329
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:
|
4
|
+
version: 6.0.0.rc2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Yates
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -81,13 +81,13 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.1'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: thunderbird
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: 0.0.0
|
90
|
-
type: :
|
90
|
+
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
@@ -95,19 +95,19 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 0.0.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: aruba
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 0.
|
103
|
+
version: 0.0.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.
|
110
|
+
version: 0.0.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: pry-byebug
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,20 +136,6 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: 3.0.0
|
139
|
-
- !ruby/object:Gem::Dependency
|
140
|
-
name: rspec_junit_formatter
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
142
|
-
requirements:
|
143
|
-
- - ">="
|
144
|
-
- !ruby/object:Gem::Version
|
145
|
-
version: '0'
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - ">="
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: '0'
|
153
139
|
- !ruby/object:Gem::Dependency
|
154
140
|
name: rubocop-rspec
|
155
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -193,6 +179,7 @@ files:
|
|
193
179
|
- docs/restore.md
|
194
180
|
- docs/setup.md
|
195
181
|
- imap-backup.gemspec
|
182
|
+
- lib/cli_coverage.rb
|
196
183
|
- lib/email/mboxrd/message.rb
|
197
184
|
- lib/email/provider.rb
|
198
185
|
- lib/email/provider/apple_mail.rb
|
@@ -224,9 +211,10 @@ files:
|
|
224
211
|
- lib/imap/backup/migrator.rb
|
225
212
|
- lib/imap/backup/sanitizer.rb
|
226
213
|
- lib/imap/backup/serializer.rb
|
214
|
+
- lib/imap/backup/serializer/directory.rb
|
215
|
+
- lib/imap/backup/serializer/imap.rb
|
227
216
|
- lib/imap/backup/serializer/mbox.rb
|
228
217
|
- lib/imap/backup/serializer/mbox_enumerator.rb
|
229
|
-
- lib/imap/backup/serializer/mbox_store.rb
|
230
218
|
- lib/imap/backup/setup.rb
|
231
219
|
- lib/imap/backup/setup/account.rb
|
232
220
|
- lib/imap/backup/setup/asker.rb
|
@@ -238,13 +226,6 @@ files:
|
|
238
226
|
- lib/imap/backup/utils.rb
|
239
227
|
- lib/imap/backup/version.rb
|
240
228
|
- lib/retry_on_error.rb
|
241
|
-
- lib/thunderbird.rb
|
242
|
-
- lib/thunderbird/install.rb
|
243
|
-
- lib/thunderbird/local_folder.rb
|
244
|
-
- lib/thunderbird/profile.rb
|
245
|
-
- lib/thunderbird/profiles.rb
|
246
|
-
- lib/thunderbird/subdirectory.rb
|
247
|
-
- lib/thunderbird/subdirectory_placeholder.rb
|
248
229
|
- spec/features/backup_spec.rb
|
249
230
|
- spec/features/configuration/minimal_configuration.rb
|
250
231
|
- spec/features/configuration/missing_configuration.rb
|
@@ -264,7 +245,6 @@ files:
|
|
264
245
|
- spec/features/support/shared/connection_context.rb
|
265
246
|
- spec/features/support/shared/message_fixtures.rb
|
266
247
|
- spec/fixtures/connection.yml
|
267
|
-
- spec/gather_rspec_coverage.rb
|
268
248
|
- spec/spec_helper.rb
|
269
249
|
- spec/support/fixtures.rb
|
270
250
|
- spec/support/higline_test_helpers.rb
|
@@ -277,25 +257,39 @@ files:
|
|
277
257
|
- spec/unit/email/provider_spec.rb
|
278
258
|
- spec/unit/imap/backup/account/connection_spec.rb
|
279
259
|
- spec/unit/imap/backup/account/folder_spec.rb
|
260
|
+
- spec/unit/imap/backup/account_spec.rb
|
280
261
|
- spec/unit/imap/backup/cli/accounts_spec.rb
|
262
|
+
- spec/unit/imap/backup/cli/backup_spec.rb
|
263
|
+
- spec/unit/imap/backup/cli/folders_spec.rb
|
281
264
|
- spec/unit/imap/backup/cli/helpers_spec.rb
|
282
265
|
- spec/unit/imap/backup/cli/local_spec.rb
|
266
|
+
- spec/unit/imap/backup/cli/migrate_spec.rb
|
267
|
+
- spec/unit/imap/backup/cli/restore_spec.rb
|
268
|
+
- spec/unit/imap/backup/cli/setup_spec.rb
|
283
269
|
- spec/unit/imap/backup/cli/utils_spec.rb
|
270
|
+
- spec/unit/imap/backup/cli_spec.rb
|
271
|
+
- spec/unit/imap/backup/client/apple_mail_spec.rb
|
284
272
|
- spec/unit/imap/backup/client/default_spec.rb
|
285
273
|
- spec/unit/imap/backup/configuration_spec.rb
|
286
274
|
- spec/unit/imap/backup/downloader_spec.rb
|
287
275
|
- spec/unit/imap/backup/logger_spec.rb
|
288
276
|
- spec/unit/imap/backup/migrator_spec.rb
|
277
|
+
- spec/unit/imap/backup/sanitizer_spec.rb
|
278
|
+
- spec/unit/imap/backup/serializer/directory_spec.rb
|
279
|
+
- spec/unit/imap/backup/serializer/imap_spec.rb
|
289
280
|
- spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb
|
290
281
|
- spec/unit/imap/backup/serializer/mbox_spec.rb
|
291
|
-
- spec/unit/imap/backup/
|
282
|
+
- spec/unit/imap/backup/serializer_spec.rb
|
292
283
|
- spec/unit/imap/backup/setup/account_spec.rb
|
293
284
|
- spec/unit/imap/backup/setup/asker_spec.rb
|
294
285
|
- spec/unit/imap/backup/setup/connection_tester_spec.rb
|
295
286
|
- spec/unit/imap/backup/setup/folder_chooser_spec.rb
|
287
|
+
- spec/unit/imap/backup/setup/helpers_spec.rb
|
296
288
|
- spec/unit/imap/backup/setup_spec.rb
|
289
|
+
- spec/unit/imap/backup/thunderbird/mailbox_exporter_spec.rb
|
297
290
|
- spec/unit/imap/backup/uploader_spec.rb
|
298
291
|
- spec/unit/imap/backup/utils_spec.rb
|
292
|
+
- spec/unit/retry_on_error_spec.rb
|
299
293
|
homepage: https://github.com/joeyates/imap-backup
|
300
294
|
licenses:
|
301
295
|
- MIT
|
@@ -311,9 +305,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
311
305
|
version: '2.5'
|
312
306
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
313
307
|
requirements:
|
314
|
-
- - "
|
308
|
+
- - ">"
|
315
309
|
- !ruby/object:Gem::Version
|
316
|
-
version:
|
310
|
+
version: 1.3.1
|
317
311
|
requirements: []
|
318
312
|
rubygems_version: 3.1.6
|
319
313
|
signing_key:
|
@@ -321,18 +315,27 @@ specification_version: 4
|
|
321
315
|
summary: Backup GMail (or other IMAP) accounts to disk
|
322
316
|
test_files:
|
323
317
|
- spec/spec_helper.rb
|
318
|
+
- spec/unit/imap/backup/account_spec.rb
|
319
|
+
- spec/unit/imap/backup/serializer/imap_spec.rb
|
320
|
+
- spec/unit/imap/backup/serializer/directory_spec.rb
|
324
321
|
- spec/unit/imap/backup/serializer/mbox_spec.rb
|
325
|
-
- spec/unit/imap/backup/serializer/mbox_store_spec.rb
|
326
322
|
- spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb
|
323
|
+
- spec/unit/imap/backup/cli_spec.rb
|
327
324
|
- spec/unit/imap/backup/setup_spec.rb
|
328
325
|
- spec/unit/imap/backup/logger_spec.rb
|
329
326
|
- spec/unit/imap/backup/configuration_spec.rb
|
330
327
|
- spec/unit/imap/backup/setup/account_spec.rb
|
331
328
|
- spec/unit/imap/backup/setup/connection_tester_spec.rb
|
332
329
|
- spec/unit/imap/backup/setup/asker_spec.rb
|
330
|
+
- spec/unit/imap/backup/setup/helpers_spec.rb
|
333
331
|
- spec/unit/imap/backup/setup/folder_chooser_spec.rb
|
332
|
+
- spec/unit/imap/backup/cli/folders_spec.rb
|
333
|
+
- spec/unit/imap/backup/cli/setup_spec.rb
|
334
|
+
- spec/unit/imap/backup/cli/backup_spec.rb
|
335
|
+
- spec/unit/imap/backup/cli/restore_spec.rb
|
334
336
|
- spec/unit/imap/backup/cli/helpers_spec.rb
|
335
337
|
- spec/unit/imap/backup/cli/accounts_spec.rb
|
338
|
+
- spec/unit/imap/backup/cli/migrate_spec.rb
|
336
339
|
- spec/unit/imap/backup/cli/utils_spec.rb
|
337
340
|
- spec/unit/imap/backup/cli/local_spec.rb
|
338
341
|
- spec/unit/imap/backup/downloader_spec.rb
|
@@ -341,7 +344,12 @@ test_files:
|
|
341
344
|
- spec/unit/imap/backup/account/folder_spec.rb
|
342
345
|
- spec/unit/imap/backup/account/connection_spec.rb
|
343
346
|
- spec/unit/imap/backup/utils_spec.rb
|
347
|
+
- spec/unit/imap/backup/serializer_spec.rb
|
344
348
|
- spec/unit/imap/backup/client/default_spec.rb
|
349
|
+
- spec/unit/imap/backup/client/apple_mail_spec.rb
|
350
|
+
- spec/unit/imap/backup/thunderbird/mailbox_exporter_spec.rb
|
351
|
+
- spec/unit/imap/backup/sanitizer_spec.rb
|
352
|
+
- spec/unit/retry_on_error_spec.rb
|
345
353
|
- spec/unit/email/mboxrd/message_spec.rb
|
346
354
|
- spec/unit/email/provider/gmail_spec.rb
|
347
355
|
- spec/unit/email/provider/apple_mail_spec.rb
|
@@ -370,4 +378,3 @@ test_files:
|
|
370
378
|
- spec/support/silence_logging.rb
|
371
379
|
- spec/support/higline_test_helpers.rb
|
372
380
|
- spec/fixtures/connection.yml
|
373
|
-
- spec/gather_rspec_coverage.rb
|
@@ -1,217 +0,0 @@
|
|
1
|
-
require "json"
|
2
|
-
|
3
|
-
require "email/mboxrd/message"
|
4
|
-
require "imap/backup/serializer/mbox_enumerator"
|
5
|
-
|
6
|
-
module Imap::Backup
|
7
|
-
class Serializer::MboxStore
|
8
|
-
CURRENT_VERSION = 2
|
9
|
-
|
10
|
-
attr_reader :folder
|
11
|
-
attr_reader :path
|
12
|
-
attr_reader :loaded
|
13
|
-
|
14
|
-
def initialize(path, folder)
|
15
|
-
@path = path
|
16
|
-
@folder = folder
|
17
|
-
@loaded = false
|
18
|
-
@uids = nil
|
19
|
-
@uid_validity = nil
|
20
|
-
end
|
21
|
-
|
22
|
-
def exist?
|
23
|
-
mbox_exist? && imap_exist?
|
24
|
-
end
|
25
|
-
|
26
|
-
def uid_validity
|
27
|
-
do_load if !loaded
|
28
|
-
@uid_validity
|
29
|
-
end
|
30
|
-
|
31
|
-
def uid_validity=(value)
|
32
|
-
do_load if !loaded
|
33
|
-
@uid_validity = value
|
34
|
-
@uids ||= []
|
35
|
-
write_imap_file
|
36
|
-
end
|
37
|
-
|
38
|
-
def uids
|
39
|
-
do_load if !loaded
|
40
|
-
@uids || []
|
41
|
-
end
|
42
|
-
|
43
|
-
def add(uid, body)
|
44
|
-
do_load if !loaded
|
45
|
-
raise "Can't add messages without uid_validity" if !uid_validity
|
46
|
-
|
47
|
-
uid = uid.to_i
|
48
|
-
if uids.include?(uid)
|
49
|
-
Imap::Backup::Logger.logger.debug(
|
50
|
-
"[#{folder}] message #{uid} already downloaded - skipping"
|
51
|
-
)
|
52
|
-
return
|
53
|
-
end
|
54
|
-
|
55
|
-
mboxrd_message = Email::Mboxrd::Message.new(body)
|
56
|
-
mbox = nil
|
57
|
-
begin
|
58
|
-
mbox = File.open(mbox_pathname, "ab")
|
59
|
-
mbox.write mboxrd_message.to_serialized
|
60
|
-
@uids << uid
|
61
|
-
write_imap_file
|
62
|
-
rescue StandardError => e
|
63
|
-
message = <<-ERROR.gsub(/^\s*/m, "")
|
64
|
-
[#{folder}] failed to save message #{uid}:
|
65
|
-
#{body}. #{e}:
|
66
|
-
#{e.backtrace.join("\n")}"
|
67
|
-
ERROR
|
68
|
-
Imap::Backup::Logger.logger.warn message
|
69
|
-
ensure
|
70
|
-
mbox&.close
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def load(uid_maybe_string)
|
75
|
-
do_load if !loaded
|
76
|
-
uid = uid_maybe_string.to_i
|
77
|
-
message_index = uids.find_index(uid)
|
78
|
-
return nil if message_index.nil?
|
79
|
-
|
80
|
-
load_nth(message_index)
|
81
|
-
end
|
82
|
-
|
83
|
-
def each_message(required_uids)
|
84
|
-
return enum_for(:each_message, required_uids) if !block_given?
|
85
|
-
|
86
|
-
indexes = required_uids.each.with_object({}) do |uid_maybe_string, acc|
|
87
|
-
uid = uid_maybe_string.to_i
|
88
|
-
index = uids.find_index(uid)
|
89
|
-
acc[index] = uid if index
|
90
|
-
end
|
91
|
-
enumerator = Serializer::MboxEnumerator.new(mbox_pathname)
|
92
|
-
enumerator.each.with_index do |raw, i|
|
93
|
-
uid = indexes[i]
|
94
|
-
next if !uid
|
95
|
-
|
96
|
-
yield uid, Email::Mboxrd::Message.from_serialized(raw)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def update_uid(old, new)
|
101
|
-
index = uids.find_index(old.to_i)
|
102
|
-
return if index.nil?
|
103
|
-
|
104
|
-
uids[index] = new.to_i
|
105
|
-
write_imap_file
|
106
|
-
end
|
107
|
-
|
108
|
-
def reset
|
109
|
-
@uids = nil
|
110
|
-
@uid_validity = nil
|
111
|
-
@loaded = false
|
112
|
-
delete_files
|
113
|
-
write_blank_mbox_file
|
114
|
-
end
|
115
|
-
|
116
|
-
def rename(new_name)
|
117
|
-
new_mbox_pathname = absolute_path("#{new_name}.mbox")
|
118
|
-
new_imap_pathname = absolute_path("#{new_name}.imap")
|
119
|
-
File.rename(mbox_pathname, new_mbox_pathname)
|
120
|
-
File.rename(imap_pathname, new_imap_pathname)
|
121
|
-
@folder = new_name
|
122
|
-
end
|
123
|
-
|
124
|
-
def mbox_pathname
|
125
|
-
absolute_path("#{folder}.mbox")
|
126
|
-
end
|
127
|
-
|
128
|
-
def imap_pathname
|
129
|
-
absolute_path("#{folder}.imap")
|
130
|
-
end
|
131
|
-
|
132
|
-
private
|
133
|
-
|
134
|
-
def do_load
|
135
|
-
data = imap_data
|
136
|
-
if data
|
137
|
-
@uids = data[:uids].map(&:to_i)
|
138
|
-
@uid_validity = data[:uid_validity]
|
139
|
-
@loaded = true
|
140
|
-
else
|
141
|
-
reset
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def imap_data
|
146
|
-
return nil if !imap_ok?
|
147
|
-
|
148
|
-
imap_data = nil
|
149
|
-
|
150
|
-
begin
|
151
|
-
imap_data = JSON.parse(File.read(imap_pathname), symbolize_names: true)
|
152
|
-
rescue JSON::ParserError
|
153
|
-
return nil
|
154
|
-
end
|
155
|
-
|
156
|
-
return nil if !imap_data.key?(:uids)
|
157
|
-
return nil if !imap_data[:uids].is_a?(Array)
|
158
|
-
|
159
|
-
imap_data
|
160
|
-
end
|
161
|
-
|
162
|
-
def imap_ok?
|
163
|
-
return false if !exist?
|
164
|
-
return false if !imap_looks_like_json?
|
165
|
-
|
166
|
-
true
|
167
|
-
end
|
168
|
-
|
169
|
-
def load_nth(index)
|
170
|
-
enumerator = Serializer::MboxEnumerator.new(mbox_pathname)
|
171
|
-
enumerator.each.with_index do |raw, i|
|
172
|
-
next if i != index
|
173
|
-
|
174
|
-
return Email::Mboxrd::Message.from_serialized(raw)
|
175
|
-
end
|
176
|
-
nil
|
177
|
-
end
|
178
|
-
|
179
|
-
def imap_looks_like_json?
|
180
|
-
return false if !imap_exist?
|
181
|
-
|
182
|
-
content = File.read(imap_pathname)
|
183
|
-
content.start_with?("{")
|
184
|
-
end
|
185
|
-
|
186
|
-
def write_imap_file
|
187
|
-
imap_data = {
|
188
|
-
version: CURRENT_VERSION,
|
189
|
-
uid_validity: @uid_validity,
|
190
|
-
uids: @uids
|
191
|
-
}
|
192
|
-
content = imap_data.to_json
|
193
|
-
File.open(imap_pathname, "w") { |f| f.write content }
|
194
|
-
end
|
195
|
-
|
196
|
-
def write_blank_mbox_file
|
197
|
-
File.open(mbox_pathname, "w") { |f| f.write "" }
|
198
|
-
end
|
199
|
-
|
200
|
-
def delete_files
|
201
|
-
File.unlink(imap_pathname) if imap_exist?
|
202
|
-
File.unlink(mbox_pathname) if mbox_exist?
|
203
|
-
end
|
204
|
-
|
205
|
-
def mbox_exist?
|
206
|
-
File.exist?(mbox_pathname)
|
207
|
-
end
|
208
|
-
|
209
|
-
def imap_exist?
|
210
|
-
File.exist?(imap_pathname)
|
211
|
-
end
|
212
|
-
|
213
|
-
def absolute_path(relative_path)
|
214
|
-
File.join(path, relative_path)
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
data/lib/thunderbird/install.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
require "thunderbird/profiles"
|
2
|
-
|
3
|
-
class Thunderbird::Install
|
4
|
-
attr_reader :title
|
5
|
-
attr_reader :entries
|
6
|
-
|
7
|
-
# entries are lines from profile.ini
|
8
|
-
def initialize(title, entries)
|
9
|
-
@title = title
|
10
|
-
@entries = entries
|
11
|
-
end
|
12
|
-
|
13
|
-
def default
|
14
|
-
Thunderbird::Profiles.new.profile_for_path(entries[:Default])
|
15
|
-
end
|
16
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require "thunderbird/profile"
|
2
|
-
require "thunderbird/subdirectory"
|
3
|
-
|
4
|
-
# A local folder is a file containing emails
|
5
|
-
class Thunderbird::LocalFolder
|
6
|
-
attr_reader :path
|
7
|
-
attr_reader :profile
|
8
|
-
|
9
|
-
def initialize(profile, path)
|
10
|
-
@profile = profile
|
11
|
-
@path = path
|
12
|
-
end
|
13
|
-
|
14
|
-
def set_up
|
15
|
-
return if path_elements.empty?
|
16
|
-
|
17
|
-
return true if !in_subdirectory?
|
18
|
-
|
19
|
-
subdirectory.set_up
|
20
|
-
end
|
21
|
-
|
22
|
-
def full_path
|
23
|
-
if in_subdirectory?
|
24
|
-
File.join(subdirectory.full_path, folder_name)
|
25
|
-
else
|
26
|
-
folder_name
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def exists?
|
31
|
-
File.exist?(full_path)
|
32
|
-
end
|
33
|
-
|
34
|
-
def msf_path
|
35
|
-
"#{path}.msf"
|
36
|
-
end
|
37
|
-
|
38
|
-
def msf_exists?
|
39
|
-
File.exist?(msf_path)
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def in_subdirectory?
|
45
|
-
path_elements.count > 1
|
46
|
-
end
|
47
|
-
|
48
|
-
def subdirectory
|
49
|
-
return nil if !in_subdirectory?
|
50
|
-
|
51
|
-
Thunderbird::Subdirectory.new(profile, subdirectory_path)
|
52
|
-
end
|
53
|
-
|
54
|
-
def path_elements
|
55
|
-
path.split(File::SEPARATOR)
|
56
|
-
end
|
57
|
-
|
58
|
-
def subdirectory_path
|
59
|
-
File.join(path_elements[0..-2])
|
60
|
-
end
|
61
|
-
|
62
|
-
def folder_name
|
63
|
-
path_elements[-1]
|
64
|
-
end
|
65
|
-
end
|
data/lib/thunderbird/profile.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require "thunderbird"
|
2
|
-
|
3
|
-
class Thunderbird::Profile
|
4
|
-
attr_reader :title
|
5
|
-
attr_reader :entries
|
6
|
-
|
7
|
-
# entries are lines from profile.ini
|
8
|
-
def initialize(title, entries)
|
9
|
-
@title = title
|
10
|
-
@entries = entries
|
11
|
-
end
|
12
|
-
|
13
|
-
def root
|
14
|
-
if relative?
|
15
|
-
File.join(Thunderbird.new.data_path, entries[:Path])
|
16
|
-
else
|
17
|
-
entries[:Path]
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def local_folders_path
|
22
|
-
File.join(root, "Mail", "Local Folders")
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def relative?
|
28
|
-
entries[:IsRelative] == "1"
|
29
|
-
end
|
30
|
-
end
|
data/lib/thunderbird/profiles.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
require "thunderbird"
|
2
|
-
require "thunderbird/install"
|
3
|
-
require "thunderbird/profile"
|
4
|
-
|
5
|
-
# http://kb.mozillazine.org/Profiles.ini_file
|
6
|
-
class Thunderbird::Profiles
|
7
|
-
def profile_for_path(path)
|
8
|
-
title, entries = blocks.find { |_name, entries| entries[:Path] == path }
|
9
|
-
|
10
|
-
Thunderbird::Profile.new(title, entries) if title
|
11
|
-
end
|
12
|
-
|
13
|
-
def profile(name)
|
14
|
-
title, entries = blocks.find { |_name, entries| entries[:Name] == name }
|
15
|
-
|
16
|
-
Thunderbird::Profile.new(title, entries) if title
|
17
|
-
end
|
18
|
-
|
19
|
-
def installs
|
20
|
-
@installs ||= begin
|
21
|
-
pairs = blocks.filter { |name, _entries| name.start_with?("Install") }
|
22
|
-
pairs.map { |title, entries| Thunderbird::Install.new(title, entries) }
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
# Parse profiles.ini.
|
29
|
-
# Blocks start with a title, e.g. '[Abc]'
|
30
|
-
# and are followed by a number of lines
|
31
|
-
def blocks
|
32
|
-
@blocks ||= begin
|
33
|
-
blocks = {}
|
34
|
-
File.open(profiles_ini_path, "rb") do |f|
|
35
|
-
title = nil
|
36
|
-
entries = nil
|
37
|
-
|
38
|
-
loop do
|
39
|
-
line = f.gets
|
40
|
-
if !line
|
41
|
-
blocks[title] = entries if title
|
42
|
-
break
|
43
|
-
end
|
44
|
-
|
45
|
-
line.chomp!
|
46
|
-
|
47
|
-
# Is this line the start of a new block
|
48
|
-
match = line.match(/\A\[([A-Za-z0-9]+)\]\z/)
|
49
|
-
if match
|
50
|
-
# Store what we got before this title as a new block
|
51
|
-
blocks[title] = entries if title
|
52
|
-
|
53
|
-
# Start a new block
|
54
|
-
title = match[1]
|
55
|
-
entries = {}
|
56
|
-
elsif line != ""
|
57
|
-
# Collect entries until we get to the next title
|
58
|
-
key, value = line.split("=")
|
59
|
-
entries[key.to_sym] = value
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
blocks
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def profiles_ini_path
|
69
|
-
File.join(Thunderbird.new.data_path, "profiles.ini")
|
70
|
-
end
|
71
|
-
end
|
@@ -1,93 +0,0 @@
|
|
1
|
-
require "thunderbird/subdirectory_placeholder"
|
2
|
-
|
3
|
-
class Thunderbird::Subdirectory
|
4
|
-
# `path` is the UI path, it doesn't have the '.sbd' extensions
|
5
|
-
# that are present in the real, file system path
|
6
|
-
attr_reader :path
|
7
|
-
attr_reader :profile
|
8
|
-
|
9
|
-
def initialize(profile, path)
|
10
|
-
@profile = profile
|
11
|
-
@path = path
|
12
|
-
end
|
13
|
-
|
14
|
-
def set_up
|
15
|
-
raise "Cannot create a subdirectory without a path" if !sub_directory?
|
16
|
-
|
17
|
-
if sub_sub_directory?
|
18
|
-
parent_ok = parent.set_up
|
19
|
-
return false if !parent_ok
|
20
|
-
end
|
21
|
-
|
22
|
-
ok = check
|
23
|
-
return false if !ok
|
24
|
-
|
25
|
-
FileUtils.mkdir_p full_path
|
26
|
-
placeholder.touch
|
27
|
-
|
28
|
-
true
|
29
|
-
end
|
30
|
-
|
31
|
-
# subdirectory relative path is 'Foo.sbd/Bar.sbd/Baz.sbd'
|
32
|
-
def full_path
|
33
|
-
relative_path = File.join(subdirectories)
|
34
|
-
File.join(profile.local_folders_path, relative_path)
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def sub_directory?
|
40
|
-
path_elements.any?
|
41
|
-
end
|
42
|
-
|
43
|
-
def sub_sub_directory?
|
44
|
-
path_elements.count > 1
|
45
|
-
end
|
46
|
-
|
47
|
-
def parent
|
48
|
-
return nil if !sub_sub_directory?
|
49
|
-
|
50
|
-
self.class.new(profile, File.join(path_elements[0..-2]))
|
51
|
-
end
|
52
|
-
|
53
|
-
# placeholder relative path is 'Foo.sbd/Bar.sbd/Baz'
|
54
|
-
def placeholder
|
55
|
-
@placeholder = begin
|
56
|
-
relative_path = File.join(subdirectories[0..-2], path_elements[-1])
|
57
|
-
path = File.join(profile.local_folders_path, relative_path)
|
58
|
-
Thunderbird::SubdirectoryPlaceholder.new(path)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def path_elements
|
63
|
-
path.split(File::SEPARATOR)
|
64
|
-
end
|
65
|
-
|
66
|
-
def exists?
|
67
|
-
File.exist?(full_path)
|
68
|
-
end
|
69
|
-
|
70
|
-
def directory?
|
71
|
-
File.directory?(full_path)
|
72
|
-
end
|
73
|
-
|
74
|
-
def subdirectories
|
75
|
-
path_elements.map { |p| "#{p}.sbd" }
|
76
|
-
end
|
77
|
-
|
78
|
-
def check
|
79
|
-
case
|
80
|
-
when exists? && !placeholder.exists?
|
81
|
-
Kernel.puts "Can't set up folder '#{full_path}': '#{full_path}' exists, but '#{placeholder.path}' is missing"
|
82
|
-
false
|
83
|
-
when placeholder.exists? && !placeholder.regular?
|
84
|
-
Kernel.puts "Can't set up folder '#{full_path}': '#{placeholder.path}' exists, but it is not a regular file"
|
85
|
-
false
|
86
|
-
when exists? && !directory?
|
87
|
-
Kernel.puts "Can't set up folder '#{full_path}': '#{full_path}' exists, but it is not a directory"
|
88
|
-
false
|
89
|
-
else
|
90
|
-
true
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|