Class: Imap::Backup::Serializer

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/imap/backup/serializer.rb,
lib/imap/backup/serializer/imap.rb,
lib/imap/backup/serializer/mbox.rb,
lib/imap/backup/serializer/message.rb,
lib/imap/backup/serializer/appender.rb,
lib/imap/backup/serializer/directory.rb,
lib/imap/backup/serializer/transaction.rb,
lib/imap/backup/serializer/folder_maker.rb,
lib/imap/backup/serializer/integrity_checker.rb,
lib/imap/backup/serializer/version2_migrator.rb,
lib/imap/backup/serializer/message_enumerator.rb,
lib/imap/backup/serializer/permission_checker.rb,
lib/imap/backup/serializer/unused_name_finder.rb,
lib/imap/backup/serializer/delayed_metadata_serializer.rb

Overview

Handles serialization for a folder

Defined Under Namespace

Classes: Appender, DelayedMetadataSerializer, Directory, FolderIntegrityError, FolderMaker, Imap, IntegrityChecker, Mbox, Message, MessageEnumerator, PermissionChecker, Transaction, UnusedNameFinder, Version2Migrator

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, folder) ⇒ Serializer

Returns a new instance of Serializer.

Parameters:

  • path (String)

    an account’s backup path

  • folder (String)

    a folder name



74
75
76
77
78
# File 'lib/imap/backup/serializer.rb', line 74

def initialize(path, folder)
  @path = path
  @folder = folder
  @validated = nil
end

Instance Attribute Details

#folderString (readonly)

Returns a folder name.

Returns:

  • (String)

    a folder name



68
69
70
# File 'lib/imap/backup/serializer.rb', line 68

def folder
  @folder
end

#pathString (readonly)

Returns an account’s backup path.

Returns:

  • (String)

    an account’s backup path



70
71
72
# File 'lib/imap/backup/serializer.rb', line 70

def path
  @path
end

Class Method Details

.folder_path_for(path:, folder:) ⇒ String

Returns the full path to a serialized folder (without file extensions).

Parameters:

  • path (String)

    an account’s backup path

  • folder (String)

    a folder name

Returns:

  • (String)

    the full path to a serialized folder (without file extensions)



23
24
25
26
# File 'lib/imap/backup/serializer.rb', line 23

def self.folder_path_for(path:, folder:)
  relative = File.join(path, folder)
  File.expand_path(relative)
end

Instance Method Details

#append(uid, message, flags) ⇒ void

This method returns an undefined value.

Appends a message to the serialized data

Parameters:

  • uid (Integer)

    the message’s UID

  • message (Integer)

    the message text

  • flags (Array[Symbol])

    the message’s flags



173
174
175
176
177
178
# File 'lib/imap/backup/serializer.rb', line 173

def append(uid, message, flags)
  validate!

  appender = Serializer::Appender.new(folder: sanitized, imap: imap, mbox: mbox)
  appender.append(uid: uid, message: message, flags: flags)
end

#apply_uid_validity(value) ⇒ String?

Sets the folder’s UID validity. If the existing value is nil, it sets the new value and ensures that both the metadata file and the mailbox are saved. If the supplied value is the same as the existing value, it does nothing. If the supplied valued is different to the existing value, it renames the existing folder to a new name, and creates a new folder with the supplied value.

Parameters:

  • value (Integer)

    The new UID validity value

Returns:

  • (String, nil)

    The name of the new folder



142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/imap/backup/serializer.rb', line 142

def apply_uid_validity(value)
  validate!

  case
  when uid_validity.nil?
    internal_force_uid_validity(value)
    nil
  when uid_validity == value
    # NOOP
    nil
  else
    apply_new_uid_validity(value)
  end
end

#check_integrity!void

This method returns an undefined value.

Checks that the folder’s data is stored correctly



117
118
119
# File 'lib/imap/backup/serializer.rb', line 117

def check_integrity!
  IntegrityChecker.new(imap: imap, mbox: mbox).run
end

#deletevoid

This method returns an undefined value.

Deletes the serialized data



123
124
125
126
127
# File 'lib/imap/backup/serializer.rb', line 123

def delete
  imap.delete
  mbox.delete
  reload
end

#each_message(required_uids = nil, &block) ⇒ Enumerator, void

Enumerates over a series of messages. When called without a block, returns an Enumerator

Parameters:

  • required_uids (Array<Integer>) (defaults to: nil)

    the UIDs of the message to enumerate over

Returns:

  • (Enumerator, void)


196
197
198
199
200
201
202
203
204
205
# File 'lib/imap/backup/serializer.rb', line 196

def each_message(required_uids = nil, &block)
  return enum_for(:each_message, required_uids) if !block

  required_uids ||= uids

  validate!

  enumerator = Serializer::MessageEnumerator.new(imap: imap)
  enumerator.run(uids: required_uids, &block)
end

#filter(&block) ⇒ void

This method returns an undefined value.

Calls the supplied block on each message in the folder and discards those for which the block returns a false result

Parameters:

  • block (block)

    the block to call



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/imap/backup/serializer.rb', line 211

