From 9d8a1844eaf456a0783d635d5b36a98b931d59c3 Mon Sep 17 00:00:00 2001 From: fsdultra Date: Mon, 16 Jun 2025 22:48:19 -0300 Subject: [PATCH 1/3] Improve date parsing in TimezoneUtil::MakeUTCDate Added support for 'Y-m-d\THis' format (e.g., 2025-03-27T130000). Also ensures the method returns `false` explicitly when all parsing attempts fail and an error is logged. --- src/lib/utils/timezoneutil.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib/utils/timezoneutil.php b/src/lib/utils/timezoneutil.php index 8d46a8d9..a65b027c 100644 --- a/src/lib/utils/timezoneutil.php +++ b/src/lib/utils/timezoneutil.php @@ -1319,8 +1319,12 @@ public static function MakeUTCDate($value, $timezone = null) { //If there is no timezone set, we use the default timezone $tz = timezone_open(date_default_timezone_get()); } - //20110930T090000Z - $date = date_create_from_format('Ymd\THis\Z', $value, timezone_open("UTC")); + //2025-03-27T130000 + $date = date_create_from_format('Y-m-d\THis', $value, $tz); + if (!$date) { + //20110930T090000Z + $date = date_create_from_format('Ymd\THis\Z', $value, timezone_open("UTC")); + } if (!$date) { //20110930T090000 $date = date_create_from_format('Ymd\THis', $value, $tz); @@ -1331,6 +1335,7 @@ public static function MakeUTCDate($value, $timezone = null) { } if (!$date) { ZLog::Write(LOGLEVEL_ERROR, sprintf("TimezoneUtil::MakeUTCDate(): failed to convert '%s' to date", $value)); + return false; } return date_timestamp_get($date); } From 85ab42978a7f3183edad4c1e126ece051f1c8910 Mon Sep 17 00:00:00 2001 From: fsdultra Date: Mon, 16 Jun 2025 23:00:18 -0300 Subject: [PATCH 2/3] Handle missing boundary in multipart messages as plain text Previously, if a multipart content-type (e.g. multipart/mixed) was missing a boundary parameter, mimeDecode would return an error and skip processing the part. This commit changes the behavior to fallback to treating the content as plain text when no boundary is found. It ensures the body is included and decoded if requested, preventing silent data loss and improving compatibility with malformed messages --- src/include/mimeDecode.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/include/mimeDecode.php b/src/include/mimeDecode.php index ff323969..771a3cdb 100644 --- a/src/include/mimeDecode.php +++ b/src/include/mimeDecode.php @@ -347,9 +347,14 @@ function _decode($headers, $body, $default_ctype = 'text/plain') case 'multipart/relative': //#20431 - android case 'multipart/mixed': case 'application/vnd.wap.multipart.related': - if(!isset($content_type['other']['boundary'])){ - $this->_error = 'No boundary found for ' . $content_type['value'] . ' part'; - return false; + if (!isset($content_type['other']['boundary'])) { + if ($this->_include_bodies) { + $encoding = isset($content_transfer_encoding['value']) ? $content_transfer_encoding['value'] : '7bit'; + $charset = isset($content_type['other']['charset']) ? $content_type['other']['charset'] : $this->_charset; + $return->body = $this->_decode_bodies ? $this->_decodeBody($body, $encoding, $charset, false) : $body; + } + $this->_error = 'Boundary missing in part ' . $content_type['value'] . ', content treated as plain text.'; + break; } $default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain'; From fd4fbdfd00e55e5363bf9cb7cc06b0c57151bba0 Mon Sep 17 00:00:00 2001 From: fsdultra Date: Mon, 16 Jun 2025 23:04:40 -0300 Subject: [PATCH 3/3] Fix: handle header fields as arrays in IMAP backend and address parser - Adjusted handling of "date", "subject", and "from" headers in BackendIMAP to support array values (take first element when needed). - Ensured `Mail_RFC822` uses the first element of the address array to avoid invalid parsing. - Prevents potential issues with multi-valued headers causing type mismatches or incorrect field extraction. --- src/backend/imap/imap.php | 13 ++++++++++--- src/include/z_RFC822.php | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/backend/imap/imap.php b/src/backend/imap/imap.php index 7eafd65b..aead09bb 100644 --- a/src/backend/imap/imap.php +++ b/src/backend/imap/imap.php @@ -1318,7 +1318,9 @@ public function GetMessage($folderid, $id, $contentparameters) { unset($textBody); unset($mail_headers); - $output->datereceived = isset($message->headers["date"]) ? $this->cleanupDate($message->headers["date"]) : null; + $output->datereceived = null; + if (isset($message->headers["date"])) + $output->datereceived = is_array($message->headers["date"]) ? $message->headers["date"][0] : $message->headers["date"]; if ($is_smime) { // #190, KD 2015-06-04 - Add Encrypted (and possibly signed) to the classifications emitted @@ -1332,10 +1334,15 @@ public function GetMessage($folderid, $id, $contentparameters) { else { $output->messageclass = "IPM.Note"; } - $output->subject = isset($message->headers["subject"]) ? $message->headers["subject"] : ""; + $output->subject = null; + if (isset($message->headers["subject"])) + $output->subject = is_array($message->headers["subject"]) ? $message->headers["subject"][0] : $message->headers["subject"]; + $output->read = $stat["flags"]; - $output->from = isset($message->headers["from"]) ? $message->headers["from"] : null; + $output->from = null; + if (isset($message->headers["from"])) + $output->from = is_array($message->headers["from"]) ? $message->headers["from"][0] : $message->headers["from"]; if (isset($message->headers["thread-topic"])) { $output->threadtopic = $message->headers["thread-topic"]; } diff --git a/src/include/z_RFC822.php b/src/include/z_RFC822.php index bb5f7d82..78a19d24 100644 --- a/src/include/z_RFC822.php +++ b/src/include/z_RFC822.php @@ -199,6 +199,7 @@ public function parseAddressList($address = null, $default_domain = null, $nest_ if (isset($address)) $this->address = $address; // z-push addition + if (is_array($this->address)) $this->address = $this->address[0]; if (strlen(trim((string) $this->address)) == 0) return array(); if (isset($default_domain)) $this->default_domain = $default_domain; if (isset($nest_groups)) $this->nestGroups = $nest_groups;