1

I'm trying to set up a web application that sends an e-mail on completion to the user with an attachment. I want the e-mail to go in both HTML and text format to ensure that everyone can view it regardless of their mail settings. I'm having trouble getting it to work, so I was wondering if anyone can spot the problem with my code.

The code I'm using is below. This was taken as a template from another site, but I have done plenty of reading up so I have a rough understanding of how it all works. Unfortunately, not enough of an understanding to fix the problem!

$firstname = $_POST['firstname'];
$email = $_POST['email'];
//define the receiver of the email 
$to = $email; 
//define the subject of the email 
$subject = "$firstname, thanks for using the One Minute Leveller"; 
//create a boundary string. It must be unique 
//so we use the MD5 algorithm to generate a random hash 
$random_hash = md5(date('r', time())); 
//define the headers we want passed. Note that they are separated with \r\n 
$headers = "From: The Xenon Group\r\nReply-To: [email protected]"; 
//add boundary string and mime type specification 
$headers .= "\r\nContent-Type: multipart/mixed; boundary=\"PHP-mixed-".$random_hash."\""; 
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks
$attachment = chunk_split(base64_encode(file_get_contents('Level3info.pdf'))); 
//define the body of the message. 
ob_start(); //Turn on output buffering 
?> 
--PHP-mixed-<?php echo $random_hash; ?>  

Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>" 

--PHP-alt-<?php echo $random_hash; ?>  
Content-Type: text/plain; charset="iso-8859-1" 
Content-Transfer-Encoding: 7bit

TEXT E-MAIL GOES HERE. ACTUAL CONTENT REMOVED

--PHP-alt-<?php echo $random_hash; ?>  

Content-Type: text/html; charset="iso-8859-1" 
Content-Transfer-Encoding: 7bit

<html><h1>HTML CONTENT GOES HERE. ACTUAL CONTENT REMOVED</h1></html>

--PHP-alt-<?php echo $random_hash; ?>-- 

--PHP-mixed-<?php echo $random_hash; ?>  

Content-Type: application/pdf; name="Level3info.pdf"  
Content-Transfer-Encoding: base64  
Content-Disposition: attachment  

<?php echo $attachment; ?> 

--PHP-mixed-<?php echo $random_hash; ?>-- 

<?php 
//copy current buffer contents into $message variable and delete current output buffer 
$message = ob_get_clean(); 
//send the email 
mail( $to, $subject, $message, $headers );

Can anyone help?!

2
  • I would recommend not jumping in and out of PHP like this. It makes your code difficult to read. Commented Jan 31, 2012 at 15:30
  • I strongly recommend the usage of an existing Class for a task like this! See pear.php.net/manual/en/package.mail.mail-mime.addattachment.php Commented Jan 31, 2012 at 15:31

3 Answers 3

2

First thing, don't re-invent the wheel - use a library such as Pear Mail http://pear.php.net/package/Mail/redirected

Secondly, you have whitespace between your headers and that isn't allowed.

From the Mail RFC:

There are several places in this standard where comments and FWS may be freely inserted. To accommodate that syntax, an additional token for "CFWS" is defined for places where comments and/or FWS can occur. However, where CFWS occurs in this standard, it MUST NOT be inserted in such a way that any line of a folded header field is made up entirely of WSP characters and nothing else.

Kind regards,

John

Sign up to request clarification or add additional context in comments.

1 Comment

Hi there, thanks for this - Pear Mail proved a million times easier!
1

Here's what I use that works. It doesn't take into account text version vs. HTML version...just an HTML version only, but perhaps it will guide you toward an answer:

<?php
    $mime_boundary = md5(uniqid(time()));

    // to
    $to = $_REQUEST["to"];
    if (is_array($to)) $to = implode(", ", $to);

    // from
    $header = "From:". ($_REQUEST["fromName"] == "" ? $_REQUEST["fromAddress"] : "{$_REQUEST["fromName"]} <{$_REQUEST["fromAddress"]}>") ."\r\n";
    $header .= "MIME-Version:1.0\r\n";
    $header .= "Content-Type:multipart/mixed; boundary=\"{$mime_boundary}\"\r\n\r\n";

    // message
    $header .= "--{$mime_boundary}\r\n";
    $header .= "Content-Type:text/html; charset=\"ISO-8859-1\"\r\n";
    $header .= "Content-Transfer-Encoding:7bit\r\n\r\n";
    $header .= "<html><head><style type=\"text/css\">body { font:10pt Arial; }</style></head><body>". str_replace("\r", "", str_replace("\n", "<br />", $_REQUEST["message"])) ."</body></html>\r\n\r\n";

    // attachment
    $attachments = (array)$_REQUEST["attachment"];
    $attachmentNames = (array)$_REQUEST["attachmentName"];
    for ($i = 0; $i < count($attachments); $i++)
    {
        if (empty($attachmentNames[$i]))
            $attachmentNames[$i] = "attachment". ($i+1) .".txt";

        if (!base64_decode($attachments[$i], true))
            $attachments[$i] = base64_encode($attachments[$i]);
        else
            $attachments[$i] = str_replace("\r", "", str_replace("\n", "", str_replace(" ", "+", $attachments[$i])));

        $header .= "--{$mime_boundary}\r\n";
        $header .= "Content-Type:application/octet-stream; name=\"{$attachmentNames[$i]}\"\r\n";
        $header .= "Content-Transfer-Encoding:base64\r\n";
        $header .= "Content-Disposition:attachment; filename=\"{$attachmentNames[$i]}\"\r\n";
        $header .= "{$attachments[$i]}\r\n\r\n";
    }

    if (mail($to, $_REQUEST["subject"], "", $header))
        echo "SUCCESS";
    else
        echo "FAIL";
?>

1 Comment

Thanks for taking the time to reply, I've actually gone with using the PEAR mail library, much easier than doing everything from scratch and I can get text/html AND attachments! Cheers!
1

Maybe you want to take a look on PHPmailer. It offers all the functionality you want to use, but in a much cleaner and uptodate-standard way than the build-in mail() function. And there are some good tutorials out there.

1 Comment

Thanks for this, I've actually gone with PEAR Mail as suggested by John (above), but the idea is the same - much easier than messing about trying to code everything from scratch!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.