PHP – Send Attachment with PHP mail()

Update @ 2014-03-10: If the following piece of code doesn’t work, you could try the comment written by karmaprod.

Update @ 2014-01-17: You may need to change the PHP_EOL setting in Windows environment as suggested by Rene.

Update @ 2015-02-13: Replace all “/r/n” to PHP_EOL as suggested by Rene and Tomas for windows environment and sending image attachment.

By default, the PHP mail() does not support sending email with attachment. In order to send an attachment, u can either use the PEAR package or PHPMailer. But in reality, the hosting server may not provide these kinds of third party libraries.

A workaround for sending attachment using PHP mail() is to construct a MIME header which contains the attachment information. The following piece of codes should help.

<?php
/* Email Detials */
  $mail_to = "<receipient address>";
  $from_mail = "<sender address>";
  $from_name = "<sender name>";
  $reply_to = "<reply-to address>";
  $subject = "<email subject>";
  $message = "<email content>";

/* Attachment File */
  // Attachment location
  $file_name = "<attachment file name>";
  $path = "<relative path/absolute path which contains the attachment>";
  
  // Read the file content
  $file = $path.$file_name;
  $file_size = filesize($file);
  $handle = fopen($file, "r");
  $content = fread($handle, $file_size);
  fclose($handle);
  $content = chunk_split(base64_encode($content));
  
/* Set the email header */
  // Generate a boundary
  $boundary = md5(uniqid(time()));
  
  // Email header
  $header = "From: ".$from_name." <".$from_mail.">".PHP_EOL;
  $header .= "Reply-To: ".$reply_to.PHP_EOL;
  $header .= "MIME-Version: 1.0".PHP_EOL;
  
  // Multipart wraps the Email Content and Attachment
  $header .= "Content-Type: multipart/mixed; boundary=\"".$boundary."\"".PHP_EOL;
  $header .= "This is a multi-part message in MIME format.".PHP_EOL;
  $header .= "--".$boundary.PHP_EOL;
  
  // Email content
  // Content-type can be text/plain or text/html
  $header .= "Content-type:text/plain; charset=iso-8859-1".PHP_EOL;
  $header .= "Content-Transfer-Encoding: 7bit".PHP_EOL.PHP_EOL;
  $header .= "$message".PHP_EOL;
  $header .= "--".$boundary.PHP_EOL;
  
  // Attachment
  // Edit content type for different file extensions
  $header .= "Content-Type: application/xml; name=\"".$file_name."\"".PHP_EOL;
  $header .= "Content-Transfer-Encoding: base64".PHP_EOL;
  $header .= "Content-Disposition: attachment; filename=\"".$file_name."\"".PHP_EOL.PHP_EOL;
  $header .= $content.PHP_EOL;
  $header .= "--".$boundary."--";
  
  // Send email
  if (mail($mail_to, $subject, "", $header)) {
    echo "Sent";
  } else {
    echo "Error";
  }
?>

It should be able to deliver emails to Gmail and Hotmail without regarding as SPAM.

Done =)

