imap-backup 8.0.2 → 9.0.0.rc1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 31b3a3ccf051c6496e8b4fde5eb0b062927fc8a0cb0c605dd597bc1289dd77e1
4
- data.tar.gz: f7a7a88cb51f2ebe01e5debd4a25df4df8adf4ee1a5fd2480532c948d51e382b
3
+ metadata.gz: 3a95742a7ae3b07a12f7cb95d50bcea360530ee351edbca8d9b93e5c4579090a
4
+ data.tar.gz: 9d7d43ba0f44f13a19272214dfe8ca265c72f7d1173ccf67c4d4a873de007a81
5
5
  SHA512:
6
- metadata.gz: 47377d324d8a4f4bf0853ac12f6e972107bbb2d215f4916bd5a6ec301870ef6fad2eb646325dba127dd7bb8ca02f6abe72d2bfeccc139bac87c9df38a55d498a
7
- data.tar.gz: 2a07b644b145263f41394f2f96590a0003381911389238f242f973236828ded448c169ed043ec7453d8bd0acc942ecb3d210e298b46d975c08b015794b7f4445
6
+ metadata.gz: 155eeb475d56b03bc8012fc8b9b2882fbd8bcaad4366ee2119952f710de79d94a6709c81185ccc49b4f20f6d333523272de4cfa3742c1ff05f797830d1cb916e
7
+ data.tar.gz: dc6c0ce95c22c81512eb71791f6a75ecc8fe35f011e48fd0d68266771fac96f234664f22316fd1e98fbfc93397713f60375555442577dc0977eedcabfc2cf1ea
@@ -0,0 +1,16 @@
1
+ # Delimiters and Prefixes
2
+
3
+ A simple folder name is `Friends`.
4
+
5
+ Most email servers allow you to put folders inside other folders.
6
+
7
+ On most email servers, the parts of a folder's name are separated with a `/` character.
8
+ So you might have `People/Friends`.
9
+
10
+ On the other hand, some email servers use a `.`, giving `People.Friends`.
11
+
12
+ Some email servers keep most email in a parent folder, often `INBOX`, so the above folder
13
+ would be `INBOX/People/Friends`.
14
+
15
+ The `migrate` and `mirror` commands provide options to help "translate" between
16
+ the behaviour of the source and destination servers.
data/docs/restore.md CHANGED
@@ -25,6 +25,4 @@ is already on the server is skipped.
25
25
 
26
26
  ## How do I restore to a different service?
27
27
 
