Skip to content

Commit

Permalink
fetcher: Delayed Mailbox Expunction
Browse files Browse the repository at this point in the history
As part of post-processing options, when fetching emails, osTicket can archive
(move) or delete (remove) a mail message from the server. When using mail
storage backend like IMAP - both operations requires `expunge` command to truly
commit the changes to the mail server.

That's all good and well, except Laminas Mail (our darling upstream lib)
expunges the mailbox in real-time when a message is moved or deleted. This
creates a problem for osTicket because **expunging causes message sequence
numbers to reset at the server end during the session!!** Which in turn causes
mismatch when we process the next message in the queued sequence. Additionally,
expunging on every message operation cases unnecessary traffic to the mail
server when every second counts.

To resolve the issue - until we switch to using `UIDs` -  this commit simply
bypasses Laminas Mail IMAP's removeMessage function so we can skip expunging on
message move/remove operations. osTicket expunges the mailbox at the end of
fetch session.
  • Loading branch information
protich committed Nov 8, 2022
1 parent 320981d commit 75c5cfe
Showing 1 changed file with 28 additions and 14 deletions.
42 changes: 28 additions & 14 deletions include/class.mail.php
Original file line number Diff line number Diff line change
Expand Up @@ -520,28 +520,21 @@ public function getRawEmail(int $i) {
/*
* move an existing message to a folder
*
* Caller should catch possible exception
*/
public function moveMessage($id, $folder) {
try {
parent::moveMessage($id, $folder);
return true;
} catch (\Throwable $t) {
// noop
}
return false;
public function moveMessage($i, $folder) {
parent::moveMessage($i, $folder);
return true;
}

/*
* Remove a message from server.
*
* Caller should catch possible exception
*/
public function removeMessage($i) {
try {
return parent::removeMessage($i);
} catch (\Throwable $t) {
// noop
}
return false;
parent::removeMessage($i);
return true;
}

/*
Expand Down Expand Up @@ -577,6 +570,27 @@ public function markAsSeen($i) {
}
}

/**
* Remove a message from server without expunging the mailbox
*
* Laminas Mail (upstream) auto expunges the mailbox on message
* removal or move (copy + remove) - which can cause major issues
* for us since we fetcher uses message sequence numbers to fetch
* messages / emails.
*
* We expunge the mailbox at the end if fetch session.
*
* TODO: Make PR upstream to support calling removeMessage with
* a boolean flag i.e removeMessage(int $id, bool $expunge = true)
*
*/
public function removeMessage($i) {
if (! $this->protocol->store([Storage::FLAG_DELETED], $i, null, '+')) {
throw new Exception('cannot set deleted flag');
}
return true;
}

// Expunge mailbox
public function expunge() {
return $this->protocol->expunge();
Expand Down

0 comments on commit 75c5cfe

Please sign in to comment.