Sidetalker
Sidetalker

Reputation: 708

How to combine HTML and an attachment using PHP mail?

RESOLVED: The issue was a missing "\r\n" at the tail end of the line reading:

. "Contact " . $from . " for tech support."

Thank you everyone for your help and suggestions!

I'm trying to make a PHP function that will send an email with some HTML body and an attached image. I've perused several of the answers on this site and online tutorials and I'm unable to see where I'm going wrong. My current code attaches an image and sends the email successfully but the HTML body is missing and I receive an empty email with my attached image.

The raw source of the email I receive appears to have my HTML in it however none of my email clients render this HTML. See the source below:

Return-path: <[email protected]>
Envelope-to: [email protected]
Delivery-date: Thu, 05 Jun 2014 18:20:36 -0600
Received: from sidesul6 by slan-550-84.anhosting.com with local (Exim 4.82)
    (envelope-from <[email protected]>)
    id 1Wshtc-003XAD-04
    for [email protected]; Thu, 05 Jun 2014 18:20:36 -0600
To: [email protected]
Subject: attachmentTest
X-PHP-Script: sideapps.com/phpMail/mailFunc.php for 74.70.70.214
From:[email protected]
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="12cbb4220ad618027879b43ba5293d9d"
Message-Id: <[email protected]>
Date: Thu, 05 Jun 2014 18:20:36 -0600

Sorry, your client doesn't support MIME types.
Contact [email protected] for tech support.--12cbb4220ad618027879b43ba5293d9d
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit


    <html>
        <body>
            <p>Testing <i><b>HTML</b></i> right now.</p>
        </body>
    </html>
--12cbb4220ad618027879b43ba5293d9d
Content-Type: image/png; name="test.png"
Content-Transfer-Encoding: base64
Content-disposition: attachment; file="test.png"

<base64 image encoding>

See my function below:

function GetHTML()
{
    return <<<HTML

    <html>
        <body>
            <p>Testing <i><b>HTML</b></i> right now.</p>
        </body>
    </html>

HTML;
}

function mailAttachment($to, $subject, $body, $from, $photoPath, $photoName, $filetype)
{
    $bound_text = md5(uniqid(rand(), true));;
    $bound = "--" . $bound_text . "\r\n";
    $bound_last = "--" . $bound_text . "--\r\n";

    $headers = "From: " . $from . "\r\n"
    . "Reply-To: " . $from . "\r\n"
    . "Return-Path: " . $from . "\r\n"
    . "MIME-Version: 1.0\r\n"
    . "Content-Type: multipart/mixed; boundary=\"$bound_text\"";

    $message =  "Sorry, your client doesn't support MIME types.\r\n"
    . "Contact " . $from . " for tech support."
    . $bound;

    $message .= "Content-Type: text/html; charset=\"iso-8859-1\"\r\n"
    . "Content-Transfer-Encoding: 7bit\r\n\r\n"
    . $body . "\r\n"
    . $bound;

    $file = file_get_contents($photoPath);

    $message .= "Content-Type: $filetype; name=\"$photoName\"\r\n"
    . "Content-Transfer-Encoding: base64\r\n"
    . "Content-disposition: attachment; file=\"$photoName\"\r\n"
    . "\r\n"
    . chunk_split(base64_encode($file))
    . $bound_last;

    if(mail($to, $subject, $message, $headers)) 
    {
         echo 'MAIL SENT!' . '<br>';
         echo 'to: ' . $to . '<br>';
         echo 'from: ' . $from . '<br>';
         echo 'bodyText: ' . $body . '<br>';
         echo 'photoPath: ' . $photoPath . '<br>';
         echo 'photoName: ' . $photoName . '<br>';
         echo 'filetype: ' . $filetype . '<br>';
    } 
    else 
    { 
         echo 'MAIL FAILED';
    }
}

mailAttachment('[email protected]', 'attachmentTest', GetHTML(),
               '[email protected]', 'testImage.png', 'uploaded.png', 'image/png');

Upvotes: 1

Views: 1446

Answers (2)

Sidetalker
Sidetalker

Reputation: 708

There is a missing "\r\n" at the tail end of the line reading:

. "Contact " . $from . " for tech support."

Below is the ammended function:

function GetHTML()
{
    return <<<HTML

    <html>
        <body>
            <p>Testing <i><b>HTML</b></i> right now.</p>
        </body>
    </html>

HTML;
}