28
- 1. Run setup and add the new server, (but don't run any backups),
29
- 2. Rename of the existing backup directory to match the new email address,
30
- 3. Run the restore.
28
+ It is best to use the `migrate` command in this case.
data/docs/setup.md CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  ## Set the server for a Google Apps account
4
4
 
5
- Use imap.gmail.com
5
+ Use `imap.gmail.com` as the 'server' setting.
@@ -0,0 +1,96 @@
1
+ module Imap::Backup
2
+ class CLI::FolderEnumerator
3
+ attr_reader :destination
4
+ attr_reader :destination_delimiter
5
+ attr_reader :source
6
+ attr_reader :source_delimiter
7
+
8
+ def initialize(
9
+ destination:,
10
+ source:,
11
+ destination_delimiter: "/",
12
+ destination_prefix: "",
13
+ source_delimiter: "/",
14
+ source_prefix: ""
15
+ )
16
+ @destination = destination
17
+ @destination_delimiter = destination_delimiter
18
+ @destination_prefix = destination_prefix
19
+ @source = source
20
+ @source_delimiter = source_delimiter
21
+ @source_prefix = source_prefix
22
+ end
23
+
24
+ def each
25
+ return enum_for(:each) if !block_given?
26
+
27
+ glob = File.join(source_local_path, "**", "*.imap")
28
+ Pathname.glob(glob) do |path|
29
+ name = source_folder_name(path)
30
+ serializer = Serializer.new(source_local_path, name)
31
+ folder = destination_folder_for(name)
32
+ yield serializer, folder
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def destination_prefix_clipped
39
+ @destination_prefix_clipped ||=
40
+ if @destination_prefix.end_with?(destination_delimiter)
41
+ @destination_prefix[0..-2]
42
+ else
43
+ @destination_prefix
44
+ end
45
+ end
46
+
47
+ def source_prefix_clipped
48
+ @source_prefix_clipped ||=
49
+ if @source_prefix.end_with?(source_delimiter)
50
+ @source_prefix[0..-2]
51
+ else
52
+ @source_prefix
53
+ end
54
+ end
55
+
56
+ def destination_folder_for(name)
57
+ parts = name.split(source_delimiter)
58
+ no_source_prefix =
59
+ if source_prefix_clipped != "" && parts.first == source_prefix_clipped
60
+ parts[1..]
61
+ else
62
+ parts
63
+ end
64
+
65
+ with_destination_prefix =
66
+ if destination_prefix_clipped && destination_prefix_clipped != ""
67
+ no_source_prefix.unshift(destination_prefix_clipped)
68
+ else
69
+ no_source_prefix
70
+ end
71
+
72
+ destination_name = with_destination_prefix.join(destination_delimiter)
73
+
74
+ Account::Folder.new(
75
+ destination.connection,
76
+ destination_name
77
+ )
78
+ end
79
+
80
+ def source_local_path
81
+ source.local_path
82
+ end
83
+
84
+ def source_folder_name(imap_pathname)
85
+ base = Pathname.new(source_local_path)
86
+ imap_name = imap_pathname.relative_path_from(base).to_s
87
+ dir = File.dirname(imap_name)
88
+ stripped = File.basename(imap_name, ".imap")
89
+ if dir == "."
90
+ stripped
91
+ else
92
+ File.join(dir, stripped)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,3 +1,4 @@
1
+ require "imap/backup/cli/folder_enumerator"
1
2
  require "imap/backup/migrator"
2
3
 
3
4
  module Imap::Backup
@@ -5,10 +6,12 @@ module Imap::Backup
5
6
  include Thor::Actions
6
7
  include CLI::Helpers
7
8
 
9
+ attr_reader :destination_delimiter
8
10
  attr_reader :destination_email
9
11
  attr_reader :destination_prefix
10
12
  attr_reader :config_path
11
13
  attr_reader :reset
14
+ attr_reader :source_delimiter
12
15
  attr_reader :source_email
13
16
  attr_reader :source_prefix
14
17
 
@@ -16,15 +19,19 @@ module Imap::Backup
16
19
  source_email,
17
20
  destination_email,
18
21
  config: nil,
22
+ destination_delimiter: "/",
19
23
  destination_prefix: "",
20
24
  reset: false,
25
+ source_delimiter: "/",
21
26
  source_prefix: ""
22
27
  )
23
28
  super([])
29
+ @destination_delimiter = destination_delimiter
24
30
  @destination_email = destination_email
25
31
  @destination_prefix = destination_prefix
26
32
  @config_path = config
27
33
  @reset = reset
34
+ @source_delimiter = source_delimiter
28
35
  @source_email = source_email
29
36
  @source_prefix = source_prefix
30
37
  end
@@ -51,62 +58,28 @@ module Imap::Backup
51
58
  @config ||= load_config(config: config_path)
52
59
  end
53
60
 
54
- def destination_account
55
- config.accounts.find { |a| a.username == destination_email }
61
+ def enumerator_options
62
+ {
63
+ destination: destination_account,
64
+ destination_delimiter: destination_delimiter,
65
+ destination_prefix: destination_prefix,
66
+ source: source_account,
67
+ source_delimiter: source_delimiter,
68
+ source_prefix: source_prefix
69
+ }
56
70
  end
57
71
 
58
72
  def folders
59
- return enum_for(:folders) if !block_given?
60
-
61
- glob = File.join(source_local_path, "**", "*.imap")
62
- Pathname.glob(glob) do |path|
63
- name = source_folder_name(path)
64
- serializer = Serializer.new(source_local_path, name)
65
- folder = folder_for(name)
66
- yield serializer, folder
67
- end
73
+ CLI::FolderEnumerator.new(**enumerator_options)
68
74
  end
69
75
 
70
- def folder_for(source_folder)
71
- no_source_prefix =
72
- if source_prefix != "" && source_folder.start_with?(source_prefix)
73
- source_folder.delete_prefix(source_prefix)
74
- else
75
- source_folder.to_s
76
- end
77
-
78
- with_destination_prefix =
79
- if destination_prefix && destination_prefix != ""
80
- destination_prefix + no_source_prefix
81
- else
82
- no_source_prefix
83
- end
84
-
85
- Account::Folder.new(
86
- destination_account.connection,
87
- with_destination_prefix
88
- )
89
- end
90
-
91
- def source_local_path
92
- source_account.local_path
76
+ def destination_account
77
+ config.accounts.find { |a| a.username == destination_email }
93
78
  end
