Using the imap_fetchstructure of PHP to obtain the mail transfer code encoding is not consistent with the actual situation.

[problems encountered]

try to use the imap_fetchstructure function of PHP to get the encoding, of the message content transfer encoding for the corresponding decoding operation. However, after testing, it is found that the representative value of encoding returned is not always consistent with the actual coding, such as--

1
Base64 encoding 307bit

2
this email actually uses Quoted-Printable encoding. The expected function encoding return value should be 4, but the actual return value is 0 (7bit).

[related Code]

function retrieve_message($auth_user,$accountid,$messageid,$fullheaders){
  $message=array();
    
  if(!($auth_user && $accountid && $messageid)){
    return false;
  }
    
  $imap=open_mailbox($auth_user,$accountid);
  if(!$imap){
    return false;
  }
    
/*
  header
*/
    
  $structure=imap_fetchstructure($imap,$messageid);
  $encoding=$structure->encoding;
  $message["body"]=imap_body($imap,$messageid);
  if(!$message["body"]){
    $message["body"]="[This message has no body.]";
  }

  if(($encoding==3) || stristr($message["body"],"Content-Transfer-Encoding: base64")){
    $message["body"]=base64_decode($message["body"]);
    if(is_gbk($message["body"])){
      $message["body"]=iconv("gbk","utf-8",$message["body"]);
    }
  } elseif(($encoding==4) || stristr($message["body"],"Content-Transfer-Encoding: quoted-printable")){
    $message["body"]=quoted_printable_decode($message["body"]);
    if(is_gbk($message["body"])){
      $message["body"]=iconv("gbk","utf-8",$message["body"]);
    }
  }
    
  imap_close($imap);
  return $message;
}

[attempts made]

searched the Internet for a long time, but could not find a particularly clear answer. I only saw that some articles mentioned that there could be multiple parts, for a complex email and the main content was generally in parts [1], so I added the following judgment--

if(isset($structure->parts) && is_array($structure->parts) && isset($structure->parts[1])){
  $encoding=$structure->parts[1]->encoding;
} else {
  $encoding=$structure->encoding;    
}

but only a small number of original problem emails get the correct encoding, and most of them don"t work.

[Test Environment]

XAMPP
operating system: Windows 10 Family Chinese version 1803
Apache version: 2.4.16 (Win32)
PHP version: 5.6.12

Php
Jan.14,2022

this problem is finally understood and solved by studying the user notes and continuous testing under imap_fetchstructure and imap_fetchbody in the PHP manual.

generally speaking, email is divided into simple and multipart. The encoding obtained by simple using imap_fetchstructure is the actual encoding used by the email; while the email from multipart may contain multiple parts, and each part may contain multiple parts,. The type and encoding of each part of the part may be different, so it needs to be parsed one by one through a loop.

can be combined with reference--

  1. comments on user " david at hundsness dot com " under the imap_fetchstructure description in the
  2. PHP manual: PHP:imap_fetchstructure-Manual
  3. comments on user " atamido at gmail dot remove dot com " under the imap_fetchbody description in the
  4. PHP manual: PHP:imap_fetchbody-Manual
MySQL Query : SELECT * FROM `codeshelper`.`v9_news` WHERE status=99 AND catid='6' ORDER BY rand() LIMIT 5
MySQL Error : Disk full (/tmp/#sql-temptable-64f5-1eb13f8-233f.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
MySQL Errno : 1021
Message : Disk full (/tmp/#sql-temptable-64f5-1eb13f8-233f.MAI); waiting for someone to free some space... (errno: 28 "No space left on device")
Need Help?