imap-backup 4.0.2 → 4.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -1
  3. data/docs/development.md +1 -2
  4. data/imap-backup.gemspec +1 -0
  5. data/lib/email/provider/apple_mail.rb +7 -0
  6. data/lib/email/provider/default.rb +12 -0
  7. data/lib/email/provider/fastmail.rb +7 -0
  8. data/lib/email/provider/gmail.rb +7 -0
  9. data/lib/email/provider.rb +16 -26
  10. data/lib/imap/backup/account/connection.rb +19 -29
  11. data/lib/imap/backup/account/folder.rb +9 -10
  12. data/lib/imap/backup/cli/helpers.rb +1 -0
  13. data/lib/imap/backup/cli/local.rb +4 -1
  14. data/lib/imap/backup/cli/utils.rb +16 -5
  15. data/lib/imap/backup/client/apple_mail.rb +11 -0
  16. data/lib/imap/backup/client/default.rb +51 -0
  17. data/lib/imap/backup/configuration/account.rb +3 -1
  18. data/lib/imap/backup/configuration/connection_tester.rb +1 -1
  19. data/lib/imap/backup/configuration/store.rb +10 -5
  20. data/lib/imap/backup/downloader.rb +3 -4
  21. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +12 -25
  22. data/lib/imap/backup/version.rb +1 -1
  23. data/lib/thunderbird/install.rb +16 -0
  24. data/lib/thunderbird/local_folder.rb +33 -65
  25. data/lib/thunderbird/profiles.rb +18 -10
  26. data/lib/thunderbird/subdirectory.rb +96 -0
  27. data/lib/thunderbird/{local_folder_placeholder.rb → subdirectory_placeholder.rb} +4 -4
  28. data/lib/thunderbird.rb +10 -2
  29. data/spec/features/restore_spec.rb +1 -1
  30. data/spec/features/support/email_server.rb +2 -2
  31. data/spec/unit/email/provider/apple_mail_spec.rb +7 -0
  32. data/spec/unit/email/provider/default_spec.rb +17 -0
  33. data/spec/unit/email/provider/fastmail_spec.rb +7 -0
  34. data/spec/unit/email/provider/gmail_spec.rb +7 -0
  35. data/spec/unit/email/provider_spec.rb +12 -25
  36. data/spec/unit/imap/backup/account/connection_spec.rb +26 -51
  37. data/spec/unit/imap/backup/account/folder_spec.rb +22 -22
  38. data/spec/unit/imap/backup/cli/utils_spec.rb +2 -2
  39. data/spec/unit/imap/backup/client/default_spec.rb +22 -0
  40. data/spec/unit/imap/backup/configuration/connection_tester_spec.rb +3 -3
  41. data/spec/unit/imap/backup/configuration/store_spec.rb +25 -12
  42. data/spec/unit/imap/backup/downloader_spec.rb +1 -2
  43. metadata +57 -26
  44. data/lib/thunderbird/mailbox.rb +0 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14c0bd789a2532461bbfbe92dd3bb2466228fe0d14b676c308f766a5c62941cf
4
- data.tar.gz: 06203ea6c126b17b26f784f2f91f3dd72d1bfd431fe100428931d624de85c53e
3
+ metadata.gz: 139120639e68abb1555421c5c63f28a6ede222f95767f86a52e3b8d548ceaf99
4
+ data.tar.gz: ef9ef718e09d4b812085c3e72f374f922ae760d318322fa2237d742aec826e37
5
5
  SHA512:
6
- metadata.gz: a4de838badaaf992ae6ff46d590bb782810f4dae83aeeb9bd1495525bddfc396341374e18c51bec2e71a1cf66135335f2e21bdd6632ced9f64bc81f93f4eafe1
7
- data.tar.gz: 20cc1c12289c753a3814205fd7cf125a2b234b567301a37f88da65b7f86b26a66274209fc8e2218975877f6568df3d991f1db03f76fe4262c8415adc3a59d6e6
6
+ metadata.gz: 3d7447ca37c7f2134ea7254fe90640ce3f6db6599a287b5b07796236d614e887cd05614045a57d8fb2b729d9e2da357f4cb42b083303dbfe1c3dc4b92b3b3dbd
7
+ data.tar.gz: 77ea7b8ba366c8416a6cef3c707b8942d4f3261f138c603b98128d2f43079880e12f241c8672a2f301c035204ccd68bc8a6bbbc6dce8d5d9590ecbd4c490844c
data/README.md CHANGED
@@ -134,7 +134,15 @@ in the configuration file.
134
134
 
135
135
  The directory ~/.imap-backup, the configuration file and all backup
136
136
  directories have their access permissions set to only allow access
137
- by your user.
137
+ by your user. This is not done on Windows - see below.
138
+
139
+ ## Windows
140
+
141
+ Due to the complexity of managing permissions on Windows,
142
+ directory and file access permissions are not set explicity.
143
+
144
+ A pull request that implements permissions management on Windows
145
+ would be welcome!
138
146
 
139
147
  # Run Backup
140
148
 
data/docs/development.md CHANGED
@@ -41,8 +41,7 @@ response = imap.append("INBOX", message, nil, nil)
41
41
  imap.examine("INBOX")
42
42
  uids = imap.uid_search(["ALL"]).sort
43
43
 
44
- REQUESTED_ATTRIBUTES = ["RFC822", "FLAGS", "INTERNALDATE"].freeze
45
- fetch_data_items = imap.uid_fetch(uids, REQUESTED_ATTRIBUTES)
44
+ fetch_data_items = imap.uid_fetch(uids, ["BODY[]"])
46
45
  ```
47
46
 
48
47
  # Contributing
data/imap-backup.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |gem|
24
24
 
25
25
  gem.add_runtime_dependency "highline"
26
26
  gem.add_runtime_dependency "mail"
27
+ gem.add_runtime_dependency "os"
27
28
  gem.add_runtime_dependency "rake"
28
29
  gem.add_runtime_dependency "thor", "~> 1.1"
29
30
 
@@ -0,0 +1,7 @@
1
+ require "email/provider/default"
2
+
3
+ class Email::Provider::AppleMail < Email::Provider::Default
4
+ def host
5
+ "imap.mail.me.com"
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Email; end
2
+ class Email::Provider; end
3
+
4
+ class Email::Provider::Default
5
+ # We don't know how to guess the IMAP server
6
+ def host
7
+ end
8
+
9
+ def options
10
+ {port: 993, ssl: {ssl_version: :TLSv1_2}}
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ require "email/provider/default"
2
+
3
+ class Email::Provider::Fastmail < Email::Provider::Default
4
+ def host
5
+ "imap.fastmail.com"
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require "email/provider/default"
2
+
3
+ class Email::Provider::GMail < Email::Provider::Default
4
+ def host
5
+ "imap.gmail.com"
6
+ end
7
+ end
@@ -1,37 +1,27 @@
1
+ require "email/provider/default"
2
+ require "email/provider/apple_mail"
3
+ require "email/provider/fastmail"
4
+ require "email/provider/gmail"
5
+
1
6
  module Email; end
2
7
 
3
8
  class Email::Provider
4
- GMAIL_IMAP_SERVER = "imap.gmail.com".freeze
5
-
6
9
  def self.for_address(address)
7
10
  case
8
11
  when address.end_with?("@fastmail.com")
9
- new(:fastmail)
10
- when address.end_with?("@gmail.com")
11
- new(:gmail)
12
+ Email::Provider::Fastmail.new
12
13
  when address.end_with?("@fastmail.fm")
13
- new(:fastmail)
14
+ Email::Provider::Fastmail.new
15
+ when address.end_with?("@gmail.com")
16
+ Email::Provider::GMail.new
17
+ when address.end_with?("@icloud.com")
18
+ Email::Provider::AppleMail.new
19
+ when address.end_with?("@mac.com")
20
+ Email::Provider::AppleMail.new
21
+ when address.end_with?("@me.com")
22
+ Email::Provider::AppleMail.new
14
23
  else
15
- new(:default)
16
- end
17
- end
18
-
19
- attr_reader :provider
20
-
21
- def initialize(provider)
22
- @provider = provider
23
- end
24
-
25
- def options
26
- {port: 993, ssl: {ssl_version: :TLSv1_2}}
27
- end
28
-
29
- def host
30
- case provider
31
- when :gmail
32
- GMAIL_IMAP_SERVER
33
- when :fastmail
34
- "imap.fastmail.com"
24
+ Email::Provider::Default.new
35
25
  end
36
26
  end
37
27
  end
@@ -1,4 +1,5 @@
1
- require "net/imap"
1
+ require "imap/backup/client/apple_mail"
2
+ require "imap/backup/client/default"
2
3
 
3
4
  require "retry_on_error"
4
5
 
@@ -29,17 +30,15 @@ module Imap::Backup
29
30
  def folders
30
31
  @folders ||=
31
32
  begin
32
- root = provider_root
33
- mailbox_lists = imap.list(root, "*")
33
+ folders = client.list
34
34
 
35
- if mailbox_lists.nil?
35
+ if folders.empty?
36
36
  message = "Unable to get folder list for account #{username}"
37
37
  Imap::Backup.logger.info message
38
38
  raise message
39
39
  end
40
40
 
41
- utf7_encoded = mailbox_lists.map(&:name)
42
- utf7_encoded.map { |n| Net::IMAP.decode_utf7(n) }
41
+ folders
43
42
  end
44
43
  end
45
44
 
@@ -54,7 +53,7 @@ module Imap::Backup
54
53
  def run_backup
55
54
  Imap::Backup.logger.debug "Running backup of account: #{username}"
56
55
  # start the connection so we get logging messages in the right order
57
- imap
56
+ client
58
57
  each_folder do |folder, serializer|
59
58
  next if !folder.exist?
60
59
 
@@ -89,34 +88,36 @@ module Imap::Backup
89
88
  end
90
89
 
91
90
  def disconnect
92
- imap.disconnect if @imap
91
+ client.disconnect if @client
93
92
  end
94
93
 
95
94
  def reconnect
96
95
  disconnect
97
- @imap = nil
96
+ @client = nil
98
97
  end
99
98
 
100
- def imap
101
- @imap ||=
99
+ def client
100
+ @client ||=
102
101
  retry_on_error(errors: LOGIN_RETRY_CLASSES) do
103
102
  options = provider_options
104
103
  Imap::Backup.logger.debug(
105
104
  "Creating IMAP instance: #{server}, options: #{options.inspect}"
106
105
  )
107
- imap = Net::IMAP.new(server, options)
106
+ client =
107
+ if provider.is_a?(Email::Provider::AppleMail)
108
+ Client::AppleMail.new(server, options)
109
+ else
110
+ Client::Default.new(server, options)
111
+ end
108
112
  Imap::Backup.logger.debug "Logging in: #{username}/#{masked_password}"
109
- imap.login(username, password)
113
+ client.login(username, password)
110
114
  Imap::Backup.logger.debug "Login complete"
111
- imap
115
+ client
112
116
  end
113
117
  end
114
118
 
115
119
  def server
116
- return @server if @server
117
- return nil if provider.nil?
118
-
119
- @server = provider.host
120
+ @server ||= provider.host
120
121
  end
121
122
 
122
123
  private
@@ -186,16 +187,5 @@ module Imap::Backup
186
187
  def provider_options
187
188
  provider.options.merge(connection_options)
188
189
  end
189
-
190
- # 6.3.8. LIST Command
191
- # An empty ("" string) mailbox name argument is a special request to
192
- # return the hierarchy delimiter and the root name of the name given
193
- # in the reference.
194
- def provider_root
195
- return @provider_root if @provider_root
196
-
197
- root_info = imap.list("", "")[0]
198
- @provider_root = root_info.name
199
- end
200
190
  end
201
191
  end
@@ -11,13 +11,13 @@ module Imap::Backup
11
11
  extend Forwardable
12
12
  include RetryOnError
13
13
 
14
- REQUESTED_ATTRIBUTES = %w[RFC822 FLAGS INTERNALDATE].freeze
14
+ BODY_ATTRIBUTE = "BODY[]".freeze
15
15
  UID_FETCH_RETRY_CLASSES = [EOFError].freeze
16
16
 
17
17
  attr_reader :connection
18
18
  attr_reader :name
19
19
 
20
- delegate imap: :connection
20
+ delegate client: :connection
21
21
 
22
22
  def initialize(connection, name)
23
23
  @connection = connection
@@ -40,20 +40,20 @@ module Imap::Backup
40
40
  def create
41
41
  return if exist?
42
42
 
43
- imap.create(utf7_encoded_name)
43
+ client.create(utf7_encoded_name)
44
44
  end
45
45
 
46
46
  def uid_validity
47
47
  @uid_validity ||=
48
48
  begin
49
49
  examine
50
- imap.responses["UIDVALIDITY"][-1]
50
+ client.responses["UIDVALIDITY"][-1]
51
51
  end
52
52
  end
53
53
 
54
54
  def uids
55
55
  examine
56
- imap.uid_search(["ALL"]).sort
56
+ client.uid_search(["ALL"]).sort
57
57
  rescue FolderNotFound
58
58
  []
59
59
  rescue NoMethodError
@@ -72,15 +72,14 @@ module Imap::Backup
72
72
  examine
73
73
  fetch_data_items =
74
74
  retry_on_error(errors: UID_FETCH_RETRY_CLASSES) do
75
- imap.uid_fetch([uid.to_i], REQUESTED_ATTRIBUTES)
75
+ client.uid_fetch([uid.to_i], [BODY_ATTRIBUTE])
76
76
  end
77
77
  return nil if fetch_data_items.nil?
78
78
 
79
79
  fetch_data_item = fetch_data_items[0]
80
80
  attributes = fetch_data_item.attr
81
- return nil if !attributes.key?("RFC822")
82
81
 
83
- attributes
82
+ attributes[BODY_ATTRIBUTE]
84
83
  rescue FolderNotFound
85
84
  nil
86
85
  end
@@ -88,14 +87,14 @@ module Imap::Backup
88
87
  def append(message)
89
88
  body = message.imap_body
90
89
  date = message.date&.to_time
91
- response = imap.append(utf7_encoded_name, body, nil, date)
90
+ response = client.append(utf7_encoded_name, body, nil, date)
92
91
  extract_uid(response)
93
92
  end
94
93
 
95
94
  private
96
95
 
97
96
  def examine
98
- imap.examine(utf7_encoded_name)
97
+ client.examine(utf7_encoded_name)
99
98
  rescue Net::IMAP::NoResponseError
100
99
  Imap::Backup.logger.warn "Folder '#{name}' does not exist on server"
101
100
  raise FolderNotFound, "Folder '#{name}' does not exist on server"
@@ -9,6 +9,7 @@ module Imap::Backup::CLI::Helpers
9
9
  connections = Imap::Backup::Configuration::List.new
10
10
  account = connections.accounts.find { |a| a[:username] == email }
11
11
  raise "#{email} is not a configured account" if !account
12
+
12
13
  account
13
14
  end
14
15
 
@@ -28,7 +28,10 @@ module Imap::Backup
28
28
  raise "Folder '#{folder_name}' not found" if !folder_serializer
29
29
 
30
30
  max_subject = 60
31
- Kernel.puts format("%-10<uid>s %-#{max_subject}<subject>s - %<date>s", {uid: "UID", subject: "Subject", date: "Date"})
31
+ Kernel.puts format(
32
+ "%-10<uid>s %-#{max_subject}<subject>s - %<date>s",
33
+ {uid: "UID", subject: "Subject", date: "Date"}
34
+ )
32
35
  Kernel.puts "-" * (12 + max_subject + 28)
33
36
 
34
37
  uids = folder_serializer.uids
@@ -5,7 +5,7 @@ module Imap::Backup
5
5
  include Thor::Actions
6
6
  include CLI::Helpers
7
7
 
8
- FAKE_EMAIL = "fake@email.com"
8
+ FAKE_EMAIL = "fake@email.com".freeze
9
9
 
10
10
  desc "ignore-history EMAIL", "Skip downloading emails up to today for all configured folders"
11
11
  def ignore_history(email)
@@ -13,15 +13,18 @@ module Imap::Backup
13
13
 
14
14
  connection.local_folders.each do |serializer, folder|
15
15
  next if !folder.exist?
16
+
16
17
  do_ignore_folder_history(folder, serializer)
17
18
  end
18
19
  end
19
20
 
20
- desc "export-to-thunderbird EMAIL [OPTIONS]",
21
+ desc(
22
+ "export-to-thunderbird EMAIL [OPTIONS]",
21
23
  <<~DOC
22
24
  [Experimental] Copy backed up emails to Thunderbird.
23
25
  A folder called 'imap-backup/EMAIL' is created under 'Local Folders'.
24
26
  DOC
27
+ )
25
28
  method_option(
26
29
  "force",
27
30
  type: :boolean,
@@ -50,7 +53,7 @@ module Imap::Backup
50
53
  end
51
54
  end
52
55
 
53
- connection.local_folders.each do |serializer, folder|
56
+ connection.local_folders.each do |serializer, _folder|
54
57
  Thunderbird::MailboxExporter.new(
55
58
  email, serializer, profile, force: force
56
59
  ).run
@@ -76,10 +79,18 @@ module Imap::Backup
76
79
  end
77
80
 
78
81
  def thunderbird_profile(name = nil)
82
+ profiles = Thunderbird::Profiles.new
79
83
  if name
80
- Thunderbird::Profiles.new.profile(name)
84
+ profiles.profile(name)
81
85
  else
82
- Thunderbird::Profiles.new.default
86
+ if profiles.installs.count > 1
87
+ raise <<~MESSAGE
88
+ Thunderbird has multiple installs, so no default profile exists.
89
+ Please supply a profile name
90
+ MESSAGE
91
+ end
92
+
93
+ profiles.installs[0].default
83
94
  end
84
95
  end
85
96
  end
@@ -0,0 +1,11 @@
1
+ require "imap/backup/client/default"
2
+
3
+ module Imap::Backup
4
+ class Client::AppleMail < Client::Default
5
+ # With Apple Mails's IMAP, passing "/" to list
6
+ # results in an empty list
7
+ def provider_root
8
+ ""
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,51 @@
1
+ require "forwardable"
2
+ require "net/imap"
3
+
4
+ module Imap::Backup
5
+ module Client; end
6
+
7
+ class Client::Default
8
+ extend Forwardable
9
+ def_delegators :imap, *%i(
10
+ append authenticate create disconnect examine
11
+ login responses uid_fetch uid_search
12
+ )
13
+
14
+ attr_reader :args
15
+
16
+ def initialize(*args)
17
+ @args = args
18
+ end
19
+
20
+ def list
21
+ root = provider_root
22
+ mailbox_lists = imap.list(root, "*")
23
+
24
+ return [] if mailbox_lists.nil?
25
+
26
+ mailbox_lists.map { |ml| extract_name(ml) }
27
+ end
28
+
29
+ private
30
+
31
+ def imap
32
+ @imap ||= Net::IMAP.new(*args)
33
+ end
34
+
35
+ def extract_name(mailbox_list)
36
+ utf7_encoded = mailbox_list.name
37
+ Net::IMAP.decode_utf7(utf7_encoded)
38
+ end
39
+
40
+ # 6.3.8. LIST Command
41
+ # An empty ("" string) mailbox name argument is a special request to
42
+ # return the hierarchy delimiter and the root name of the name given
43
+ # in the reference.
44
+ def provider_root
45
+ @provider_root ||= begin
46
+ root_info = imap.list("", "")[0]
47
+ root_info.name
48
+ end
49
+ end
50
+ end
51
+ end
@@ -147,10 +147,12 @@ module Imap::Backup
147
147
 
148
148
  def default_server(username)
149
149
  provider = Email::Provider.for_address(username)
150
- if provider.provider == :default
150
+
151
+ if provider.is_a?(Email::Provider::Default)
151
152
  Kernel.puts "Can't decide provider for email address '#{username}'"
152
153
  return nil
153
154
  end
155
+
154
156
  provider.host
155
157
  end
156
158
  end
@@ -3,7 +3,7 @@ module Imap::Backup
3
3
 
4
4
  module Configuration::ConnectionTester
5
5
  def self.test(account)
6
- Account::Connection.new(account).imap
6
+ Account::Connection.new(account).client
7
7
  "Connection successful"
8
8
  rescue Net::IMAP::NoResponseError
9
9
  "No response"
@@ -1,4 +1,5 @@
1
1
  require "json"
2
+ require "os"
2
3
 
3
4
  module Imap::Backup
4
5
  module Configuration; end
@@ -25,11 +26,12 @@ module Imap::Backup
25
26
  end
26
27
 
27
28
  def save
28
- mkdir_private path
29
+ FileUtils.mkdir(path) if !File.directory?(path)
30
+ make_private(path) if !windows?
29
31
  remove_modified_flags
30
32
  remove_deleted_accounts
31
33
  File.open(pathname, "w") { |f| f.write(JSON.pretty_generate(data)) }
32
- FileUtils.chmod 0o600, pathname
34
+ FileUtils.chmod(0o600, pathname) if !windows?
33
35
  end
34
36
 
35
37
  def accounts
@@ -54,7 +56,7 @@ module Imap::Backup
54
56
  @data ||=
55
57
  begin
56
58
  if File.exist?(pathname)
57
- Utils.check_permissions pathname, 0o600
59
+ Utils.check_permissions(pathname, 0o600) if !windows?
58
60
  contents = File.read(pathname)
59
61
  data = JSON.parse(contents, symbolize_names: true)
60
62
  else
@@ -73,9 +75,12 @@ module Imap::Backup
73
75
  accounts.reject! { |a| a[:delete] }
74
76
  end
75
77
 
76
- def mkdir_private(path)
77
- FileUtils.mkdir(path) if !File.directory?(path)
78
+ def make_private(path)
78
79
  FileUtils.chmod(0o700, path) if Utils.mode(path) != 0o700
79
80
  end
81
+
82
+ def windows?
83
+ OS.windows?
84
+ end
80
85
  end
81
86
  end
@@ -13,16 +13,15 @@ module Imap::Backup
13
13
  count = uids.count
14
14
  Imap::Backup.logger.debug "[#{folder.name}] #{count} new messages"
15
15
  uids.each.with_index do |uid, i|
16
- message = folder.fetch(uid)
16
+ body = folder.fetch(uid)
17
17
  log_prefix = "[#{folder.name}] uid: #{uid} (#{i + 1}/#{count}) -"
18
- if message.nil?
18
+ if body.nil?
19
19
  Imap::Backup.logger.debug("#{log_prefix} not available - skipped")
20
20
  next
21
21
  end
22
22
  Imap::Backup.logger.debug(
23
- "#{log_prefix} #{message['RFC822'].size} bytes"
23
+ "#{log_prefix} #{body.size} bytes"
24
24
  )
25
- body = message["RFC822"]
26
25
  serializer.save(uid, body)
27
26
  end
28
27
  end
@@ -1,10 +1,9 @@
1
1
  require "thunderbird/local_folder"
2
- require "thunderbird/mailbox"
3
2
  require "thunderbird/profiles"
4
3
 
5
4
  module Imap::Backup
6
5
  class Thunderbird::MailboxExporter
7
- EXPORT_PREFIX = "imap-backup"
6
+ EXPORT_PREFIX = "imap-backup".freeze
8
7
 
9
8
  attr_reader :email
10
9
  attr_reader :serializer
@@ -19,28 +18,29 @@ module Imap::Backup
19
18
  end
20
19
 
21
20
  def run
22
- local_folder.set_up
21
+ local_folder_ok = local_folder.set_up
22
+ return if !local_folder_ok
23
23
 
24
- if mailbox.msf_exists?
24
+ if local_folder.msf_exists?
25
25
  if force
26
- Kernel.puts "Deleting '#{mailbox.msf_path}' as --force option was supplied"
27
- File.unlink mailbox.msf_path
26
+ Kernel.puts "Deleting '#{local_folder.msf_path}' as --force option was supplied"
27
+ File.unlink local_folder.msf_path
28
28
  else
29
- Kernel.puts "Skipping export of '#{folder.name}' as '#{mailbox.msf_path}' exists"
29
+ Kernel.puts "Skipping export of '#{serializer.folder}' as '#{local_folder.msf_path}' exists"
30
30
  return false
31
31
  end
32
32
  end
33
33
 
34
- if mailbox.exists?
34
+ if local_folder.exists?
35
35
  if force
36
- Kernel.puts "Overwriting '#{mailbox.path}' as --force option was supplied"
36
+ Kernel.puts "Overwriting '#{local_folder.path}' as --force option was supplied"
37
37
  else
38
- Kernel.puts "Skipping export of '#{folder.name}' as '#{mailbox.path}' exists"
38
+ Kernel.puts "Skipping export of '#{serializer.folder}' as '#{local_folder.path}' exists"
39
39
  return false
40
40
  end
41
41
  end
42
42
 
43
- FileUtils.cp serializer.mbox_pathname, mailbox.path
43
+ FileUtils.cp serializer.mbox_pathname, local_folder.full_path
44
44
 
45
45
  true
46
46
  end
@@ -49,23 +49,10 @@ module Imap::Backup
49
49
 
50
50
  def local_folder
51
51
  @local_folder ||= begin
52
- folder_path = File.dirname(serializer.folder)
53
52
  top_level_folders = [EXPORT_PREFIX, email]
54
- prefixed_folder_path =
55
- if folder_path == "."
56
- File.join(top_level_folders)
57
- else
58
- File.join(top_level_folders, folder_path)
59
- end
53
+ prefixed_folder_path = File.join(top_level_folders, serializer.folder)
60
54
  Thunderbird::LocalFolder.new(profile, prefixed_folder_path)
61
55
  end
62
56
  end
63
-
64
- def mailbox
65
- @mailbox ||= begin
66
- mailbox_name = File.basename(serializer.folder)
67
- Thunderbird::Mailbox.new(local_folder, mailbox_name)
68
- end
69
- end
70
57
  end
71
58
  end
@@ -3,7 +3,7 @@ module Imap; end
3
3
  module Imap::Backup
4
4
  MAJOR = 4
5
5
  MINOR = 0
6
- REVISION = 2
6
+ REVISION = 3
7
7
  PRE = nil
8
8
  VERSION = [MAJOR, MINOR, REVISION, PRE].compact.map(&:to_s).join(".")
9
9
  end
@@ -0,0 +1,16 @@
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