Sending email with multiple attachments with PHP

Today I was looking for a cut/paste script to manage emails with multiple attachments with php and I only found classes, server-side libraries or non-working examples (!!!).

I just needed an easy script and I did not find it… so I cut/pasted here and there, I changed something, shaked a bit and here it is an easy and working script.

Just fill $files array with the files to be sent, custom email fields and you’re done.

Enjoy and send mails with any number of attachments without any class/library

  • You have to be careful with the mail function.

    Some free hosts disable it.

  • I would also appreciate how to send those mails right from the form – especialy how to attach multiple files and then send them.

  • Mrinalini

    Hey, its a nice script but how to attach files at run time?

  • A perfect script. I was quite fagged out trying to correct a code sending a single attachment and got no where. Great work.

  • sasha

    It would be great to know how to make form for uploading files and storing in this array. I am beginner in PHP. Anyone help, please?

  • Stephen

    Thanks for the multiple attachments code. I found what appears to be a problem with it though. For the very last file, I think you need a “–” at the end of the mime boundary hash; i.e., “–{$mime_boundary}–\n”. Otherwise, I get an extra empty file attached to the email called “ATT000??.txt”.

  • Godd Example to send multiple attachment in PHP
    thank you very much for your help

  • prosenjit das

    Thank You … It is really helpful for my project … thanx lots ..

  • jerry

    hey
    I cant get it to work , what do I need to do with it
    btw I am sort of new to php
    pleas help me anyone

  • Roxie

    The script works great except for one thing.
    I always get an extra file “ATT000XX.txt” that is empty.

    I trying adding “-” to the end of “–{$mime_boundary}”. I added it to just the one in the loop, out of the loop and every combination in between.

    Nothing seems to work.

    How do I get that file to not be attached?

    Thanks.

  • ioulianos

    I had the same experience, especially with examples that didn’t work or corrupt attachments, until I found your code.

    Thans a lot !!!

  • Umesh

    gr8 work ! but there is problem of extra file “ATT000XX.txt”.

    i found a way in which we can solve this problem as follows;

    $just=count($files);
    for($x=0;$x<count($files);$x++){
    $file = fopen($files[$x],”rb”);
    $data = fread($file,filesize($files[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= “Content-Type: {\”application/octet-stream\”};\n” . ” name=\”$files[$x]\”\n” .
    “Content-Disposition: attachment;\n” . ” filename=\”$files[$x]\”\n” .
    “Content-Transfer-Encoding: base64\n\n” . $data . “\n\n”;
    if($x==($just-1))
    {
    $message .= “–{$mime_boundary}-\n”;
    } else
    {
    $message .= “–{$mime_boundary}\n”;
    }

    }

  • Umesh

    replace the for loop with this code

    $just=count($files);
    for($x=0;$x<count($files);$x++){
    $file = fopen($files[$x],”rb”);
    $data = fread($file,filesize($files[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= “Content-Type: {\”application/octet-stream\”};\n” . ” name=\”$files[$x]\”\n” .
    “Content-Disposition: attachment;\n” . ” filename=\”$files[$x]\”\n” .
    “Content-Transfer-Encoding: base64\n\n” . $data . “\n\n”;
    if($x==($just-1))
    {
    $message .= “–{$mime_boundary}-\n”;
    } else
    {
    $message .= “–{$mime_boundary}\n”;
    }

    }

  • Line 10 can be skipped because of line 21.

  • pcsimke

    this worked for me butt i get that extra file

    strange thing in windows mail there is no extra file
    in outlook i got it

    i tray Umesh thing butt then i got only one attachment

    i include 3 of them

  • Ichah

    this worked for me butt i get that extra file

    strange thing in windows mail there is no extra file
    in outlook i got it

    i tray Umesh thing butt then i got only one attachment

    i include 3 of them

    instead of –{$mime_boundary}\n this use
    –-{$mime_boundary}–\n

  • ichha

    instead of –{$mime_boundary}\n this use
    –-{$mime_boundary}–-\n

  • Dave

    I am having issues with multiple attachments. Only the fist one is getting attached while the other files aren’t. Any ideas?

  • Nick

    I also had issues with an extra attachment, but this did solve the problem:

    Original:
    Line 33:
    $message .= “–{$mime_boundary}\n”;

    FIX:
    $message .= “–{$mime_boundary}–\n”;

  • Nick

    Hmm, for some reason, WordPress combines 2 hashes “- -” into one hash: “–”

    So to clarify, you want 2 hashes before and after {$mime_boundary}

  • Mike Engel

    Thanks Emanuele!!! Great script. Since a lot of people above seem to be having the same problem and I solved said problem, I will show my improved version that worked for me with 0 attachments, 1 attachment and more than 1 attachment without the extra txt file or gibberish at the end. Maybe u can re-post this if u get a chance.

    <?php

    // array with filenames to be sent as attachment

    $files = array("filename.blah", "filename.blah");
    $filecount=count($files);
    // email fields: to, from, subject, and so on
    $to = "blah@blah.com";
    $from = "blah@blah.com";
    $subject ="testemail";
    $message = "testing if the script i downloaded works";
    $headers = "From: $from";

    // boundary
    $semi_rand = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

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

    // multipart boundary
    $message = "This is a multi-part message in MIME format.\n\n" . "–{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
    if($filecount!=0)
    {
    $message .= "–{$mime_boundary}\n";
    }

    // preparing attachments
    for($x=0;$x<$filecount;$x++)
    {

    $file = fopen($files[$x],"rb");
    $data = fread($file,filesize($files[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    if($x==$filecount-1)
    {
    $message .= "–{$mime_boundary}-\n";
    }

    else
    {
    $message .= "–{$mime_boundary}\n";
    }
    }

    // send
    $ok = @mail($to, $subject, $message, $headers);
    if ($ok)
    {
    echo "mail sent to $to!”;
    }
    else
    {
    echo “mail could not be sent!”;
    }

    ?>

  • Hi,
    This code works but the initial problem was that it was attaching the empty text file but i used the new code like here specified i replaced the loop with that just variable and even the last code

    <?php

    // array with filenames to be sent as attachment

    $files = array("filename.blah", "filename.blah");
    $filecount=count($files);
    // email fields: to, from, subject, and so on
    $to = "blah@blah.com";
    $from = "blah@blah.com";
    $subject ="testemail";
    $message = "testing if the script i downloaded works";
    $headers = "From: $from";

    // boundary
    $semi_rand = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

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

    // multipart boundary
    $message = "This is a multi-part message in MIME format.\n\n" . "–{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
    if($filecount!=0)
    {
    $message .= "–{$mime_boundary}\n";
    }

    // preparing attachments
    for($x=0;$x

    the extra txt file is removed but it is attaching only one file not all the files name that i gave in the array please provide me the solution for that so that it will attach all the files without extra txt file.

  • Wilson Abesamis

    Try this it really works on my side.

    $value){
    $ctr_file++;
    $att_file = $_FILES[$idx][‘tmp_name’];
    $att_file_type = $_FILES[$idx][‘type’];
    $att_file_name = $_FILES[$idx][‘name’];

    if (is_uploaded_file($att_file)) {

    // Read the file to be attached (‘rb’ = read binary)
    $file = fopen($att_file,’rb’);
    $data = fread($file,filesize($att_file));
    fclose($file);

    // Base64 encode the file data
    $data = chunk_split(base64_encode($data));

    // Add file attachment to the message
    $message .= “Content-Type: {$att_file_type};\n” .
    ” name=\”{$att_file_name}\”\n” .
    “Content-Disposition: attachment;\n” .
    ” filename=\”{$att_file_name}\”\n” .
    “Content-Transfer-Encoding: base64\n\n” .
    $data . “\n\n”;

    $message .= ($ctr_file != count($_FILES)) ? “–{$mime_boundary}\n” : “–{$mime_boundary}–\n”;
    }
    }

    echo mail($to,$subject,$message,$headers) ? ‘mail sent with attached files’ : ‘mail not sent!’;
    }
    ?>

  • Srig

    Simply superb.. its wrkin fine dude…

  • Swaroop

    HI, can any one hellp me out, I have mentioned the following code, we are reciving an email with the text format – ATT0029.txt , the following code as mentioned, we are trying to attach a word format and submit

    / Build email data
    // generate a random string to be used as the boundary marker
    $mime_boundary = “==Multipart_Boundary_x”.md5(mt_rand()).”x”;

    // open the file for a binary read
    $file = fopen($this->attachment, ‘rb’);
    // read the file content into a variable
    $data = fread($file, filesize($this->attachment));
    // close the file
    fclose($file);
    // now we encode it and split it into acceptable length lines
    $data = chunk_split(base64_encode($data));
    $file_name = explode(“\\”, $this->attachment );
    // now we’ll build the message headers
    $headers = “From: $from\r\n” . “MIME-Version: 1.0\r\n” . “Content-Type: multipart/mixed;\r\n” . ” boundary=\”{$mime_boundary}\””;
    // next, we’ll build the message body
    // note that we insert two dashes in front of the
    // MIME boundary when we use it
    $message = “This is a multi-part message in MIME format.\n\n” . “–{$mime_boundary}\n” . “Content-Type: text/plain; charset=\”iso-8859-1\”\n” . “Content-Transfer-Encoding: 7bit\n\n” . $message_body . “\n\n”;
    // now we’ll insert a boundary to indicate we’re starting the attachment
    // we have to specify the content type, file name, and disposition as
    // an attachment, then add the file content and set another boundary to
    // indicate that the end of the file has been reached
    $message .= “–{$mime_boundary}\n” . “Content-Type: text/plain;\n” . ” name=\”{$file_name[1]}\”\n” .
    “Content-Disposition: attachment;\n” .
    // ” filename=\”{$fileatt_name}\”\n” .
    “Content-Transfer-Encoding: base64\n\n” . $data . “\n\n” . “–{$mime_boundary}–\n”;

    Please help me out with the solution

  • danny

    It doesnt work at all, sometimes it adds 2 attachment other times nothing. The code of Wilson Abesamis is not complete, pls send the complete code

    THanks

    Dabby

  • jithin

    works.. but attachment recieves like text

  • Pingback: MySQL to JSON with PHP : Emanuele Feronato()

  • carl

    I made to changes to the original

    replace line 22 with:
    if (count($files)){
    $message .=”–{$mime_boundary}\n”;
    }
    else{
    $message .=”–{$mime_boundary}–\n”;
    }

    replace line 33 with:
    if ($x==count($files)-1){
    $message .=”–{$mime_boundary}–\n”;
    }
    else{
    $message .=”–{$mime_boundary}\n”;
    }

    this handles extra file problem and allows for no files or multiple files to be sent

  • carl

    Retool here ==You can leave lime 22 as is, but change lime 33 as mentioned above

  • How do I name the files to be attached with files which have been uploaded as part of a form to complete the following line?

    (“file_1.ext”,”file_2.ext”,”file_3.ext”,……);

  • Shaaa

    Nice Script… :)

  • Marten Hansson

    Such a great script! Been testing script on the net for >10hrs without findng what I was looking for. Until now. Thanks from Sweden!

  • Marten Hansson

    Oh forgot to say, if you want to send the message in html instead of plain text, just change Content-Type from text/plain to text/html.

  • john

    file_get_contents() has been available since php 4.3.0 (release in 2002):

    $data = chunk_split( base64_encode(file_get_contents(“$files[$x]”)) );

  • Daibhidh

    This looks like a great script and works fine, wit the exception of the extra empty attachment. Lots of people have suggested fixes, but it’s not very clear which fix actually work…would anyone who’s got the script to work be able to post the full amended script on here?

    Many thanks :)

  • This is my modification which solved for me problem of unwanted file:

    // preparing attachments
    $counted = count($files);
    for($x=0;$x<$counted;$x++){
    $data = chunk_split( base64_encode(file_get_contents("$files[$x]")) );
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    if($x < $counted-1){
    $message .= "–{$mime_boundary}\n";
    }else{
    $message .= "–{$mime_boundary}-\n";
    }
    }

  • bobdole

    Thanks for this snippet, it provided an excellent starting place.
    I had issues with this script however, after reading the comments and looking over various other pages I managed to piece something together that works well. This should work for both 0 and more than 0 files. I added the proper elements to support utf8 encoded messages in the subject, filename and body. You may need to alter the script for your application but this may save some time:

    //begin_example

    $to_address = “someaddress@something.com”;
    $second_to_address = “someotheraddress@something.com”;

    $to = “$to_address”. “, “; // note the comma
    $to .= “$second_to_address”;

    $from_name = “Bob Dole”;
    $from_email = “bob@dole.com”;

    $additional_email1 = “add1@something.com”;
    $additional_email2 = “add2@something.com”;
    $additional_email3 = “add3@something.com”;

    $sub = “Test Subject”;

    //utf-8 handling
    $subject = “=?UTF-8?B?”;
    $subject .= base64_encode($sub);
    $subject .=”?=\n”;

    //UTF-8 from header
    $headers = “From: =?UTF-8?B?”.base64_encode($from_name).”?= \r\n”;

    if(empty($additional_email1)){}else{ $headers .= “CC: \r\n”; }
    if(empty($additional_email2)){}else{ $headers .= “CC: \r\n”; }
    if(empty($additional_email3)){}else{ $headers .= “CC: \r\n”; }

    $body = ” Test email body”;

    //path to files relative to the document
    $attachment_path = “attachments/some_folder”;

    //you can easily create a function that reads a directory and returns an array of files or “empty” . The if statement below will allow empty to properly format the mail for no attachments.
    $dir_contents = array(“file_1.ext”,”file_2.ext”,”file_3.ext”);

    $files = $dir_contents;

    //random number for MIME boundary
    $semi_rand = md5(time());
    //the MIME boundary
    $mime_boundary = “==Multipart_Boundary_x{$semi_rand}x”;

    //add the headers for attachment

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

    // multipart boundary
    $msg = “This is a multi-part message in MIME format.\n\n”.”–{$mime_boundary}\n”.”Content-type: text/plain; charset=UTF-8\n”.”Content-Transfer-Encoding: 8bit\n\n”.$body.”\n\n”;

    //attachment code
    //if the files array isn’t empty attach the files, else don’t run the attachment code
    if( $files “empty”){

    $counted = count($files);
    for($x=0;$x<$counted;$x++){
    $msg .= "–{$mime_boundary}\n";
    $data = chunk_split(base64_encode(file_get_contents("".$attachment_path."/".$files[$x]."")) );
    $msg .= "Content-Type: application/octet-stream;\n"
    ." name=\"=?UTF-8?B?".base64_encode($files[$x])."?=\"\n".
    "Content-Disposition: attachment;\n" ." filename=\"=?UTF-8?B?".base64_encode($files[$x])."?=\"\n"
    ."Content-Transfer-Encoding: base64\n\n".$data."\n\n";
    }

    }

    $res = @mail($to, $subject, $msg, $headers);

    if($res){

    return TRUE;

    }
    else
    {
    return FALSE;
    }

    //end_example

  • you have just saved me soooo much work

  • Jerrid

    I am very new to coding PHP. In fact, I am learning it on the fly because of a client. I need to attach four files from a form and send them. I am using the file attach button from Dreamweaver CS3. How do I set the file names in this array?

    // array with filenames to be sent as attachment
    $files = array(“file_1.ext”,”file_2.ext”,”file_3.ext”,……);

    Do I have to set variable that look at each form field?

    I am lost and could really use some help.

    These are all going to be text files, by the way, if that matters.

  • bobdole

    Jerrid, check http://php.net/manual/en/reserved.variables.files.php . Essentially it all starts with the $_FILES superglobal variable. To see what the array looks like I use “print_r($_FILES); ” ( http://php.net/manual/en/function.print-r.php) . There is a good example of how to use print_r with some “pre” tags to view arrays ( which makes them more manageable ). I wouldn’t implement a send attachment without some sort of validation mainly so you can control file size and types being sent. Check http://php.net/manual/en/function.move-uploaded-file.php for some information on the move_uploaded_file function. They have a good uploading multiple files example there. BTW my post above has some issues because this form submission seems to strip characters such as greater than and less than signs hopefully everyone can figure out how to fill in the gaps.

  • LeXtruX

    Nice script, works fine for me, except that I get things like this where usually the first lines of my mail contents show in gmail: – PNG IHDR – – < qâ pHYs šœ OiCCPPhotoshop ICC profile xÚ SgTSé =÷ÞôBKˆ€”KoR RB … and I don't want that at all… because it looks like you get a virus of some sort (if you are a noob at things like this, I need it for a CMS so I can't really use smth like that to show in the mail headers right?

  • Tarek

    GREAT YET SIMPLE. THANKS

  • Andrew Strickland

    heres a form processing code I wrote that uploads 3 files without using an array… also requires re-captcha but you can take that out of the code if needed…also does some PHP validation… still gona add some file extension validations and file size… name of file attachments on form are fileatt, fileatt2, and fileatt3…hope this helps someone.

    require_once(‘recaptchalib.php’);
    $privatekey = “6LdvfQwAAAAAAIqtAC0RV1XXPwSq8oMbqJz9xP4Y”;
    $resp = recaptcha_check_answer ($privatekey,
    $_SERVER[“REMOTE_ADDR”],
    $_POST[“recaptcha_challenge_field”],
    $_POST[“recaptcha_response_field”]);

    if (!$resp->is_valid) {
    $result = $result . “A small problemPlease Go back and try it again.” .
    “(” . $resp->error . “)”;
    }

    elseif (!($firstname && $lastname && $city && $country && $contactPhone && $email)) {$result = $result . “ERROR: Please Re-apply, Fill all fields marked *“;
    }
    elseif (!eregi(“^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$”, $email)) {$result = $result . “ERROR: Email Not Valid”;
    }
    else{

    $firstname = $_POST[‘firstname’];
    $lastname = $_POST[‘lastname’];
    $businessName = $_POST[‘businessName’];
    $streetAddress = $_POST[‘streetAddress’];
    $city = $_POST[‘city’];
    $country = $_POST[‘country’];
    $contactPhone = $_POST[‘contactPhone’];
    $mobilePhone = $_POST[‘mobilePhone’];
    $fax = $_POST[‘fax’];
    $email = $_POST[’email’];
    $from = $_POST[‘firstname’];
    $from .= $_POST[‘lastname’];

    if(isset($_POST[‘checkValves’])&&
    $_POST[‘checkValves’] == ‘1’)
    {
    $requested = $requested . ” Check Valves, “;
    }

    if(isset($_POST[‘fireValves’])&&
    $_POST[‘fireValves’] == ‘1’)
    {
    $requested = $requested . ” Fire Valves, “;
    }
    if(isset($_POST[‘flanges’])&&
    $_POST[‘flanges’] == ‘1’)
    {
    $requested = $requested . ” Flanges, “;
    }
    if(isset($_POST[‘guageGlassFittings’])&&
    $_POST[‘guageGlassFittings’] == ‘1’)
    {
    $requested = $requested . ” Guage Glass Fittings, “;
    }
    if(isset($_POST[‘globeValves’])&&
    $_POST[‘globeValves’] == ‘1’)
    {
    $requested = $requested . ” Globe Valves, “;
    }
    if(isset($_POST[‘safetyValves’])&&
    $_POST[‘safetyValves’] == ‘1’)
    {
    $requested = $requested . ” Safety Valves, “;
    }
    if(isset($_POST[‘sightGlasses’])&&
    $_POST[‘sightGlasses’] == ‘1’)
    {
    $requested = $requested . ” Sight Glasses, “;
    }
    if(isset($_POST[‘steamEjectors’])&&
    $_POST[‘steamEjectors’] == ‘1’)
    {
    $requested = $requested . ” Steam Ejectors, “;
    }
    if(isset($_POST[‘steamUnions’])&&
    $_POST[‘steamUnions’] == ‘1’)
    {
    $requested = $requested . ” Steam Unions, “;
    }
    if(isset($_POST[‘treacleCocks’])&&
    $_POST[‘treacleCocks’] == ‘1’)
    {
    $requested = $requested . ” Treacle Cocks, “;
    }
    if(isset($_POST[‘vacuumBreakValves’])&&
    $_POST[‘vacuumBreakValves’] == ‘1’)
    {
    $requested = $requested . ” Vacuum Break Valves, “;
    }
    if(isset($_POST[‘other’])&&
    $_POST[‘other’] == ‘1’)
    {
    $requested = $requested . ” Other, “;
    }

    $additionalDetails = $_POST[‘additionalDetails’];

    // Obtain file upload vars
    $file_name = $_FILES[‘fileatt’][‘name’];
    $temp_name = $_FILES[‘fileatt’][‘tmp_name’];
    $file_type = $_FILES[‘fileatt’][‘type’];
    // Obtain file upload vars
    $file_name2 = $_FILES[‘fileatt2’][‘name’];
    $temp_name2 = $_FILES[‘fileatt2’][‘tmp_name’];
    $file_type2 = $_FILES[‘fileatt2’][‘type’];
    // Obtain file upload vars
    $file_name3 = $_FILES[‘fileatt3’][‘name’];
    $temp_name3 = $_FILES[‘fileatt3’][‘tmp_name’];
    $file_type3 = $_FILES[‘fileatt3’][‘type’];

    $to = “dd@vodafone.co.nz”;
    $subject = “Price Enquiry Form”;

    $info = “First Name(s): ” . $firstname . “\n”;
    $info .= “Last Name: ” . $lastname . “\n”;
    $info .= “Business Name: ” . $businessName . “\n”;
    $info .= “Street Address: ” . $streetAddress . “\n”;
    $info .= “City: ” . $city . “\n”;
    $info .= “Country: ” . $country . “\n”;
    $info .= “Contact Phone: ” . $contactPhone . “\n”;
    $info .= “Mobile Phone: ” . $mobilePhone . “\n”;
    $info .= “Fax: ” . $fax . “\n”;
    $info .= “Email: ” . $email . “\n\n”;

    $info .= “Requested Info for: ” . $requested . “\n\n”;
    $info .= “Additional Details: ” . $additionalDetails . “\n”;
    $message = $info;

    // things you need
    $file = $temp_name;
    $content = chunk_split(base64_encode(file_get_contents($file)));
    $uid = md5(uniqid(time()));

    $header = “From: $firstname $lastname \n” .
    $header = “Reply-To: $email \r\n” ;
    $header .= ‘Cc: fd@vodafone.co.nz‘ . “\r\n”;
    $header .= “MIME-Version: 1.0\r\n”;

    // declaring we have multiple kinds of email
    $header .= “Content-Type: multipart/mixed; boundary=\””.$uid.”\”\r\n\r\n”;
    $header .= “This is a multi-part message in MIME format.\r\n”;

    // plain text part
    $header .= “–“.$uid.”\r\n”;
    $header .= “Content-type:text/plain; charset=iso-8859-1\r\n”;
    $header .= “Content-Transfer-Encoding: 7bit\r\n\r\n”;
    $header .= $message.”\r\n\r\n”;

    //file attachment
    $header .= “–” .$uid. “\r\n”;
    $header .= “Content-Type: “.$file_type.”; name=\””.$file_name.”\”\r\n”;
    $header .= “Content-Transfer-Encoding: base64\r\n”;
    $header .= “Content-Disposition: attachment; filename=\””.$file_name.”\”\r\n\r\n”;
    $header .= $content.”\r\n\r\n”;

    //file attachment 2
    $header .= “–” .$uid. “\r\n”;
    $header .= “Content-Type: “.$file_type2.”; name=\””.$file_name2.”\”\r\n”;
    $header .= “Content-Transfer-Encoding: base64\r\n”;
    $header .= “Content-Disposition: attachment; filename=\””.$file_name2.”\”\r\n\r\n”;
    $header .= $content.”\r\n\r\n”;

    //file attachment 3
    $header .= “–” .$uid. “\r\n”;
    $header .= “Content-Type: “.$file_type3.”; name=\””.$file_name3.”\”\r\n”;
    $header .= “Content-Transfer-Encoding: base64\r\n”;
    $header .= “Content-Disposition: attachment; filename=\””.$file_name3.”\”\r\n\r\n”;
    $header .= $content.”\r\n\r\n”;

    $ok = @mail($to, $subject, “”, $header );
    if ($ok){
    $result = $result . “Thank You” . $firstname . ” for Your Enquiry!\n We will contact you asap\n”;
    }else {
    $result = $result . “Sorry” . $firstname . ” There was a Problem sending the Form\n Please Try Again\n”;
    }
    }
    include ‘thankyou.php’;

    • saravanann

      good morning sir
      i need sending file with attachment the file via php. this program need pls send my email id i trust you thank you sir

  • Andrew Strickland

    also 4got to mention that the included thankyou.php has a div that echos $result…

  • Andrew Strickland

    ok mine didnt quite work… it’s attaching the file info but the full file isnt being attached? can any1 see wats wrong with my code?

  • Andrew Strickland

    ok someone delete all my posts and if anybody cud help me make my code into an array uploading email form?

  • Deepak

    Thank you

  • Arjun

    Took a few pointers from here. Thanks!

  • Dipen

    Thank you

  • If you want a complete working script, see below;
    This removes any extra attachments, and makes sure all attachments are included. No additional text in the body, no missing files! Enjoy!

    <?php
    // array with filenames to be sent as attachment
    $path1 = "path/to/file1.ext";
    $path2 = "path/to/file2.ext";
    $patharray = array("$path2", "$path1");
    $files = array("file2.ext", "file1.ext");
    // email fields: to, from, subject, and so on
    $to = "email@youremail.com";
    $from = "email@youremail.com";
    $subject = "Subject title here";
    $message = "Write a message for email body here \n \n";
    $headers = "From: $from";
    // boundary
    $semi_rand = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
    // headers for attachment
    $headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" .
    " boundary=\"{$mime_boundary}\"";
    // multipart boundary
    $message = "This is a multi-part message in MIME format.\n\n" . "–{$mime_boundary}\n" .
    "Content-Type: text/plain; charset=\"iso-8859-1\"\n" .
    "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";
    // preparing attachments
    $just = count($files);
    for ($x = 0; $x < count($files); $x++) {
    $file = fopen($patharray[$x], "rb");
    $data = fread($file, filesize($patharray[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    if ($x < $just – 1) {
    $message .= "–{$mime_boundary}\n";
    } else {
    $message .= "–{$mime_boundary}–\n";
    }
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    if ($x

  • Dayan

    Hi Daniel E. The code you pasted is incomplete. Could you please re-paste? Cheers mate.

  • hey…
    i upload multiple file first nd store it in a folder
    nw can any1 teme hw to send dose files…..

  • Lost hours with other broken scripts till I find yours. You’re my saviour! Works like a charm!

    If you want to send multiple email attachments with PHP using the mail function, search no more.

  • Craigy

    hi

    For anybody still struggling with the extra empty text attachment, the following worked for me. I’ve only tested it when there will always be at least 1 attachment.

    Change

    $message .= “–{$mime_boundary}\n”;

    to

    if ($x<=count($files)-2)
    {
    $message .= "–{$mime_boundary}\n";
    }

    note there should be two hyphens before {$mime_boundary}, not 1

  • Pingback: Send multipul attatchments php. « mistersaisho.com()

  • leizle_ho

    this is my modification that solved the unwantend file “AT00001.txt”

    // preparing attachments
    for($x=0;$x<count($files);$x++){
    $file = fopen($files[$x],"rb");
    $data = fread($file,filesize($files[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    if ($x==count($files)-1){
    $message .= "–{$mime_boundary}–\n";
    } else
    {
    $message .= "–{$mime_boundary}\n";
    }
    }

  • juggy

    this works!!! just tested if for email with 1, 2 and no attachments!!!

    I have split into parts;

    PART1;
    <?php
    // email fields: to, from, subject, and so on
    $to = $_POST['to'];
    $from = $_POST['from'];
    $message = $_POST['message'];
    $headers = "From: $from";

    // array with filenames to be sent as attachment
    //$path1 = "";
    $path1 = "upload/avatar1.jpg"; //your path to your file1

    //$path2 = "";
    $path2 = "upload/avatar2.jpg"; //your path to your file2

  • juggy

    PART2;
    ////////////////////////////
    //CHECK IF FILES UPLOADED!!!
    // if path1 & path2 uploaded
    if ((!empty($path1)) && (!empty($path2))) {
    $files = array($path1, $path2);
    $subject = “if path1 & path2 uploaded”;
    include(“mail_include.php”);

    // if path1 only uploaded
    } else if ((!empty($path1)) && (empty($path2))) {
    $files = array($path1);
    $subject = “if path1 only uploaded”;
    include(“mail_include.php”);

    // if path2 only uploaded
    } else if ((empty($path1)) && (!empty($path2))) {
    $files = array($path2);
    $subject = “if path2 only uploaded”;
    include(“mail_include.php”);

    // if no path uploaded
    } else {
    $subject = “if no paths uploaded”;
    }

  • juggy

    PART3;
    ////////////////////////////
    // SEND MAIL
    $ok = @mail($to, $subject, $message, $headers);
    if ($ok) {
    echo “mail sent to $to!”;
    } else {
    echo “mail could not be sent!, PLEASE CONTACT US FOR A QUOTE”;
    }
    ?>

  • juggy

    PART4;
    //mail_include.php
    <?php
    // boundary
    $semi_rand = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

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

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

    // preparing attachments
    for($x=0;$x

  • juggy

    // preparing attachments
    for($x=0;$x

  • suman

    How attached full path with $files = array(“123pengerorg.pdf”,”123penger.pdf”);

  • I was looking for an email script for multiple pdf attachments and found your script working perfectly as per my requirement. Thank you very much for the help

  • Poovaraghavan

    Tnks Dude It s realy work..i was search lot but this only solution for me thnk s dude…

  • Rajeev Raj Karn

    It is such a great script

  • curiousUser

    how to fix the code so that when it sends emails there is
    not that extra blank ATT00001..txt file?
    I tried all the solutions in the comments above and none of them work when
    am i trying to send 2 files. it only sends 1 file.

  • add this at line 36

    $message .="--";

    Will get rid of that text file.

    Way easier then changing the loop!

    luke-roberts.info

  • John

    Thanks dude.

    its really a great code , i just put it and working fine.

    Thanks.

  • This code worked out fine from the first time, I know not all hosts permit attachments, but in my case did the job, thank you very much

  • Myles

    Luke, your fix doesn’t work.

    $message .=”–“;

    wish it had! :(

  • Jeff

    This post we very helpful. I thought I’d add an implementation that included uploading the files from an HTML form.

    $email_to = “destination@email.address”;
    $email_subject = “Test Subject”;
    $email_from = “from@email.address”;
    $email_message = “Email body”;

    $mime_boundary = “==Multipart_Boundary_x{$semi_rand}x”;
    $headers = ‘From: ‘.$email_from.”\r\n”.’Reply-To: ‘.$email_from.”\r\n”;
    $headers .= “MIME-Version: 1.0\n” . “Content-Type: multipart/mixed;\n” . ” boundary=\”{$mime_boundary}\””;
    $message = “This is a multi-part message in MIME format.\n\n” . “–{$mime_boundary}\n” . “Content-Type: text/plain; charset=\”iso-8859-1\”\n” . “Content-Transfer-Encoding: 7bit\n\n” . $email_message . “\n\n”;
    $message .= “–{$mime_boundary}\n”;

    $x = 0;
    foreach ($_FILES[“resume”][“name”] as $key => $file_name)
    {
    $file_location = $_FILES[“resume”][“tmp_name”][$key];

    $file = fopen($file_location, “rb”);
    $data = fread($file, filesize($file_location));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= “Content-Type: {\”application/octet-stream\”};\n” . ” name=\”$file_name\”\n” .
    “Content-Disposition: attachment;\n” . ” filename=\”$file_name\”\n” .
    “Content-Transfer-Encoding: base64\n\n” . $data . “\n\n”;
    if($x == count($_FILES[“resume”][“name”])) {
    $message .= “–{$mime_boundary}–\n”;
    } else {
    $message .= “–{$mime_boundary}\n”;
    }
    $x++;
    }
    @mail($email_to, $email_subject, $message, $headers);

  • Jeff

    Oh and I see WordPress substitutes double-dashes with an ndash adds smart quotes. See if this is better:


    $email_to = "destination@email.address";
    $email_subject = "Test Subject";
    $email_from = "from@email.address";
    $email_message = "Email body";

    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";
    $headers = 'From: '.$email_from."\r\n".'Reply-To: '.$email_from."\r\n";
    $headers .= "MIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\"";
    $message = "This is a multi-part message in MIME format.\n\n" . "--{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $email_message . "\n\n";
    $message .= "--{$mime_boundary}\n";

    $x = 0;
    foreach ($_FILES["resume"]["name"] as $key => $file_name)
    {
    $file_location = $_FILES["resume"]["tmp_name"][$key];

    $file = fopen($file_location, "rb");
    $data = fread($file, filesize($file_location));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$file_name\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$file_name\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    if($x == count($_FILES["resume"]["name"])) {
    $message .= "--{$mime_boundary}--\n";
    } else {
    $message .= "--{$mime_boundary}\n";
    }
    $x++;
    }
    @mail($email_to, $email_subject, $message, $headers);

  • Moses

    Finally solved the extra file mystery use this it works like a charm

    <?php

    // array with filenames to be sent as attachment
    $files = array("file_1.ext","file_2.ext","file_3.ext",……);

    // email fields: to, from, subject, and so on
    $to = "mail@mail.com";
    $from = "mail@mail.com";
    $subject ="My subject";
    $message = "My message";
    $headers = "From: $from";

    // boundary
    $semi_rand = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

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

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

    // preparing attachments
    for($x=0;$x<count($files);$x++){
    $message .= "–{$mime_boundary}\n";
    $file = fopen($files[$x],"rb");
    $data = fread($file,filesize($files[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    }

    // send

    $ok = @mail($to, $subject, $message, $headers);
    if ($ok) {
    echo "mail sent to $to!”;
    } else {
    echo “mail could not be sent!”;
    }

    ?>

  • Nice script …

  • When i receive the file or files I get a message on outlook 2003 saying the file is corrupted (if I send a .zip) OR if i send the file with a .doc extension on the end it opens in word but then says I need a converter… or sometimes it just spurts out a line or jibberish… my code is below. Advice would be greatly appreciated.

    <?php

    // array with filenames to be sent as attachment
    $files = array("file_1.zip");

    // email fields: to, from, subject, and so on
    $to = "jlane@xxxxxx.co.uk, jlane@xxxxxx.com";
    $EmailFrom = Trim(stripslashes($_POST['name3']));
    //$from = "e-Hub_Submit_Work";
    $subject = Trim(stripslashes($_POST['subject']));
    $message = Trim(stripslashes($_POST['message2']));
    $headers = "From: $EmailFrom";

    // boundary
    $semi_rand = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

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

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

    // preparing attachments
    for($x=0;$x<count($files);$x++){
    $file = fopen($files[$x],"rb");
    $data = fread($file,filesize($files[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    if ($x==count($files)-1){
    $message .= "–{$mime_boundary}–\n";
    } else
    {
    $message .= "–{$mime_boundary}\n";
    }
    }

    // send

    $ok = mail($to, $subject, $message, $headers);
    if ($ok) {
    echo "mail sent to $to!”;
    } else {
    echo “mail could not be sent!”;
    }

    ?>

  • Could you remove the previous postings email addresses – i forgot to take them off! thanks in advance.

  • joseph

    This works very well, but…. my attachments are EMPTY. wth? And why doesn’t the author comment or reply to questions?

  • nitin niraj

    awesome work man

  • Hi
    This is a nice script,
    I used above code, and its working fine…..

    Thanks a lot

  • Jack

    I get an email with an attachment but when I try to open it up I get an error message saying the file has been damaged and it won’t open.

    What can I do to fix this problem? This is the first time I’ve tried to use php so I know next to nothing about it :( Any help would be GREATLY appreciated!

  • Hassan

    jack

    Be sure you are giving exact path of files in files array?

  • Basil

    Thanks, great help.
    But if you would fix the code it would be even better.

    I also found the extra attachment, could have saved myself 20 minutes if I read the user complaints first.

    My fix was just trimming off the “\n” when the loop is done and add back “–\n”.
    $message = substr($message, 0, -1) . “–\n”;

    And I have to say I had to remove that for(), and use a foreach().
    $foreach($files as $file)
    {

    }
    seems cleaner to me. And I get rid of all those ugly $files[$x] and use $file.

  • Gertjan Vierling

    To fix the problem with the ATT00001..txt file I changed the script as below.
    Replace line 20-34 of the original script with:

    // multipart boundary
    $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” . $message . “\n\n”;

    // preparing attachments
    for($x=0;$x<count($files);$x++){
    $file = fopen($files[$x],"rb");
    $data = fread($file,filesize($files[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "–{$mime_boundary}\n" . "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    }

    // here's our closing mime boundary that indicates the last of the message
    $message.="–{$mime_boundary}–\n";

  • Gertjan Vierling

    …and change all the single ‘-‘ into a double ‘- -‘ (because of the WordPress problem of this forum).

  • Pingback: Email mit JPG-Anhang versenden - IP-Symcon Community Forum()

  • thanks man very much

  • Aah nice one but i found http://www.7tech.co.in/php/send-mail-with-or-without-attachment-by-using-php/ which have also good explaination

  • Niaz

    Hi,
    I found very good stuff in this blog and I have attached multiple documents and send email successfully to my gmail and hotmail account. Just I face one problem when I provided my official email address e.g niaz.aahmad@hbstech.co.uk then I not received email. anyone tell where what is problem? my official email is working & I am getting emails from other accounts.

  • Pingback: Enviar e-mail con adjunto/s | El rincón de Gu()

  • Yazan

    Dear All,

    I am very new to php and I am trying to get this script to work.

    When I run it using php command line I get “mail could not be sent!” directly.

    Can you please advise me through setting up php, i did not install any webserver or cgi, is it the reason?

    Regards

  • Zico Saheb Santra

    I want to send only one attachment but the code at the top did not worked properly .Emails are going and file name is going, not the content of that file. please give a script that will work……..

  • Pingback: Kindle – Unofficial Guardian Subscription - James' Repository()

  • Gratuz

    Thanks for this simple and amazing scripts – works perfectly!

  • This is nice sricpt, Thanks!

  • Hi everyone, the code above works perfectly for me it’s just that it almost took half an hour for the script to execute! Is there any way I can do to so that this code will execute a little bit faster?

    Thanks in advance!

  • Ajmel Karim

    Thanks a lot

  • Thanks a lot for short and concrete example!!!!
    Dzi?kuj? bardzo

  • khushboo

    Thanks alot :)

  • <?php

    if(isset($_POST['Submit'])){
    // array with filenames to be sent as attachment
    $files = array($_FILES['theFile']['tmp_name']);

    // email fields: to, from, subject, and so on
    $to = "toemail@gmail.com";
    $from = "fromemail@gmail.com";
    $subject ="My Subject";
    $message = "My Attachments";
    $headers = "From: $from";

    // boundary
    $semi_rand = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

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

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

    // preparing attachments
    for($x=0;$x<count($files);$x++){
    $file = fopen($files[$x],"rb");
    $filename = $_FILES['theFile']['name'];
    $data = fread($file,filesize($files[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$filename\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    $message .= "–{$mime_boundary}\n";
    }

    // send

    $ok = mail($to, $subject, $message, $headers,"-femail@excelattorneyservice.com");
    if ($ok) {
    echo "mail sent to $to!”;
    } else {
    echo “mail could not be sent!”;
    }

    }

    ?>

  • Panickev

    For people who want to sent multiple attachments and dont want the weird textfile.

    Just simply remove line 21
    and change line 22 in:
    $message = “–{$mime_boundary}\n”;

    Here is the function:

    function mail_attachment($files, $path, $mailto, $from_mail, $subject, $message)
    {
    // email fields: to, from, subject, and so on
    $to = $mailto;
    $from = $from_mail;
    $subject =$subject;
    $message = $message;
    $headers = “From: “.$from;

    // boundary
    $semi_rand = md5(time());
    $mime_boundary = “==Multipart_Boundary_x{$semi_rand}x”;

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

    // multipart boundary
    // $message = “This is a multi-part message in MIME format.\n\n” . “–{$mime_boundary}\n” . “Content-Type: text/plain; charset=\”iso-8859-1\”\n” . “Content-Transfer-Encoding: 7bit\n\n” . $message . “\n\n”;
    $message = “–{$mime_boundary}\n”;

    // preparing attachments
    for($i=0; $i < count($files); $i++)
    {
    $file = fopen($path.$files[$i],"rb");
    $data = fread($file,filesize($path.$files[$i]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "Content-Type: {\"application/octet-stream\"};\n"." name=\"".$files[$i]."\"\n" .
    "Content-Disposition: attachment;\n"." filename=\"".$files[$i]."\"\n" .
    "Content-Transfer-Encoding: base64\n\n".$data."\n\n";
    $message .= "–{$mime_boundary}\n";
    }
    // send
    if(mail($to, $subject, $message, $headers))
    echo "Send succesful";
    else
    echo "There was an error while sending the email";
    }

  • Panickev

    Change the code a bit. With my last one there is no Message in the email.

    Here is the function:

    function mail_attachment($files, $path, $mailto, $from_mail, $subject, $message)
    {
    // email fields: to, from, subject, and so on
    $to = $mailto;
    $from = $from_mail;
    $subject =$subject;
    $bericht = $message;
    $headers = “From: “.$from;

    // boundary
    $semi_rand = md5(time());
    $mime_boundary = “==Multipart_Boundary_x{$semi_rand}x”;

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

    // multipart boundary
    // $message = “This is a multi-part message in MIME format.\n\n” . “–{$mime_boundary}\n” . “Content-Type: text/plain; charset=\”iso-8859-1\”\n” . “Content-Transfer-Encoding: 7bit\n\n” . $message . “\n\n”;
    $message = “–{$mime_boundary}\n”;

    // preparing attachments
    for($i=0; $i < count($files); $i++)
    {
    $file = fopen($path.$files[$i],"rb");
    $data = fread($file,filesize($path.$files[$i]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "Content-Type: {\"application/octet-stream\"};\n"." name=\"".$files[$i]."\"\n" .
    "Content-Disposition: attachment;\n"." filename=\"".$files[$i]."\"\n" .
    "Content-Transfer-Encoding: base64\n\n".$data."\n\n";
    $message .= "–{$mime_boundary}\n";
    }
    // send

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

    if(mail($to, $subject, $message, $headers))
    echo "Send succesful";
    else
    echo "There was an error while sending the email";
    }

  • After more than 30 goes and trying every combination on here this was the only solution that worked for me where I could have multiple attachments with no funny text file, and both the attachments opened correctly.

    The only change is to the loop and it goes as follows:

    // preparing attachments
    for($x=0;$x<count($files);$x++){
    $file = fopen($files[$x],"rb");
    $data = fread($file,filesize($files[$x]));
    fclose($file);
    $data = chunk_split(base64_encode($data));
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$files[$x]\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    if($x == (count($files)-1)) {
    $message .= "–{$mime_boundary}–";
    } else {
    $message .= "–{$mime_boundary}\n";
    }
    }

  • The coding was changed after upload! it should be:

    –(2 dashes){$mime_boundary}–(2 dashes)”;
    } else {
    $message .= “–(2 dashes){$mime_boundary}\n”;
    }
    }

    in other words where its showing – next to {$mime_boundary} put – – (without the space)

  • @Jeff : Thanks! Your solution worked.

  • awesome script for sending mail attachments, working fine…

  • pavithra

    HI, can you please help me in rectifying the error in the below code:

    i am trying to make an contact form with attachments. for that, i am getting blank attachment(i.e attachment without any data). could you please help me by checking the code below:

    HTML FORM code:

    Email-To *:
    Email from *:
    Mobile * :
    Subject * :
    Message * : Select A File To Upload:

    PHP CODE:

    <?php

    if(isset($_POST['email'])) {

    $email_to = "abc.123@gmail.com" ;

    function died($error) {

    echo "We are very sorry, but there were error(s) found with the form you submitted. ";
    echo "These errors appear below.”;
    echo $error.””;
    echo “Please go back and fix these errors.”;
    die();
    }

    if(!isset($_POST[’email_to’]) ||
    !isset($_POST[’email_from’]) ||
    !isset($_POST[‘telephone’]) ||
    !isset($_POST[‘subject’]) ||
    !isset($_POST[‘comments’])) {
    died(‘We are sorry, but there appears to be a problem with the form you submitted.’);
    }

    $email_send = $_POST[’email_to’]; // required
    $email_from = $_POST[’email_from’]; // required
    $telephone = $_POST[‘telephone’]; // required
    $subject = $_POST[‘subject’]; // required
    $comments = $_POST[‘comments’]; // required

    //Get the uploaded file information
    $name_of_uploaded_file = basename($_FILES[‘uploaded_file’][‘name’]);
    //get the file extension of the file
    $type_of_uploaded_file = substr($name_of_uploaded_file, strrpos($name_of_uploaded_file, ‘.’) + 1);
    $size_of_uploaded_file = $_FILES[“uploaded_file”][“size”]/1024;//size in KBs

    $error_message = “”;
    $email_exp = ‘/^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/’;

    $mailids = explode(“,”, $email_send);
    $myBool = TRUE;
    if(sizeof($mailids)>5)
    {
    $error_message .= ‘The Email Addresses exceded ……’;
    }else
    {
    for ($i=0; $i<sizeof($mailids); $i++)
    {

    if(!preg_match($email_exp,$mailids[$i]))
    {
    $error_message .= 'The Email Address you entered does not appear to be valid.’;
    $myBool = false;
    break;
    }
    }

    }

    //Settings
    $max_allowed_file_size = 1024; // size in KB
    $allowed_extensions = array(“jpg”, “jpeg”, “gif”, “bmp”, “doc”, “docs”, “xls”, “xlsx”, “rar”, “zip”, “png”, “txt”, “ppt”, “pdf”, “psd”);
    //Validations
    if($size_of_uploaded_file > $max_allowed_file_size )
    {
    $errors .= “\n Size of file should be less than $max_allowed_file_size”;
    }
    //—— Validate the file extension —–
    $allowed_ext = false;
    for($i=0; $i<sizeof($allowed_extensions); $i++)
    {
    if(strcasecmp($allowed_extensions[$i],$type_of_uploaded_file) == 0)
    {
    $allowed_ext = true;
    }
    }
    if(!$allowed_ext)
    {
    $errors .= "\n The uploaded file is not supported file type. ".
    " Only the following file types are supported: ".implode(',',$allowed_extensions);
    }
    //copy the temp. uploaded file to uploads folder
    $path_of_uploaded_file = $upload_folder . $name_of_uploaded_file;
    $tmp_path = $_FILES["uploaded_file"]["tmp_name"];
    if(is_uploaded_file($path_of_uploaded_file))
    {
    if(!copy($tmp_path,$path_of_uploaded_file))
    {
    $errors .= '\n error while copying the uploaded file';
    }
    }

    $string_exp = '/^[0-9]+$/';
    if(!preg_match($string_exp,$telephone)) {
    $error_message .= 'The phone number you entered not appear valid. Please make sure that you entered valid mobile number.’;
    }
    $email_exp = ‘/^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/’;
    if(!preg_match($email_exp,$email_from)) {
    $error_message .= ‘The To-Email Address you entered does not appear to be valid.’;
    }
    if(strlen($comments) < 2) {
    $error_message .= 'The Comments you entered do not appear to be valid.’;
    }
    if(strlen($error_message) > 0) {
    died($error_message);
    }
    $email_message = ” \n\n”;

    function clean_string($string) {
    $bad = array(“content-type”,”bcc:”,”to:”,”cc:”,”href”);
    return str_replace($bad,””,$string);
    }

    $email_message .= ” “.clean_string($telephone).”\n”;
    $email_message .= ” “.clean_string($comments).”\n”;
    $email_subject = $subject;
    $email_to=$email_send;
    // create email headers
    $headers = ‘From: ‘.$email_from.”\r\n”.
    $headers = “\n MIME-Version: 1.0\n” .
    “content-Type: miltipart/mixed;\n” .
    ‘Reply-To: ‘.$email_from.”\r\n” .
    ‘X-Mailer: PHP/’ . phpversion();
    @mail($email_to, $email_subject, $email_message,$path_of_uploaded_file, $headers);
    ?>

    Thank you for contacting us. We will be in touch with you very soon.

  • Roelof Sybren van Ijken

    Thanks my fried. It works.

  • chary

    I am trying to send multiple attachment with an email. These files are stored in a folder named ‘uploads’. Here the mail is going with attachment of last file in the folder only. remaining files are not send as attachment. please give me solution.
    Code:
    $htmlbody = $body;
    $textmessage = “This is a plain text message”;

    //define the from \ reply to headers
    $headers = “From: charyatwork@gmail.com\r\nReply-To: charyatwork@gmail.com“;

    //create a unique boundary string to delimit different parts of the email (plain text, html, file attachment)
    $random_hash = md5(date(‘r’, time()));

    //add boundary string and mime type specification
    $headers.=”\r\nContent-Type: multipart/mixed; boundary=\”PHP-mixed-“.$random_hash.”\””;

    //define the body of the message.
    $message=”–PHP-mixed-$random_hash\r\n”
    .”Content-Type: multipart/alternative; boundary=\”PHP-alt-$random_hash\”\r\n\r\n”;
    $message.= “–PHP-alt-$random_hash\r\n”
    .”Content-Type: text/plain; charset=\”iso-8859-1\”\r\n”
    .”Content-Transfer-Encoding: 7bit\r\n\r\n”;

    //Insert the plain text message.
    $message .= strip_tags($textmessage);
    $message .= “\r\n\r\n–PHP-alt-$random_hash\r\n”
    .”Content-Type: text/html; charset=\”iso-8859-1\r\n”
    .”Content-Transfer-Encoding: 7bit\r\n\r\n”;

    //Insert the html message.
    $message.= $htmlbody;
    $message.=”\r\n\r\n–PHP-alt-$random_hash–\r\n\r\n”;

    //read the atachment file contents into a string,
    //encode it with MIME base64,
    //and split it into smaller chunks for sending
    $dir=”uploads”;
    $files2 = scandir($dir, 1);
    //echo “”.count($files2);
    for($x=0;$x<count($files2);$x++)
    {
    $file=$files2[$x];
    $attachment = chunk_split(base64_encode(file_get_contents("uploads/".$file)));

    //include attachment
    $message.= "–PHP-mixed-$random_hash\r\n"
    ."Content-Type: application/zip; name=\"$file\"\r\n"
    ."Content-Transfer-Encoding: base64\r\n"
    ."Content-Disposition: attachment\r\n\r\n";
    $message.= $attachment;
    $message.= "/r/n–PHP-mixed-$random_hash–";
    }
    //send the email

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

  • Pingback: Using PHP to send Email with multiple file attachments | Love Life, Live Code, Music Is The Best!()

  • Frustrated

    emanuele feronato, why don’t you respond to the comments?!

  • Frustrated

    Or did you just report the code from

    http://php.net/manual/en/function.mail.php

    and don’t actually understand it so you can’t help?

  • wlf

    I wasn’t sure whether to you use your script or this other one I found here http://asdlog.com/Create_form_to_send_email_with_attachment

    In the end I used your headers and the form from there! Thanks!

  • Chris

    After much frustration (that I never really worked out) I managed to get it to correctly produce 0, 1, 2 or more attachments. Couldn’t get the various if statements to work properly to get rid of the extra attachment, but moved the mime boundary to the beginning of the loop and got rid of the one before the loop. Also used a simplification John suggested to reduce the code size.

    Thought I’d share this for anyone who can’t get the above to work in their code either (mine was part of a form submit etc).

    // multipart boundary
    $message .= “This is a multi-part message in MIME format.\n\n” . “–{$mime_boundary}\n” . “Content-Type: text/plain; charset=\”iso-8859-1\”\n” . “Content-Transfer-Encoding: 7bit\n\n” . $message . “\n\n”;

    // preparing attachments
    for($x=0;$x<count($files);$x++){
    $message .= "–{$mime_boundary}\n";
    $data = chunk_split(base64_encode(file_get_contents("$files[$x]")));
    $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$filenames[$x]\"\n" .
    "Content-Disposition: attachment;\n" . " filename=\"$filenames[$x]\"\n" .
    "Content-Transfer-Encoding: base64\n\n" . $data . "\n\n";
    }

  • Chris

    OK – second line in prepare attachments should have a double minus in the “–{mime_boundary}\n” bit. Probably has appeared as a single minus again here.

  • Pingback: Using PHP to send Email with multiple file attachments | AdamFitch.com()

  • Nick

    Your script helped! Many thanks.

  • thanks for the nice code

  • Bob

    Worked fine as is for me, except remove the ……..s at the end of the array declaration.

    $files = array(“file_1.ext”,”file_2.ext”,”file_3.ext”,……);

    No problem getting an extra “ATT000??.txt” attachment.

  • Rogelio

    Gracias , gran aporte!!!!!!!

  • Dinesh

    I have used the code like this. I am getting the attachments, but they are blank. Please help me I am noob in php.

    <?php

    if(isset($_POST['Email_Address'])) {

    $files = array("Resume.docx", "Resume2.docx");

    $email_to = "abc@mydomain.com";
    $email_subject = "My Company – Career Enquiry";
    $thankyou = "http://www.mydomain.com/thanks.html&quot;;
    $email_sender = "admin@mydomain.com";

    // boundary
    $semi_rand = md5(time());
    $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

    function died($error) {
    echo "Sorry, but there were error(s) found with the form you submitted. ";
    echo "These errors appear below.”;
    echo $error.””;
    echo “Please go back and fix these errors.”;
    die();
    }

    $full_name = $_POST[‘Full_Name’]; // required
    $email_from = $_POST[‘Email_Address’]; // required
    $telephone = $_POST[‘Tel_No’]; //required
    $comments = $_POST[‘Description’]; // required

    $email_message = “Message details below.\r\n”;

    function clean_string($string) {
    $bad = array(“content-type”,”bcc:”,”to:”,”cc:”,”href”);
    return str_replace($bad,””,$string);
    }

    $email_message .= “Full Name: “.clean_string($full_name).”\r\n”;
    $email_message .= “Email: “.clean_string($email_from).”\r\n”;
    $email_message .= “Contact Number: “.clean_string($telephone).”\r\n”;
    $email_message .= “Message: “.clean_string($comments).”\r\n”;

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

    // preparing attachments
    for($x=0;$x
    location.replace(”)

  • Amit

    Can any one tell me how to attach file name in above code with path..
    because i want to attach the file fetching from folder….
    can some one post code for that dynamic doc file

  • Anitha

    hi..i am fresher…so i cant understand above coding.where i attach the file?.. .
    $files = array(“filename.blah”, “filename.blah”);this file when i attach

  • anitha

    file attachment or file upload same or not

  • kolpi

    works like a charm (:

  • Ranjeet Gholave

    Great work…!!
    Thanks

  • Camilo

    Don’t works for me, can put the form ! Thanks !

  • sg

    use this one

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

  • Dip

    Excellent code. It helps me greatly. Thanks a lot.

  • Basil
    on July 14, 2011 at 4:17 am

    … got it right. HIs solution is elegant and works.

    I use an array for my files (they are generated in memory, not loaded, but it should make no difference). Each $attachments element is an array like this: array(‘file_name’=>’myFileName.csv’, ‘type’=>’application/csv’, ‘content’=>$csvString)

    then I use Basil’s solution:

    foreach($attachments as $attachment) {
    $data = chunk_split(base64_encode($attachment[‘content’]));
    $message .= “Content-Type: {$attachment[‘type’]};\n”;
    $message .= ” name=\”{$attachment[‘file_name’]}\”\n”;
    $message .= “Content-Transfer-Encoding: base64\n\n”;
    $message .= $data . “\n\n”;
    $message .= “–{$mime_boundary}\n”;
    }
    $message = substr($message, 0, -1) . “–\n”;

  • Naved
  • $message .= “–{$mime_boundary}\n”;

    a very nice script dude! greetz!

  • Kris

    I am having trouble with the attachments.. I receive them but they dont openup.. Can anyone guide me??

  • irfan

    Try multiple attachment email with php, html5 and css3.
    techmynd.org/demos/html5-multiple-attachment-email/

  • Pingback: Anonymous()

  • Rameez

    I really appreciate your work thanks..

  • Jitendra

    it’s working !!! Thanks,,

  • Kasaija Ronald

    Thanks this site really helped

  • zain

    its a great work.thanks

  • Pingback: Php mail not working with more than one recipient | ?????()

  • reuben

    Thanks so much! Works great.

  • Danny Lewis

    ATT0000.txt is a symptom of Exchange being a jerk or a good guy, depending on how you look at it. That file contains the newline after the mime boundary (what was at the end of the email and Exchange thought you might like to have it).

    The way I fixed it, just before line 33 ($message .= “–{$mime_boundary}\n”;), I inserted an if that checks to see if this was the last iteration of the for loop, and if so, break and do not add the mime boundary:
    if (($i + 1) == count($files)) {
    break;
    }
    $message .= “–{$mime_boundary}\n”;

    Hope this helps!

  • I just cannot figure out how to: “Just fill $files array with the files to be sent.”

    This is my html code:

  • Thanks for the awesome Helpful….

  • sanam

    Hello, I had the same experience, especially with examples that didn’t work or corrupt attachments, until I found your code.