68 thoughts on “PHP – Send Attachment with PHP mail()”

  1. Fantastic Article… I really searched a lot and also tried a lot of codes but they just were not working. I needed to send an image as an attachment with an email to the member of the website. Real good effort there!!!

    Like

  2. my wrapping makes a problem with this code it shows only the empty attachments file and no content in the body of the mail

    Like

  3. its not working with me, don’t know why?
    showing error.
    what to do?

    but when I use sendmail on terminal, it dispatches email and takes to spam

    also in php.ini the path to sendmail is already given correctly on my linux machine

    mail with attachment will be a good thing, but for now I want the simple mails to work in php without attachments and then I am sure mails without attachments will also go out.

    can you help me please

    Like

    1. Hi Molik,

      First of all, what error did you get? can you post it here?

      Second, if you find that the outgoing emails were treated as SPAM. most likely the domain is not in the email whitelist. Actually setup an email server is quite complicated and i dun have much experience on that. If you dun mind using gmail as a relay, i would suggest you read the following post.
      Postfix – Relay via Gmail

      I dun know if your server is using Sendmail/Postfix. In my experience, Postfix is more user friendly.

      Hope the above information could help.

      Kit

      Like

  4. I couldn’t have it working until I changed all those “$header” to “$message”. Here it is my working code:

    <?php
    // https://eureka.ykyuen.info/2010/02/16/php-send-attachmemt-with-php-mail/
    /* Email Detials */
    	$mail_to = "";
    	$from_mail = "";
    	$from_name = "";
    	$reply_to = "";
    	$subject = "";
    	$message = "";
    
    /* Attachment File */
    	// Attachment location
    	$file_name = "";
    	$path = "";
    	
    	// Read the file content
    	$file = $path.$file_name;
    	$file_size = filesize($file);
    	$handle = fopen($file, "r");
    	$content = fread($handle, $file_size);
    	fclose($handle);
    	$content = chunk_split(base64_encode($content));
    	
    /* Set the email header */
    	// Generate a boundary
    	$boundary = md5(uniqid(time()));
    	
    	// Email header
    	$header = "From: ".$from_name." \r\n";
    	$header .= "Reply-To: ".$reply_to."\r\n";
    	$header .= "MIME-Version: 1.0\r\n";
    	
    	// Multipart wraps the Email Content and Attachment
    	$header .= "Content-Type: multipart/mixed;\r\n";
    	$header .= " boundary=\"".$boundary."\"";
    
    	$message .= "This is a multi-part message in MIME format.\r\n\r\n";
    	$message .= "--".$boundary."\r\n";
    	
    	// Email content
    	// Content-type can be text/plain or text/html
    	$message .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n";
    	$message .= "Content-Transfer-Encoding: 7bit\r\n";
    	$message .= "\r\n";
    	$message .= "$message_body\r\n";
    	$message .= "--".$boundary."\r\n";
    	
    	// Attachment
    	// Edit content type for different file extensions
    	$message .= "Content-Type: application/xml;\r\n";
    	$message .= " name=\"".$file_name."\"\r\n";
    	$message .= "Content-Transfer-Encoding: base64\r\n";
    	$message .= "Content-Disposition: attachment;\r\n";
    	$message .= " filename=\"".$file_name."\"\r\n";
    	$message .= "\r\n".$content."\r\n";
    	$message .= "--".$boundary."--\r\n";
    	
    	// Send email
    	if (mail($mail_to, $subject, $message, $header)) {
    		echo "Sent";
    	} else {
    		echo "Error";
    	}
    ?>
    

    Like

  5. Will this work on a windows server running php?
    I am trying to use the above code and although I get sent displayed on the screen no email is received and I am not sure what to try?

    Like

  6. Thank you for this script, it’s helps me to find a error on mine.
    I also replace the \r\n by PHP_EOL and it’s working on my windows test enviroment and also on the linux server.

    Like

  7. I was wondering if you could tell me how to use this script, i want to send an image, for where ” ” they are can you fill the blanks in with examples, also I’m trying to upload images only can you help me ?

    Like

    1. just host the php file one a webserver which could run PHP and then fill in all details like <receipient address>

      Open this php file on the browser with http protocol and it should work.

      Like

    1. i hvn’t tried that before but i guess you can repeat the following part to send more attachments.

        // Attachment
        // Edit content type for different file extensions
        $header .= "Content-Type: application/xml; 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";
        $header .= "--".$boundary."--";
      

       

      And the following article should be able to help too.
      How to send HTML emails with multiple attachments in PHP

      Like

  8. sorry i forget to post my code here is my code

    /* Email Detials */
    $mail_to = "";
    $from_mail = "hemant.kumar@anaadihsoftech.in";
    $from_name = "Hemant";
    $reply_to = "";
    $subject = $name." want to customize his tshirt";
    $message = "Dear Admin below is customer deatils want to design his/her t-shirt,
      dlfkjasfldja;ldkjf;lakjsdflk;jakld;fjadfsdf
      From:- anurag
      Mobile:-7799833121
      Email id:-dfsj@jglk.com";
         
    /* Attachment File */
    // Attachment location
    $file_name = "image";
    $path = "";
     
    // Read the file content
    $file = $newname;
    $file_size = filesize($file);
    $handle = fopen($file, "r");
    $content = fread($handle, $file_size);
    fclose($handle);
    $content = chunk_split(base64_encode($content));
     
    /* Set the email header */
    // Generate a boundary
    $boundary = md5(uniqid(time()));
     
    // Email header
         
    
    
    $header = "MIME-Version: 1.0\r\n";
     
    // Multipart wraps the Email Content and Attachment
    $header .= "Content-Type: multipart/mixed; boundary=\"".$boundary."\"\r\n";
    $header .= "This is a multi-part message in MIME format.\r\n";
    $header .= "--".$boundary."\r\n";
     
    // Email content
    // Content-type can be text/plain or text/html
    $header .= "Content-type:text/plain; charset=iso-8859-1\r\n";
    $header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
    $header .= "$message\r\n";
    $header .= "--".$boundary."\r\n";
     
    //Email from and reply define 
    $header = "From: ".$from_name." \r\n";
    $header .= "Reply-To: ".$reply_to."\r\n"; 
     
     
    // Attachment
    // Edit content type for different file extensions
    $header .= "Content-Type: application/xml; 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";
    $header .= "--".$boundary."--";
     
    // Send email
    if (mail($mail_to, $subject,"", $header)) {
      echo "Sent";
    } else {
      echo "Error";
    }
    

    Liked by 1 person

      1. I check the spam folder but still i can’t find the email that I sent and I didn’t receive any error too.

        Like

      2. Disregard my first reply about “i didn’t receive any error” here i see in my error_log “unexpected T_STRING on line 18”

        Like

      3. Hi, I solve the first error and its working. But when I change the email receiver I have this new error fread(): supplied argument is not a valid stream resource on line 19
        [05-Nov-2014 19:31:41] PHP Warning: fclose(): supplied argument is not a valid stream resource on line 20

        Like

      4. Hi Ykyuen I have this errors now

        Warning: filesize() [function.filesize]: stat failed for /usr/local/apache/htdocs/Test/CashPickup.xml in /home7/homecre1/public_html/Test/Mail.php on line 20

        Warning: fopen(/usr/local/apache/htdocs/Test/CashPickup.xml) [function.fopen]: failed to open stream: No such file or directory in /home7/homecre1/public_html/Test/Mail.php on line 21

        Warning: fread(): supplied argument is not a valid stream resource in /home7/homecre1/public_html/Test/Mail.php on line 22

        Warning: fclose(): supplied argument is not a valid stream resource in /home7/homecre1/public_html/Test/Mail.php on line 23

        Notice: Undefined variable: message_body in /home7/homecre1/public_html/Test/Mail.php on line 47
        Sent

        Like

  9. This script have problem with sending image attachment (image is not readable). I think that problem is in new line and new row symbols (\n\r) wich break image source code. I found another script with PHP_EOL at end of line at it works without problem.

    Liked by 1 person

  10. this sends emails perfectly well, the only problem i got is that attachments sent to hotmail have 0.0 kb size, are not readable, but sent to gmail they are readable, any thoughts any one ?

    Like

  11. I realize this is an old thread. I am still receiving “error” when trying to send. I’m sure it is in the path and file name. The file name is correct, but maybe I am not getting the path correct? My code is listed below.

    /* Attachment File */
    // Attachment location
    $file_name = "doc.pdf";
    $path = "/HospiceLC/internal/aidenotes/";
    

    Thank you for any assistance.

    Like

      1. It doesn’t appear to be working, but I contacted the hosting provider. It turns out that they have the email features blocked because we host our own email in house. Thank you for the response. I appreciate it.

        Like

  12. Hello – I cannot seem to get this to work. I keep getting “error” when trying to send mail. Everything seems exactly correct except for the “filename” and “path” – can someone please provide an example? For file name, I have the name of the actual PDF file (doc.pdf) and the file name I’ve tried the full HTTP address to the document. Not working. Do I need trailing slashes or something in either? Or do I need to use the local path name? The PDF file I want to email is in the same location as the script. This is on a Linux machine, not Windows.

    Like

  13. when I am sending Email through locally on gmail than email send Properly with attachment But when i send through a linux server than message send but attachment not shown
    below O/P shown In my email

    Content-Type: application; name=”_sales_Report.pdf”

    Content-Transfer-Encoding: base64

    Content-Disposition: attachment

    JVBERi0xLjcKJeLjz9MKMTAgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCAxIDAgUiAvTGFz

    dE1vZGlmaWVkICj6VPgjU1tLO3U4eUvs4aAt5J2CIle4kykgL1Jlc291cmNlcyAyIDAgUiAvTWVk

    aWFCb3ggWzAuMDAwMDAwIDAuMDAwMDAwIDg0MS44OTAwMDAgNTk1LjI3NjAwMF0gL0Nyb3BCb3gg

    WzAuMDAwMDAwIDAuMDAwMDAwIDg0MS44OTAwMDAgNTk1LjI3NjAwMF0gL0JsZWVkQm94IFswLjAw

    Like

  14. If you attach a file from your Desktop or C Drive – like C:/Desktop/ – the file shows sent, but also shows 0 MB as an attachment. You have to attach a file from your ‘File Manager’ from your web host. Currently, I use FileZilla and set my path as the following – $path = “”; (or double quotes). It pulls the file from the general File Manager path. I tested it and it worked with Karmaprods code, but no message body. 😦 I will keep testing. Hope this helps.

    Like

  15. One last thing – Karmaprods code worked but was missing a body. To fix that issue, I changed the first $message variable to read $message_body in regards to his line $message .= “$message_body\r\n”;. Now it works fine except that your mail gets sent by the following suffix….user@boscustweb0101.eigbox.net. Who the heck is boscustweb0101.eigbox.net?!?! Dark forces are at work here….LOL.

    Like

  16. Thanks for this. I’m sending an xml file, and it sends the email fine with the xml attachment, but the xml file attachment it’s sending has a size of 0kB and it opens empty in notepad. Does anyone know why this might be? Is it something to do with the encoding?

    Like

  17. Hello,
    I ve tried your code and got the response as SENT but i never received the mail in my gmail inbox nor spam…I am testing it locally on my pc.

    Like

  18. Hi,
    Thank you for your code. I have been struggling to send a button uploaded file via email for days and your code is the closest if got to making it. I am at the point where I do receive an email which does show the attachment icon when it arrives to my inbox, however this icon disappears once I click and read the email. I have tried tweaking the boundaries and the encoding lines since I guess the problem might be there by looking at what I receive in the email body.
    Please below the code I’m using and email I am receiving. Any help will be greatly appreciated since I seem to have arrived to a dead end 😦

    Thanks!


    <?php
    if($_POST && isset($_FILES['uploads_name']))
    {
    $myemail = 'example@gmail.com';//

    EMAIL BODY RECEIVED:
    Content-Type: text/plain; charset=”iso-8859-1″
    Content-Transfer-Encoding: 7bit
    BODY
    Content-Type: multipart/mixed;
    name=”dni.pdf”
    Content-Transfer-Encoding: base64
    Content-Disposition: attachment;
    filename=”dni.pdf”

    JVBERi0xLjQNJeLjz9MNCjggMCBvYmoNPDwvTGluZWFyaXplZCAxL0wgNDM2MTY0L08gMTAvRSAy
    MTQ5MTEvTiAyL1QgNDM1ODg1L0ggWyA0MzYgMTQ2XT4+DWVuZG9iag0gICAgICAgICAgICAgICAg
    DQp4cmVmDQo4IDcNCjAwMDAwMDAwMTYgMDAwMDAgbg0KMDAwMDAwMDU4MiAwMDAwMCBuDQowMDAw
    MDAwNjQyIDAwMDAwIG4NCjAwMDAwMDA3NzEgMDAwMDAgbg0KMDAwMDAwMDgzNyAwMDAwMCBuDQow
    ……………………. encoded data continues……………

    Thank you!

    Like

    1. I want to also add that replacing all “/r/n” to PHP_EOL as suggested by Rene and Tomas has the same effect on the email received. Expect I only \get the BODY message on the email body.

      Thank you!

      Like

  19. Hi Dear,
    If I run the code i am getting error message means its execute else part
    Here is the code

      $mail_to = "";
      $from_mail = "";
      $from_name = "Career Detail";
      $reply_to = "";
      $subject = "Attachment mail";
      $message = "PHP Email with Attachment";
     
    /* Attachment File */
      // Attachment location
     
       
      // Read the file content
      $file = "/images/locations.jpg";
      $file_size = filesize($file);
      $handle = fopen($file, "r");
      $content = fread($handle, $file_size);
      fclose($handle);
      $content = chunk_split(base64_encode($content));
       
    /* Set the email header */
      // Generate a boundary
      $boundary = md5(uniqid(time()));
       
      // Email header
      $header = "From: ".$from_name." ".$from_mail." ".PHP_EOL;
      $header .= "Reply-To: ".$reply_to.PHP_EOL;
      $header .= "MIME-Version: 1.0".PHP_EOL;
       
      // Multipart wraps the Email Content and Attachment
      $header .= "Content-Type: multipart/mixed; boundary=\"".$boundary."\"".PHP_EOL;
      $header .= "This is a multi-part message in MIME format.".PHP_EOL;
      $header .= "--".$boundary.PHP_EOL;
       
      // Email content
      // Content-type can be text/plain or text/html
      $header .= "Content-type:text/plain; charset=iso-8859-1".PHP_EOL;
      $header .= "Content-Transfer-Encoding: 7bit".PHP_EOL.PHP_EOL;
      $header .= "$message".PHP_EOL;
      $header .= "--".$boundary.PHP_EOL;
       
      // Attachment
      // Edit content type for different file extensions
      $header .= "Content-Type: application/xml; name=\"".$file_name."\"".PHP_EOL;
      $header .= "Content-Transfer-Encoding: base64".PHP_EOL;
      $header .= "Content-Disposition: attachment; filename=\"".$file_name."\"".PHP_EOL.PHP_EOL;
      $header .= $content.PHP_EOL;
      $header .= "--".$boundary."--";
       
      // Send email
      if (mail($mail_to, $subject, "", $header)) {
        echo "Sent";
      } else {
        echo "Error";		
      }
    

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.