View Full Version : Extra "scrap" attachment sent - PHP mail() with multiple attachments

03-29-2010, 07:54 PM
I'm having a hard time googling an answer for this one. I am just starting to dabble in adding attachments to an e-mail being sent with mail(). I found some online tutorials and examples for adding a single attachment and some for adding multiple attachments and I have cobbled together my own working multiple attachment e-mail processing page but I have been getting garbage attachment(s) along with the actual files being sent. I can't figure out why.

Here is my full code for the processing page:

0 => Array(
'title' => 'UPLOAD_ERR_OK',
'message' => 'Value: 0; There is no error, the file uploaded with success.'
1 => Array(
'title' => 'UPLOAD_ERR_INI_SIZE',
'message' => 'Value: 1; The uploaded file exceeds the upload_max_filesize directive in php.ini.'
2 => Array(
'title' => 'UPLOAD_ERR_FORM_SIZE',
'message' => 'Value: 2; The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'
3 => Array(
'title' => 'UPLOAD_ERR_PARTIAL',
'message' => 'Value: 4; No file was uploaded.'
4 => Array(
'title' => 'UPLOAD_ERR_NO_FILE',
'message' => 'Value: 4; No file was uploaded.'
5 => Array(
'title' => 'RESERVED?',
'message' => 'No error message is available for this error number.'
6 => Array(
'title' => 'UPLOAD_ERR_NO_TMP_DIR',
'message' => 'Value: 6; Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.'
7 => Array(
'message' => 'Value: 7; Failed to write file to disk. Introduced in PHP 5.1.0.'
8 => Array(
'message' => 'Value: 8; A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help. Introduced in PHP 5.2.0.'
foreach($_FILES['file']['tmp_name'] as $key=>$value){

foreach($path_to_files as $key=>$value){
//copy files to local directory...
$errors .= '\n error while copying the uploaded file';

//send form data via e-mail

function send_form($to, $from, $subject, $file_uploads){
// $fileatt // Path to the file
// $fileatt_type //MIME type of the file
// $fileatt_name // Filename that will be used for the file as the attachment

$email_to = $to; // Who the email is to
$email_from = $from; // Who the email is from
$email_subject = $subject; // The Subject of the email
$email_message = "Form Data Submitted:\n\n"; // Message that the email has in it

//Needs work to clean up and secure the form input from header injection attacks...
foreach($_POST as $key=>$value){
if($key != "submit"){
$email_message.="<li>".$heading.": ".$response."</li>\n";

$headers = "From: ".$email_from;

$semi_rand = md5(time()); //setting a "unique" boundary for the server to recognize the start and end of the multipart data
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

$headers .= "\nMIME-Version: 1.0\n" .
"Content-Type: multipart/mixed;\n" .
" boundary=\"{$mime_boundary}\"";

$email_message .= "This is a multi-part message in MIME format.\n\n" .
"--{$mime_boundary}\n" .
"Content-Type:text/html; charset=\"iso-8859-1\"\n" .
"Content-Transfer-Encoding: 7bit\n\n" .
$email_message . "\n\n";

print "There are ".count($file_uploads)." files<br />\n";
print "<ul>\n";
foreach($file_uploads as $key=>$value){
print "<li><a href=\"/process.php#".$file_uploads[$key]['name']."\">".$file_uploads[$key]['name']."</a></li>\n";
print "</ul>\n";

$fileatt = $file_uploads[$i]['location']; // Should be the full path to the file
$fileatt_type = $file_uploads[$i]['mime_type'];

print "<br />\n<br />\n<br />\n<br />\n<br />\n<br />\n<br />\n<br />\n<br />\n<br />\n <h1 id=\"".$fileatt_name."\">This file is named \"".$fileatt_name."\"</h1><br />\n";

$file = fopen($fileatt,'rb');
$data = fread($file,filesize($fileatt));
$data = chunk_split(base64_encode($data));
$email_message .= "--{$mime_boundary}\n";
$email_message .= "Content-Type: {$fileatt_type};\n" .
" name=\"{$fileatt_name}\"\n" .
"Content-Transfer-Encoding: base64\n\n" .
$data . "\n\n" .
$ok = @mail($email_to, $email_subject, $email_message, $headers);
if($ok) {
return true;
return false;

$subject="Upload Confirmation";
$attachments = $_FILES['file']['tmp_name'];

$sent = send_form($to,$from,$subject,$uploaded_files);
print "<h3>Form Sent</h3>\n";
print "<h3>Form NOT Sent</h3>\n";
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link type="image/x-icon" href="/favicon.ico" rel="shortcut icon"/>

<script type="text/javascript">

<style type="text/css">
* {margin:0;padding:0;border:0;}

<h3>Input Data:</h3>
<?php print"<div style=\"white-space:pre;width:500px;padding:5px;border:1px solid #000;\">";print_r($_POST);print"</div>"; ?>
<h3>Files Submitted:</h3>
<?php print"<div style=\"white-space:pre;width:500px;padding:5px;border:1px solid #000;\">";print_r($files);print"</div>"; ?>

The form data and uploaded files are fed in from a separate form page. I am using form names of "file[]" for each upload item. I have no problems getting the data to submit, no problems copying the files out of the temp directory into my uploads folder, and no problems sending the e-mail.

I only had some problems working out the details for the attachments but I thought I had them almost completely sorted out. The attachments arrive unmarred, correctly named, and properly formatted -- but they suddenly have a tag-along little friend named ATT00001 (size of about 280 bytes). Can someone please tell me why this is happening and how I can kill this little guy?

I'm figuring I have some problem with my $headers data causing this but I can't spot it.