function mailAttachment($to, $subject, $body, $from, $photoPath, $photoName, $filetype)
{
    $bound_text = md5(uniqid(rand(), true));;
    $bound = "--" . $bound_text . "\r\n";
    $bound_last = "--" . $bound_text . "--\r\n";

    $headers = "From: " . $from . "\r\n"
    . "Reply-To: " . $from . "\r\n"
    . "Return-Path: " . $from . "\r\n"
    . "MIME-Version: 1.0\r\n"
    . "Content-Type: multipart/mixed; boundary=\"$bound_text\"";

    $message =  "Sorry, your client doesn't support MIME types.\r\n"
    . "Contact " . $from . " for tech support.\r\n"
    . $bound;

    $message .= "Content-Type: text/html; charset=\"iso-8859-1\"\r\n"
    . "Content-Transfer-Encoding: 7bit\r\n\r\n"
    . $body . "\r\n"
    . $bound;

    $file = file_get_contents($photoPath);

    $message .= "Content-Type: $filetype; name=\"$photoName\"\r\n"
    . "Content-Transfer-Encoding: base64\r\n"
    . "Content-disposition: attachment; file=\"$photoName\"\r\n"
    . "\r\n"
    . chunk_split(base64_encode($file))
    . $bound_last;

    if(mail($to, $subject, $message, $headers)) 
    {
         echo 'MAIL SENT!' . '<br>';
         echo 'to: ' . $to . '<br>';
         echo 'from: ' . $from . '<br>';
         echo 'bodyText: ' . $body . '<br>';
         echo 'photoPath: ' . $photoPath . '<br>';
         echo 'photoName: ' . $photoName . '<br>';
         echo 'filetype: ' . $filetype . '<br>';
    } 
    else 
    { 
         echo 'MAIL FAILED';
    }
}

mailAttachment('[email protected]', 'attachmentTest', GetHTML(),
               '[email protected]', 'testImage.png', 'uploaded.png', 'image/png');

Upvotes: 1

IdusOrtus
IdusOrtus

Reputation: 1116

This doesn't attach a file, but you can embed an image within the HTML. Looks like you have the attachment part sorted though. Perhaps this will help with the html content.

This code works in a work environment stuck in 2007, haven't fully tested it with modern browsers, versions of Outlook past 2007, etc.

IIRC, the trick was embedding the full html into the email body and working with tables.

HTML :

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
    <title>Order</title>
</head>
<body>
    <style type="text/css">     
        table#bodyTable {}
        table#emailContainer {}
    </style>
    <table width="100%" height="100%" cellpadding="0" cellspacing="0" border="0" id="bodyTable">
      <tr><td align="center" valign="top"> 
          <div style="overflow: hidden;">
           <table border="0" cellpadding="0" cellspacing="0" width="800" id="emailContainer">
            <tr><td align="center" valign="top">
                <table style="font-family:Tahoma;font-size:13px" width="500" align="center">
                 <tr bgcolor="#ffffff"><td style="padding:10px;color:#000000;" align="left" bgcolor="#ffffff">
                   <div style="margin: 15px;float:left;">
                     <a href="http://image.link.redirect" target="_blank"><img alt="YourImageAltText" border="0" src="http://your.domain/img/yourImage.jpg" height="48" width="230" /></a>                                          
                   </div>
                  </td></tr>            
                  <tr><td style="padding:18px 30px 10px;font-size:11px" align="left">
                   <div style="font-size:12px">
                     This email is to confirm your recent job submission 
                   </div>                   
                   </tr></td>               
                  <tr bgcolor="#ffffff"><td style="padding:10px;color:#000000" align="center"></td></tr>
                </table>                            
              </td></tr>
             </table><!-- End central content table, fixed width, aligned to center based upon master table -->
           </div> 
         </td></tr>
    </table><!-- end master containing table -->
</body>
</html>

PHP: I build the $msg string with dynamic content and an external template, using include('./templates/teamNotificationEmailBody.php');

function orderMail($sendTo, $subject, $msg, $errorRedirect, $successRedirect) {

$headers  = 'MIME-Version: 1.0' . "\r\n";
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$headers .= 'From: [email protected]';

if (isset($sendTo)) 
{  
    $email = filter_var($sendTo, FILTER_SANITIZE_EMAIL);  
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) 
    {    
        echo "<hr/>$email is <strong>NOT</strong> a valid email address.<br/><br/>Please return to the reservation form and enter a valid email address.<hr/><br/><a href=\"$errorRedirect\">Return $errorRedirect</a><br/>";  
        exit();
    }  
}   

if (mail($sendTo, $subject, $msg, $headers)) 
{
    if (isset($successRedirect)) 
    {
        echo "$successRedirect";
        header("location: $successRedirect");
        exit();
    } 
} 
else 
{
    echo "<hr/>An error occured with the email notification system. <br/><br/><hr/><br/><a href=\"$errorRedirect\">Click here to return</a><br/>";  
    exit();
} 

Upvotes: 0

Related Questions