7

I want to extract only the HTML content from a imap_body result. The imap_body give a verbatim copy of the mail.

Makram
  • 834
  • 2
  • 9
  • 21

3 Answers3

19

I found a solution:

function getBody($uid, $imap)
{
    $body = $this->get_part($imap, $uid, "TEXT/HTML");
    // if HTML body is empty, try getting text body
    if ($body == "") {
        $body = $this->get_part($imap, $uid, "TEXT/PLAIN");
    }
    return $body;
}

function get_part($imap, $uid, $mimetype, $structure = false, $partNumber = false)
{
    if (!$structure) {
        $structure = imap_fetchstructure($imap, $uid, FT_UID);
    }
    if ($structure) {
        if ($mimetype == $this->get_mime_type($structure)) {
            if (!$partNumber) {
                $partNumber = 1;
            }
            $text = imap_fetchbody($imap, $uid, $partNumber, FT_UID);
            switch ($structure->encoding) {
                case 3:
                    return imap_base64($text);
                case 4:
                    return imap_qprint($text);
                default:
                    return $text;
            }
        }

        // multipart
        if ($structure->type == 1) {
            foreach ($structure->parts as $index => $subStruct) {
                $prefix = "";
                if ($partNumber) {
                    $prefix = $partNumber . ".";
                }
                $data = $this->get_part($imap, $uid, $mimetype, $subStruct, $prefix . ($index + 1));
                if ($data) {
                    return $data;
                }
            }
        }
    }
    return false;
}

function get_mime_type($structure)
{
    $primaryMimetype = ["TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER"];

    if ($structure->subtype) {
        return $primaryMimetype[(int)$structure->type] . "/" . $structure->subtype;
    }
    return "TEXT/PLAIN";
}
Christian Gollhardt
  • 16,510
  • 17
  • 74
  • 111
Makram
  • 834
  • 2
  • 9
  • 21
8

http://php.net/manual/en/function.imap-fetchbody.php

Parameter 3, "the section" is as follows:

The part number. It is a string of integers delimited by period which index into a body part list as per the IMAP4 specification

(empty) - Entire message
0 - Message header
1 - MULTIPART/ALTERNATIVE
1.1 - TEXT/PLAIN
1.2 - TEXT/HTML
2 - file.ext

Therefore, to grab the HTML part of the mail, you would have to use the 1.2 option as the third parameter. Like so:

$message = imap_fetchbody($inbox, $number, 1.2);
GunniH
  • 186
  • 1
  • 8
  • This only applies /if/ the message follows this structure. Many emails do not, and they will not follow this structure if it includes attachments. The best way method is to parse the bodystructure to find the HTML section you want. – Max Aug 25 '14 at 19:11
  • Thank you for your answer. Unfortunatly, i tried this method but it didn't work. – Makram Aug 26 '14 at 09:57
  • @Max can you help me with a method for body structure. – Makram Aug 26 '14 at 09:58
  • `imap_fetchbody($inbox, $number, 2);` worked for me – gingerCodeNinja Dec 17 '19 at 12:40
4

I don't have enough reputation to add a comment, but I just wanted to clarify in @GunniH's answer that your call to the function should look like this:

$message = imap_fetchbody($inbox, $number, '1.2');

instead of this

$message = imap_fetchbody($inbox, $number, 1.2);

That final argument should be a string, not an int.