imap-backup 16.1.0 → 16.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf6997d289ca5babbecd35e683ede921273300779f3f7dac95e247c0478f1814
4
- data.tar.gz: '009892c47699a0cc94ff28c2d3ea7346915732b7dc86c7231b7e606302219888'
3
+ metadata.gz: 773e831319b208a930da663eae601d32236281104f4712960bfdb42dbc9d7794
4
+ data.tar.gz: 0da5b5f25c8e89022b387f08e5a5bee101284067fa6c5b9db7b35c95890e92da
5
5
  SHA512:
6
- metadata.gz: 46bdbccf9be3efade25e500f6c67f37de4fc0a0aa8514b55f8eabf7e1171042b5be87d029f37d9cb449c23d1fcf0d5fd2a20c2e8595c6149eff0c20f89e6b3d3
7
- data.tar.gz: d507a668897c325e2cc771d69b083f9929247b839b55d1fe86bfaeac3ee8be40df43b9f634d4f97c0188fe3bcbfba666456a9131236103455020fb45ecec9d61
6
+ metadata.gz: ccd49d19ec804c70c5aaaadcc40129ad8fcccf129c8de01c2c9e74cec0068bd2268fe6ea4e79f1d313539069e727891da9d0fc16e91a9e64c2301b00248204d8
7
+ data.tar.gz: 92553f44cf28d9c3a19b4cc3ff63fbd5a2dae59056663e9222ba0481ac6768d77f91c33e6d2aec652e451fbc1a5c9ae8f3933fcc2b9d601a5d3ce04865720af3
@@ -44,7 +44,7 @@ module Imap::Backup
44
44
  # The name of the download strategy to adopt during backups
45
45
  # @return [String]
46
46
  attr_accessor :download_strategy
47
- # Should 'Seen' flags be cached before fetchiong emails and
47
+ # Should 'Seen' flags be cached before fetching emails and
48
48
  # rewritten to the server afterwards?
49
49
  #
50
50
  # Some IMAP providers, notably Apple Mail, set the '\Seen' flag
@@ -57,6 +57,12 @@ module Imap::Backup
57
57
  # mark messages as '\Seen' when accessed).
58
58
  # @return [Boolean]
59
59
  attr_reader :reset_seen_flags_after_fetch
60
+ # The status of the account - controls backup and migration behavior
61
+ # "active" - the account is available for backup and migration,
62
+ # "archived" - the account is available for migration, but not backup,
63
+ # "offline" - the account is not available for backup or migration.
64
+ # @return [String] one of "active" (the default), "archived", or "offline"
65
+ attr_reader :status
60
66
 
61
67
  def initialize(options)
62
68
  check_options!(options)
@@ -72,6 +78,7 @@ module Imap::Backup
72
78
  @download_strategy = options[:download_strategy]
73
79
  @multi_fetch_size_orignal = options[:multi_fetch_size]
74
80
  @reset_seen_flags_after_fetch = options[:reset_seen_flags_after_fetch]
81
+ @status = options[:status] || DEFAULT_STATUS
75
82
  @client = nil
76
83
  @changes = {}
77
84
  @marked_for_deletion = false
@@ -122,7 +129,11 @@ module Imap::Backup
122
129
 
123
130
  # @return [Hash] all Account data for serialization
124
131
  def to_h
125
- h = {username: @username, password: @password}
132
+ h = {
133
+ username: @username,
134
+ password: @password,
135
+ status: status
136
+ }
126
137
  h[:local_path] = @local_path if @local_path
127
138
  h[:folders] = @folders if @folders
128
139
  h[:folder_blacklist] = true if @folder_blacklist
@@ -230,6 +241,44 @@ module Imap::Backup
230
241
  update(:reset_seen_flags_after_fetch, value)
231
242
  end
232
243
 
244
+ # Sets the status attribute and marks it as modified, storing the original value
245
+ #
246
+ # @param value [String] one of "active", "archived", or "offline"
247
+ # @raise [ArgumentError] if the value is not a valid status
248
+ # @return [void]
249
+ def status=(value)
250
+ if !VALID_STATUSES.include?(value)
251
+ raise ArgumentError, "status must be one of: #{VALID_STATUSES.join(', ')}"
252
+ end
253
+
254
+ update(:status, value)
255
+ end
256
+
257
+ # @return [Boolean] true if the account is active
258
+ def active?
259
+ @status == "active"
260
+ end
261
+
262
+ # @return [Boolean] true if the account is archived
263
+ def archived?
264
+ @status == "archived"
265
+ end
266
+
267
+ # @return [Boolean] true if the account is offline
268
+ def offline?
269
+ @status == "offline"
270
+ end
271
+
272
+ # @return [Boolean] true if the account is available for backup operations
273
+ def available_for_backup?
274
+ active?
275
+ end
276
+
277
+ # @return [Boolean] true if the account is available for migration operations
278
+ def available_for_migration?
279
+ active? || archived?
280
+ end
281
+
233
282
  private