def filter(&block)
  temp_name = Serializer::UnusedNameFinder.new(serializer: self).run
  temp_folder_path = self.class.folder_path_for(path: path, folder: temp_name)
  new_mbox = Serializer::Mbox.new(temp_folder_path)
  new_imap = Serializer::Imap.new(temp_folder_path)
  new_imap.uid_validity = imap.uid_validity
  appender = Serializer::Appender.new(folder: temp_name, imap: new_imap, mbox: new_mbox)
  enumerator = Serializer::MessageEnumerator.new(imap: imap)
  enumerator.run(uids: uids) do |message|
    keep = block.call(message)
    appender.append(uid: message.uid, message: message.body, flags: message.flags) if keep
  end
  imap.delete
  new_imap.rename imap.folder_path
  mbox.delete
  new_mbox.rename mbox.folder_path
  reload
end

#folder_pathString

Returns the path to the serialized folder (without file extensions).

Returns:

  • (String)

    the path to the serialized folder (without file extensions)



231
232
233
# File 'lib/imap/backup/serializer.rb', line 231

def folder_path
  self.class.folder_path_for(path: path, folder: sanitized)
end

#force_uid_validity(value) ⇒ void

This method returns an undefined value.

Overwrites the UID validity of the folder and ensures that both the metadata file and the mailbox are saved.

Parameters:

  • value (Integer)

    the new UID validity



162
163
164
165
166
# File 'lib/imap/backup/serializer.rb', line 162

def force_uid_validity(value)
  validate!

  internal_force_uid_validity(value)
end

#get(uid) ⇒ Serializer::Message

Get message metadata

Parameters:

  • uid (Integer)

    a message UID

Returns:



35
36
37
38
# File 'lib/imap/backup/serializer.rb', line 35

def get(uid)
  validate!
  imap.get(uid)
end

#messagesArray<Hash>

Returns:

  • (Array<Hash>)


41
42
43
44
# File 'lib/imap/backup/serializer.rb', line 41

def messages
  validate!
  imap.messages
end

#reloadvoid

This method returns an undefined value.

Forces a reload of the serialized files



242
243
244
245
# File 'lib/imap/backup/serializer.rb', line 242

def reload
  @imap = nil
  @mbox = nil
end

#sanitizedString

Returns The folder’s name adapted for using as a file name.

Returns:

  • (String)

    The folder’s name adapted for using as a file name



236
237
238
# File 'lib/imap/backup/serializer.rb', line 236

def sanitized
  @sanitized ||= Naming.to_local_path(folder)
end

#transaction(&block) ⇒ void

This method returns an undefined value.

Calls the supplied block. This method is present so that this class implements the same interface as DelayedMetadataSerializer

Parameters:

  • block (block)

    the block that is wrapped by the transaction



86
87
88
# File 'lib/imap/backup/serializer.rb', line 86

def transaction(&block)
  block.call
end

#uid_validityInteger

Returns the UID validity for the folder.

Returns:

  • (Integer)

    the UID validity for the folder



47
48
49
50
# File 'lib/imap/backup/serializer.rb', line 47

def uid_validity
  validate!
  imap.uid_validity
end

#uidsArray<Integer>

Returns The uids of all messages.

Returns:

  • (Array<Integer>)

    The uids of all messages



53
54
55
56
# File 'lib/imap/backup/serializer.rb', line 53

def uids
  validate!
  imap.uids
end

#update(uid, flags: nil) ⇒ void

This method returns an undefined value.

Updates a messages flags

Parameters:

  • uid (Integer)

    the message’s UID

  • flags (Array<Symbol>) (defaults to: nil)

    the flags to set on the message



184
185
186
187
188
189
190
# File 'lib/imap/backup/serializer.rb', line 184

def update(uid, flags: nil)
  message = imap.get(uid)
  return if !message

  message.flags = flags if flags
  imap.save
end

#update_uid(old, new) ⇒ void

This method returns an undefined value.

Update a message’s metadata, replacing its UID

Parameters:

  • old (Integer)

    the existing message UID

  • new (Integer)

    the new UID to apply to the message



62
63
64
65
# File 'lib/imap/backup/serializer.rb', line 62

def update_uid(old, new)
  validate!
  imap.update_uid(old, new)
end

#validate!Boolean

Checks that the metadata files are valid, migrates the metadata file from older versions, if necessary, or deletes any existing files if the pair are not valid.

Returns:

  • (Boolean)

    indicates whether there are existing, valid files



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/imap/backup/serializer.rb', line 94

def validate!
  return true if @validated

  optionally_migrate2to3

  imap_valid = imap.valid?
  mbox_valid = mbox.valid?
  if imap_valid && mbox_valid
    @validated = true
    return true
  end
  warn_imap = !imap_valid && imap.exist?
  Logger.logger.info("Metadata file '#{imap.pathname}' is invalid") if warn_imap
  warn_mbox = !mbox_valid && mbox.exist?
  Logger.logger.info("Mailbox '#{mbox.pathname}' is invalid") if warn_mbox

  delete

  false
end