eml file display using php not showing images

48 Views Asked by At

I'm using this code for display eml file contests using php

It shows email body fine but it not displaying the attached images.

<?php

error_reporting(-1);

$EML_FILE_PATH = '';
$PICTURE_DIRECTORY_PATH = 'img/';

$filename = 'sample.eml';
$eml_file = $EML_FILE_PATH . $filename;

// Improved error handling when opening and reading the file.
if (!$handle = fopen($eml_file, 'r')) {
    die('Cannot open file (' . $eml_file . ')');
}
$content = fread($handle, filesize($eml_file));
fclose($handle);

if ($content === false) {
    die('Error reading file (' . $eml_file . ')');
}

// Define separators for different sections of the email.
if (strpos($content, '------_') !== false) {
    $separator = '------_';
} else {
    $separator = '------=_';
}
$aContent = explode($separator, $content);

$aImages = array();
$thisHTMLContent = '';

foreach ($aContent as $thisContent) {
    if (strpos($thisContent, 'Content-Type: text/html') !== false) {
        // Correct handling of the email HTML body.
        $thisContent = substr($thisContent, strpos($thisContent, '<!DOCTYPE'));
        $thisHTMLContent = quoted_printable_decode($thisContent);
    }

    // Function to process images (DRY principle).
    function processImage($thisContent, $imgType) {
        $begin = strpos($thisContent, 'Content-ID: <') + 13;
        $long = strpos(substr($thisContent, $begin), '>');
        $img_id = substr($thisContent, $begin, $long);
        $img_name = substr($thisContent, strpos($thisContent, 'name="') + 6, strpos($thisContent, ".$imgType\"") - strpos($thisContent, 'name="') - 6);
        $img_location = $img_name; // Simplified logic assuming name is used as location.
        $searched = 'Content-ID: <' . $img_id . '>';
        $Content_ID_pos = strpos($thisContent, $searched);
        $img_base64 = substr($thisContent, $Content_ID_pos + strlen($searched) + 1);
        return array('id' => $img_id, 'name' => $img_name, 'location' => $img_location, 'type' => $imgType, 'base64' => $img_base64);
    }

    if (strpos($thisContent, 'Content-Type: image/gif;') !== false) {
        $aImages[] = processImage($thisContent, 'gif');
    }
    if (strpos($thisContent, 'Content-Type: image/jpeg;') !== false) {
        $aImages[] = processImage($thisContent, 'jpg');
    }
}

foreach ($aImages as $image) {
    $imageData = 'data:image/' . $image['type'] . ';base64,' . trim($image['base64']);
    $thisHTMLContent = str_replace('cid:' . $image['id'], $imageData, $thisHTMLContent);
}

echo $thisHTMLContent;
?>

after body ends it shows this kind of texts but not displays the images

--0000000000003cea95058bbee080-- --0000000000003cea99058bbee082 Content-Type: image/jpeg; name="=?UTF-8?B?16rXnNeV16DXlCDXqNen15XXkdenINeh16jXp9eZ15Qu? =?UTF-8?B?anBn?=" Content-Disposition: attachment; filename="=?UTF-8?B?16rXnNeV16DXlCDXqNen15XXkdenINeh16jXp9eZ15QuanBn?=" Content-Transfer-Encoding: base64 X-Attachment-Id: f_jx4j1uzv0 Content-ID: /9j/4AAQSkZJRgABAQEASwBLAAD/4RDqRXhpZgAATU0AKgAAAAgABgALAAIAAAAmAAAIYgESAAMA AAABAAMAAAExAAIAAAAmAAAIiAEyAAIAAAAUAAAIrodpAAQAAAABAAAIwuocAAcAAAgMAAAAVgAA AAAc6gAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

at the end it shows like this

enter image description here

can someone help me to figure out the issue, becoz im using shared server i cant use php libraries or packages

1

There are 1 best solutions below

1
Paarth Pratim Mout On

I tried this and I finally got this resolved by inspecting the base64 image string. In my case the base64 string which the function processImage() was returning had additional redundant string "--000000000000c387400611a9d71b--" concatenated to it. So, I tried fixing it by detecting the "--" position from base64 string and cleaning the base64 string without this redundant string.

Modified code:

<?php
error_reporting(-1);

$EML_FILE_PATH = '';

$filename = 'sample-2.eml';
$eml_file = $EML_FILE_PATH . $filename;

// Improved error handling when opening and reading the file.
if (!$handle = fopen($eml_file, 'r')) {
    die('Cannot open file (' . $eml_file . ')');
}
$content = fread($handle, filesize($eml_file));
fclose($handle);

if ($content === false) {
    die('Error reading file (' . $eml_file . ')');
}

// Define separators for different sections of the email.
if (strpos($content, '------_') !== false) {
    $separator = '------_';
} else {
    $separator = '------=_';
}
$aContent = explode($separator, $content);

$aImages = array();
$thisHTMLContent = '';

// Function to process images (DRY principle).
function processImage($thisContent, $imgType) {
    $begin = strpos($thisContent, 'Content-ID: <') + 13;
    $long = strpos(substr($thisContent, $begin), '>');
    $img_id = substr($thisContent, $begin, $long);
    $img_name = substr($thisContent, strpos($thisContent, 'name="') + 6, strpos($thisContent, ".$imgType\"") - strpos($thisContent, 'name="') - 6);
    $img_location = $img_name; // Simplified logic assuming name is used as location.
    $searched = 'Content-ID: <' . $img_id . '>';
    $Content_ID_pos = strpos($thisContent, $searched);
    $img_base64 = substr($thisContent, $Content_ID_pos + strlen($searched) + 1);
    //redundant  part detection
    $redunantPart = "--";
    //redundant part position taken out
    $redunantParPos = strpos($img_base64, $redunantPart);
    //base64 string is cleaned
    $img_base64_clean = substr($img_base64, 0, $redunantParPos);
    //final return of the  new string
    return array('id' => $img_id, 'name' => $img_name, 'location' => $img_location, 'type' => $imgType, 'base64' => $img_base64_clean);
}

foreach ($aContent as $thisContent) {
    if (strpos($thisContent, 'Content-Type: text/html') !== false) {
        // Correct handling of the email HTML body.
        $thisContent = substr($thisContent, strpos($thisContent, '<!DOCTYPE'));
        $thisHTMLContent = quoted_printable_decode($thisContent);
    }

    if (strpos($thisContent, 'Content-Type: image/gif;') !== false) {
        $aImages[] = processImage($thisContent, 'gif');
    }
    if (strpos($thisContent, 'Content-Type: image/jpeg;') !== false) {
        $aImages[] = processImage($thisContent, 'jpg');
    }
}
// Output the image using data URI
$finalImage = '';
foreach ($aImages as $image) {
    $finalImage .= '<img src="data:image/' . $image['type'] . ';base64,' . trim($image['base64']) . '" />';
}