234
283
 
235
284
  attr_reader :changes
@@ -237,9 +286,11 @@ module Imap::Backup
237
286
  REQUIRED_ATTRIBUTES = %i[password username].freeze
238
287
  OPTIONAL_ATTRIBUTES = %i[
239
288
  connection_options download_strategy folders folder_blacklist local_path mirror_mode
240
- multi_fetch_size reset_seen_flags_after_fetch server
289
+ multi_fetch_size reset_seen_flags_after_fetch server status
241
290
  ].freeze
242
291
  KNOWN_ATTRIBUTES = REQUIRED_ATTRIBUTES + OPTIONAL_ATTRIBUTES
292
+ VALID_STATUSES = %w[active archived offline].freeze
293
+ DEFAULT_STATUS = "active".freeze
243
294
 
244
295
  def check_options!(options)
245
296
  missing_required = REQUIRED_ATTRIBUTES - options.keys
@@ -28,6 +28,8 @@ module Imap::Backup
28
28
  config = load_config(**options)
29
29
  exit_code = nil
30
30
  accounts = requested_accounts(config)
31
+ # Filter to only include accounts available for backup
32
+ accounts = accounts.select(&:available_for_backup?)
31
33
  if accounts.none?
32
34
  Logger.logger.warn "No matching accounts found to backup"
33
35
  return
@@ -88,6 +88,16 @@ module Imap::Backup
88
88
  raise "Account '#{destination_email}' does not exist" if !destination_account
89
89
 
90
90
  raise "Account '#{source_email}' does not exist" if !source_account
91
+
92
+ if !source_account.available_for_migration?
93
+ raise "Account '#{source_email}' is not available for migration " \
94
+ "(status: #{source_account.status})"
95
+ end
96
+
97
+ return if destination_account.available_for_migration?
98
+
99
+ raise "Account '#{destination_email}' is not available for migration " \
100
+ "(status: #{destination_account.status})"
91
101
  end
92
102
 
93
103
  def choose_prefixes_and_delimiters!
@@ -30,7 +30,8 @@ module Imap::Backup
30
30
  path,
31
31
  folders,
32
32
  multi_fetch,
33
- reset_seen_flags_after_fetch
33
+ reset_seen_flags_after_fetch,
34
+ status_row
34
35
  ].compact
35
36
 
36
37
  menu.header = <<~HEADER.chomp
@@ -127,6 +128,12 @@ module Imap::Backup
127
128
  ["changes to unread flags will be reset during download"]
128
129
  end
129
130
 
131
+ def status_row
132
+ return nil if account.status == "active"
133
+
134
+ ["status", account.status]
135
+ end
136
+
130
137
  def format_rows(rows)
131
138
  largest_label, _value = rows.max_by do |(label, value)|
132
139
  if value
@@ -56,6 +56,7 @@ module Imap::Backup
56
56
  choose_folders menu
57
57
  modify_multi_fetch_size menu
58
58
  toggle_reset_seen_flags_after_fetch menu
59
+ rotate_status menu
59
60
  delete_account menu
60
61
  menu.choice("(q) return to main menu") { throw :done }
61
62
  menu.hidden("quit") { throw :done }
@@ -151,6 +152,19 @@ module Imap::Backup
151
152
  end
152
153
  end
153
154
 
155
+ def rotate_status(menu)
156
+ current_status = account.status
157
+ statuses = %w[active archived offline]
158
+ current_index = statuses.index(current_status) || 0
159
+ next_index = (current_index + 1) % statuses.length
160
+ next_status = statuses[next_index]
161
+
162
+ menu_item = "change status (currently: #{current_status} -> #{next_status})"
163
+ menu.choice(menu_item) do
164
+ account.status = next_status
165
+ end
166
+ end
167
+
154
168
  def test_connection(menu)
155
169
  menu.choice("test connection") do
156
170
  result = Setup::ConnectionTester.new(account).test
@@ -4,7 +4,7 @@ module Imap::Backup
4
4
  # @private
5
5
  MAJOR = 16
6
6
  # @private
7
- MINOR = 1
7
+ MINOR = 2
8
8
  # @private
9
9
  REVISION = 0
10
10
  # @private
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: 16.1.0
4
+ version: 16.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Yates
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-02 00:00:00.000000000 Z
11
+ date: 2025-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: highline