php-imap: Problem with subject =?UTF-8?Q? (2)

Describe the bug When I’m parsing the e-mail message, I’m facing this issue when trying to getSubject().

Used config I’m using default package config.

Code to Reproduce The troubling code section which produces the reported bug.

$client = Client::account('default');
$client->connect();
$inbox = $client->getFolderByPath('INBOX');
$query = $inbox->messages();
$messages = $query->where(['UNSEEN'])->from($email)->get();

foreach ($messages as $message) {    
     echo $message->getSubject();
}

Expected behavior 99% of cases this script work, but to an specific message it’s returing the subject as:

=?utf-8?Q?Confirmaci=C3=B3n_reserva_Free_Tour_Flo?= =?utf-8?Q?rencia_Esencial_-_Buendiatours.com?=

Desktop / Server (please complete the following information):

  • OS: Windows 11 Enterprise
  • PHP: XAMPP / PHP 8.2.7
  • Version v5.3
  • Provider Hetzner Online GmbH

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 1
  • Comments: 17 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Wonderful, works perfectly, thank you very much. We’ll hope the imap-php library fixes this in the future.

this paulocardozo decodeSubject function id doing pretty good job with my test set of subjects, but cannot decode this one:

=?UTF-8?B?VGlja2V0IE5vOiBb7aC97bOpMTddIE1haWxib3ggSW5ib3ggLSAoMTcpIEluY29taW5nIGZhaWxlZCBtZXNzYWdlcw==?=

We’ve just checked this subject with the latest version of decodeSubject() function, it was decoded into:

Ticket No: [??????17] Mailbox Inbox - (17) Incoming failed messages

I have created a function to parse subject:

`private static function decodeSubject($subject) {

    $parts = preg_match_all("/(=\?[^\?]+\?[BQ]\?)([^\?]+)(\?=)[\r\n\t ]*/i", $subject, $m);

    $joined_parts = '';
    if (count($m[1]) > 1 && !empty($m[2])) {
        // Example: GyRCQGlNVTtZRTkhIT4uTlMbKEI=
        $joined_parts = $m[1][0] . implode('', $m[2]) . $m[3][0];

        $subject_decoded = iconv_mime_decode($joined_parts, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, "UTF-8");

        if ($subject_decoded && trim($subject_decoded) != trim(rtrim($joined_parts, '='))) {
            return $subject_decoded;
        }
    }

    // iconv_mime_decode() can't decode:
    // =?iso-2022-jp?B?IBskQiFaSEcyPDpuQC4wTU1qIVs3Mkp2JSIlLyU3JSItahsoQg==?=
    $subject_decoded = iconv_mime_decode($subject, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, "UTF-8");

    // Sometimes iconv_mime_decode() can't decode some parts of the subject:
    // =?iso-2022-jp?B?IBskQiFaSEcyPDpuQC4wTU1qIVs3Mkp2JSIlLyU3JSItahsoQg==?=
    // =?iso-2022-jp?B?GyRCQGlNVTtZRTkhIT4uTlMbKEI=?=
    if (preg_match_all("/=\?[^\?]+\?[BQ]\?/i", $subject_decoded)) {
        $subject_decoded = \imap_utf8($subject);
    }

    if (!$subject_decoded) {
        $subject_decoded = $subject;
    }

    return $subject_decoded;
}`

Then I do that. image

@Webklex Well, as I’m very delayed in a project, I’ve tested the solution above, it’s related to https://github.com/Webklex/php-imap/issues/410#issuecomment-1608876508 and it worked.

`private static function decodeSubject($subject) { $parts = preg_match_all(“/(=?[^?]+?[BQ]?)([^?]+)(?=)[\r\n\t ]*/i”, $subject, $m);

    $joined_parts = '';
    if (count($m[1]) > 1 && !empty($m[2])) {
        // Example: GyRCQGlNVTtZRTkhIT4uTlMbKEI=
        $joined_parts = $m[1][0].implode('', $m[2]).$m[3][0];

        $subject_decoded = iconv_mime_decode($joined_parts, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, "UTF-8");

        if ($subject_decoded && trim($subject_decoded) != trim(rtrim($joined_parts, '='))) {
            return $subject_decoded;
        }
    }

    // iconv_mime_decode() can't decode:
    // =?iso-2022-jp?B?IBskQiFaSEcyPDpuQC4wTU1qIVs3Mkp2JSIlLyU3JSItahsoQg==?=
    $subject_decoded = iconv_mime_decode($subject, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, "UTF-8");

    // Sometimes iconv_mime_decode() can't decode some parts of the subject:
    // =?iso-2022-jp?B?IBskQiFaSEcyPDpuQC4wTU1qIVs3Mkp2JSIlLyU3JSItahsoQg==?=
    // =?iso-2022-jp?B?GyRCQGlNVTtZRTkhIT4uTlMbKEI=?=
    if (preg_match_all("/=\?[^\?]+\?[BQ]\?/i", $subject_decoded)) {
        $subject_decoded = \imap_utf8($subject);
    }

    if (!$subject_decoded) {
        $subject_decoded = $subject;
    }

    return $subject_decoded;

}`

@Webklex I just noticed, the same code works on unix server (Hostinger), but isn’t working locally on Windows. It’s seems very strange to me, but still investigating…

@Webklex It seems be a local problem… I’m creating from scratch an application that verify constantly a mailbox, in the older version of application, your packege is working as well, but on newer not… I’ll further investigate here and post as soon as I have news.

Thanks!