Search code examples
phpemailencodingbase64email-headers

using PHP to return an image in a base64 encoded email


I'm working on an email send and tracking application, but I'm running into a problem that I just can't figure out. I want to us a tracking image in my emails but I'm getting some strange behavior. Currently, I'm sending out emails encoded in base64. In the body of the HTML message I'm using an HTML image tag with a link to a PHP file on my server. That file sends back an image using the following PHP code:

header("Content-Type: image/png");
readfile("full-server-path-to-image.png");

This is where it gets strange. If I view the message in the Outlook email client the image will not display (just shows red "X" image icon). Other normally linked images will display just fine though. If I view the same message in Gmail I am able to see all of the images. It's really weird that the image serves up just fine in some email clients but not all of them.

I noticed this problem started when I changed to encoding my messages in base64. Before I started encoding my messages I was able to view all images in any email client. My gut is telling me this has something to do with the content-encoding-type, but I have no idea how to fix it. Any help would be appreciated!

Here is the PHP code I'm using to send out messages:

$myHTMLmessage = chunk_split(base64_encode('
<html><head></head><body>
<img src="https://www.my-web-site.com/openTrack.php?t={trackerid}"></a>
</body></html>'));

$boundary = uniqid('np');               
$to = "[email protected]"
$headers = "MIME-Version: 1.0\r\n";
$headers .= "From: [email protected]\r\n";
$headers .= "Content-Type: multipart/alternative;boundary=" . $boundary . "\r\n";

$message = "This is a MIME encoded message.";
$message .= "\r\n\r\n--" . $boundary . "\r\n";
$message .= "Content-Type: text/plain;charset=UTF-8\r\n";
$message .= "Content-Transfer-Encoding: base64\r\n\r\n";
//Plain text body
$message .= "some plain text";
$message .= "\r\n\r\n--" . $boundary . "\r\n";
$message .= "Content-Type: text/html;charset=UTF-8\r\n";
$message .= "Content-Transfer-Encoding: base64\r\n\r\n";
//Html body
$message .= $myHTMLmessage;
$message .= "\r\n\r\n--" . $boundary . "--";

mail($to,$subject,$message,$headers);

Solution

  • Just in case anyone runs into something like this I figured out it all boils down to how email clients encode urls. In my original code I am using a url with 2 parameters inside my image src attribute. Like this:

    http://www.my-web-site.com/page.php?pram1=something&pram2=something
    

    When Outlook processes this url it get changed to:

    http://www.my-web-site.com/page.php?pram1=something&amp;pram2=something
    

    Other email clients are smart enough to leave the & symbol the way it is without converting it to &amp;

    In my live code I needed to $_GET both url parameters and process them. If my script couldn't process both parameters then it wouldn't even get to the line where it would send back an image. The best workaround I could come up with was adding this code in my page.php file:

    $pram1 = $_GET['pram1'];
    $pram2 = $_GET['pram2'];
    
    if(!isset($pram2)){
        $pram2 = $_GET['amp;pram2'];
    }
    
    // now regardless of the email client both parameters contain a value to process
    
    if((isset($pram1)) && (isset($pram2))){
        header("Content-Type: image/png");
        readfile("full-server-path-to-image.png");
    }
    

    I know is sounds pretty simple, but I had been scratching my head over this for way too long. Originally, I was convinced it was something to do with how the message was encoded before it was sent out. Never thought it would be Outlook changing my code. On second though Microsoft never likes to make things easy.....never gets old...lol