views:

26

answers:

0

Hello everybody,

I'm actually developing a webmail written in PHP5 with the native IMAP library and the Symfony framework. I have some difficulty to understand the structure result of the imap_fetchstructure() method and how can I use this with the imap_fetchbody() method to retrieve the body message.

The PHP5 documentation specify that imap_fetchstructure() returns an stdClass object with the following property :

  • type : Primary body type
    • 0 : text
    • 1 : multipart
    • 2 : message
    • 3 : application
    • 4 : audio
    • 5 : image
    • 6 : video
    • 7 : other
  • ifsubtype : TRUE if there is a subtype string
  • subtype : MIME subtype
  • parts : An array of objects identical in structure to the top-level object, each of which corresponds to a MIME body part.

(I think other properties are not important for what I want to do.)

I write the class BodyMessage which can extract the body message of an alternative message and a mixed message but I'm not sure my development is correct.

class BodyMessage
{
    private $html = null;

    /**
     * Decode the imap_fetchbody result
     *
     * @param int $charset Message encoding
     * @param string $imap_fetchbody Encoded message
     * @return string Decoded message
     */
    private static function decodeImapFetchBody($charset, $imap_fetchbody)
    {
      switch($charset)
      {
        case ENC7BIT:
          $result = imap_qprint($imap_fetchbody);
          $result = utf8_encode($result);
        break;

        case ENCQUOTEDPRINTABLE:
          $result = imap_qprint($imap_fetchbody);
          $result = utf8_encode($result);
        break;

        default:
          throw new sfException('Charset ('.$charset.') is not supported.');
        break;
      }

      return $result;
    }

    /**
     * Decode an Alternative message
     *
     * @param imap_stream $imap_stream IMAP stream
     * @param int $message_no Message number
     * @param string $alternative_part Alternative Parts
     * @return string Body of the message
     */
    private static function decodeAlternativePart($imap_stream, $message_no, $alternative_part, $section_prefix = null)
    {
      $result = null;

      foreach($alternative_part as $local_section => $part)
      {
        if(($part->type == TYPETEXT) && ($part->ifsubtype == 1) && ($part->subtype == 'HTML'))
        {
          try
          {
            (is_null($section_prefix)) ? $section = $local_section : $section = $section_prefix.'.'.$local_section;
            $result = BodyMessage::decodeImapFetchBody($part->encoding, imap_fetchbody($imap_stream, $message_no, $section));
          }
          catch(sfException $e)
          {
            throw $e;
          }
        }
      }

      if(is_null($result))
        throw new sfException('No html part found into the alternative parts.');

      return $result;
    }

    /**
     * Décode a Mixed message
     *
     * @param imap_stream $imap_stream IMAP stream
     * @param int $message_no Message number
     * @param stdClass $mixed_part Mixed parts
     * @return string Body of the message
     */
    private static function decodeMixedPart($imap_stream, $message_no, $mixed_part)
    {
      $result = null;

      foreach($mixed_part as $section => $part)
      {
        if(($part->type == TYPEMULTIPART) && ($part->ifsubtype == 1) && ($part->subtype == 'ALTERNATIVE'))
        {
          try
          {
            $result = BodyMessage::decodeAlternativePart($imap_stream, $message_no, $part->parts, 1);
          }
          catch(sfException $e)
          {
            throw $e;
          }
        }
      }

      if(is_null($result))
        throw new sfException('No html part found into the alternative parts.');

      return $result;
    }

    /**
     * Create a BodyMessage with an IMAP stream and a message number
     *
     * @param imap_stream $imap_stream IMAP stream
     * @param int $message_no Message number
     */
    public static function constructFromNo($imap_stream, $message_no)
    {
      $structure_message = imap_fetchstructure($imap_stream, $message_no);

      if(($structure_message->type == TYPEMULTIPART) && ($structure_message->ifsubtype == 1) && ($structure_message->subtype == 'ALTERNATIVE'))
      {
        try
        {
          $html = BodyMessage::decodeAlternativePart($imap_stream, $message_no, $structure_message->parts);
        }
        catch(sfException $e)
        {
          throw $e;
        }
      }
      else if(($structure_message->type == TYPEMULTIPART) && ($structure_message->ifsubtype == 1) && ($structure_message->subtype == 'MIXED'))
      {
        try
        {
          $html = BodyMessage::decodeMixedPart($imap_stream, $message_no, $structure_message->parts);
        }
        catch(sfException $e)
        {
          throw $e;
        }
      }
      else
        throw new sfException('The message structure is not supported.');

      return new BodyMessage($html);
    }

    /**
     * Constructeur du Body d'un message
     *
     * @param string $html Body du message
     */
    public function  __construct($html)
    {
      $this->html = $html;
    }

    /**
     * Getter du Body du message
     *
     * @return string Body du message
     */
    public function getHtml()
    {
      return $this->html;
    }
  }

If someone can help me to understand the imap_fetchstructure() result and how can I use this with the imap_fetchbody() method, I would be graceful.