php-imap
php-imap copied to clipboard
leaveUnread() does not work if an exception happens during fetching
One user reported an issue https://github.com/freescout-help-desk/freescout/issues/4159.
If an error occurs during fetching the email in the mailbox stays "read" even though leaveUnread() is set.
Here is the example of headers which can be used to reproduce the issue:
X-Mailer: CodeIgniter
Date: Thu, 1 Aug 2024 10:55:28 +0100
Precedence: bulk
Auto-Submitted: auto-replied
X-Priority: 1 (Highest)
We've found out that the following line marks an email as "read": https://github.com/Webklex/php-imap/blob/master/src/Query/Query.php#L246
if ($this->getFetchBody()) {
$contents = $this->client->getConnection()->content($uids, "RFC822", $this->sequence)->validatedData();
}
So apparently somewhere in the code there should a place marking an email as "unread" if leaveUnread() is set.
Is it so? If yes, can someone help to find that place in order to try to find a solution.
It looks like messages are marked as "unread" here: https://github.com/Webklex/php-imap/blob/master/src/Message.php#L300
Here is the fix for Query->populate() function https://github.com/Webklex/php-imap/blob/master/src/Query/Query.php#L339C24-L339C32:
+ $exception = null;
foreach ($raw_messages["headers"] as $uid => $header) {
$content = $raw_messages["contents"][$uid] ?? "";
$flag = $raw_messages["flags"][$uid] ?? [];
$extensions = $raw_messages["extensions"][$uid] ?? [];
+ try {
$message = $this->make($uid, $msglist, $header, $content, $flag);
+ } catch (\Exception $e) {
+ $exception = $e;
+ continue;
+ }
foreach ($extensions as $key => $extension) {
$message->getHeader()->set($key, $extension);
}
if ($message !== null) {
$key = $this->getMessageKey($message_key, $msglist, $message);
$messages->put("$key", $message);
}
$msglist++;
}
+ if ($exception) {
+ throw $exception;
+ }
It's quite an important thing as if someone fetches only unread emails (like us) and an exception happens for some email in a bunch all other emails will stay marked as "unread" and will be unprocessed.
And here is the fix allowing to leave emails unread even if "Allowed memory size exhausted" fatal error occurs:
https://github.com/freescout-help-desk/freescout/commit/b9391d87dc0c7f5e10913f629646435d7ee07e8c