94
79
 
95
80
  def source_account
96
81
  config.accounts.find { |a| a.username == source_email }
97
82
  end
98
-
99
- def source_folder_name(imap_pathname)
100
- base = Pathname.new(source_local_path)
101
- imap_name = imap_pathname.relative_path_from(base).to_s
102
- dir = File.dirname(imap_name)
103
- stripped = File.basename(imap_name, ".imap")
104
- if dir == "."
105
- stripped
106
- else
107
- File.join(dir, stripped)
108
- end
109
- end
110
83
  end
111
84
  end
112
85
  end
@@ -1,3 +1,4 @@
1
+ require "imap/backup/cli/folder_enumerator"
1
2
  require "imap/backup/mirror"
2
3
 
3
4
  module Imap::Backup
@@ -5,9 +6,11 @@ module Imap::Backup
5
6
  include Thor::Actions
6
7
  include CLI::Helpers
7
8
 
9
+ attr_reader :destination_delimiter
8
10
  attr_reader :destination_email
9
11
  attr_reader :destination_prefix
10
12
  attr_reader :config_path
13
+ attr_reader :source_delimiter
11
14
  attr_reader :source_email
12
15
  attr_reader :source_prefix
13
16
 
@@ -15,13 +18,17 @@ module Imap::Backup
15
18
  source_email,
16
19
  destination_email,
17
20
  config: nil,
21
+ destination_delimiter: "/",
18
22
  destination_prefix: "",
23
+ source_delimiter: "/",
19
24
  source_prefix: ""
20
25
  )
21
26
  super([])
27
+ @destination_delimiter = destination_delimiter
22
28
  @destination_email = destination_email
23
29
  @destination_prefix = destination_prefix
24
30
  @config_path = config
31
+ @source_delimiter = source_delimiter
25
32
  @source_email = source_email
26
33
  @source_prefix = source_prefix
27
34
  end
@@ -61,62 +68,28 @@ module Imap::Backup
61
68
  @config = load_config(config: config_path)
62
69
  end
63
70
 
64
- def destination_account
65
- config.accounts.find { |a| a.username == destination_email }
71
+ def enumerator_options
72
+ {
73
+ destination: destination_account,
74
+ destination_delimiter: destination_delimiter,
75
+ destination_prefix: destination_prefix,
76
+ source: source_account,
77
+ source_delimiter: source_delimiter,
78
+ source_prefix: source_prefix
79
+ }
66
80
  end
67
81
 
68
82
  def folders
69
- return enum_for(:folders) if !block_given?
70
-
71
- glob = File.join(source_local_path, "**", "*.imap")
72
- Pathname.glob(glob) do |path|
73
- name = source_folder_name(path)
74
- serializer = Serializer.new(source_local_path, name)
75
- folder = folder_for(name)
76
- yield serializer, folder
77
- end
78
- end
79
-
80
- def folder_for(source_folder)
81
- no_source_prefix =
82
- if source_prefix != "" && source_folder.start_with?(source_prefix)
83
- source_folder.delete_prefix(source_prefix)
84
- else
85
- source_folder.to_s
86
- end
87
-
88
- with_destination_prefix =
89
- if destination_prefix && destination_prefix != ""
90
- destination_prefix + no_source_prefix
91
- else
92
- no_source_prefix
93
- end
94
-
95
- Account::Folder.new(
96
- destination_account.connection,
97
- with_destination_prefix
98
- )
83
+ CLI::FolderEnumerator.new(**enumerator_options)
99
84
  end
100
85
 
101
- def source_local_path
102
- source_account.local_path
86
+ def destination_account
87
+ config.accounts.find { |a| a.username == destination_email }
103
88
  end
104
89
 
105
90
  def source_account
106
91
  config.accounts.find { |a| a.username == source_email }
107
92
  end
108
-
109
- def source_folder_name(imap_pathname)
110
- base = Pathname.new(source_local_path)
111
- imap_name = imap_pathname.relative_path_from(base).to_s
112
- dir = File.dirname(imap_name)
113
- stripped = File.basename(imap_name, ".imap")
114
- if dir == "."
115
- stripped
116
- else
117
- File.join(dir, stripped)
118
- end
119
- end
120
93
  end
121
94
  end
122
95
  end
@@ -69,9 +69,12 @@ module Imap::Backup
69
69
  All emails which have been backed up for the "source account" (SOURCE_EMAIL) are
70
70
  uploaded to the "destination account" (DESTINATION_EMAIL).
71
71
 
72
- When one or other account has namespaces (i.e. prefixes like "INBOX."),
72
+ When one or other account has namespaces (i.e. prefixes like "INBOX"),
73
73
  use the `--source-prefix=` and/or `--destination-prefix=` options.
74
74
 
75
+ When one or other account uses a delimiter other than `/` (i.e. `.`),
76
+ use the `--source-delimiter=` and/or `--destination-delimiter=` options.
77
+
75
78
  Usually, you should migrate to an account with empty folders.
76
79
 
77
80
  Before migrating each folder, `imap-backup` checks if the destination
@@ -86,6 +89,11 @@ module Imap::Backup
86
89
  config_option
87
90
  quiet_option
88
91
  verbose_option
92
+ method_option(
93
+ "destination-delimiter",
94
+ type: :string,
95
+ desc: "the delimiter for destination folder names"
96
+ )
89
97
  method_option(
90
98
  "destination-prefix",
91
99
  type: :string,
@@ -98,6 +106,11 @@ module Imap::Backup
98
106
  desc: "DANGER! This option deletes all messages from destination folders before uploading",
99
107
  aliases: ["-r"]
100
108
  )
109
+ method_option(
110
+ "source-delimiter",
111
+ type: :string,
112
+ desc: "the delimiter for source folder names"
113
+ )
101
114
  method_option(
102
115
  "source-prefix",
103
116
  type: :string,
@@ -132,12 +145,22 @@ module Imap::Backup
132
145
  config_option
133
146
  quiet_option
134
147
  verbose_option
148
+ method_option(
149
+ "destination-delimiter",
150
+ type: :string,
151
+ desc: "the delimiter for destination folder names"
152
+ )
135
153
  method_option(
136
154
  "destination-prefix",
137
155
  type: :string,
138
156
  desc: "the prefix (namespace) to add to destination folder names",
139
157
  aliases: ["-d"]
140
158
  )
159
+ method_option(
160
+ "source-delimiter",
161
+ type: :string,
162
+ desc: "the delimiter for source folder names"
163
+ )
141
164
  method_option(
142
165
  "source-prefix",
143
166
  type: :string,
@@ -1,9 +1,9 @@
1
1
  module Imap; end
2
2
 
3
3
  module Imap::Backup
4
- MAJOR = 8
4
+ MAJOR = 9
5
5
  MINOR = 0
6
- REVISION = 2
7
- PRE = nil
6
+ REVISION = 0
7
+ PRE = "rc1".freeze
8
8
  VERSION = [MAJOR, MINOR, REVISION, PRE].compact.map(&:to_s).join(".")
9
9
  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: 8.0.2
4
+ version: 9.0.0.rc1
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-12-12 00:00:00.000000000 Z
11
+ date: 2022-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: highline
@@ -218,6 +218,7 @@ files:
218
218
  - README.md
219
219
  - bin/imap-backup
220
220
  - docs/configuration.md
221
+ - docs/delimiters-and-prefixes.md
221
222
  - docs/development.md
222
223
  - docs/restore.md
223
224
  - docs/setup.md
@@ -240,6 +241,7 @@ files:
240
241
  - lib/imap/backup/account/folder.rb
241
242
  - lib/imap/backup/cli.rb
242
243
  - lib/imap/backup/cli/backup.rb
244
+ - lib/imap/backup/cli/folder_enumerator.rb
243
245
  - lib/imap/backup/cli/helpers.rb
244
246
  - lib/imap/backup/cli/local.rb
245
247
  - lib/imap/backup/cli/migrate.rb
@@ -299,9 +301,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
299
301
  version: '2.6'
300
302
  required_rubygems_version: !ruby/object:Gem::Requirement
301
303
  requirements:
302
- - - ">="
304
+ - - ">"
303
305
  - !ruby/object:Gem::Version
304
- version: '0'
306
+ version: 1.3.1
305
307
  requirements: []
306
308
  rubygems_version: 3.3.7
307
309
  signing_key: