PHP mail with Multiple Attachments

In previous example we’ve learned how to send PHP mail with an attachment, and I have also created separate Ajax tutorial for the same. But some of you also want to send multiple attachments, so today I am going to refine the PHP code to show you how we can send multiple attachments with PHP mail.

Markup

First we need to create HTML multipart/form-data form with file input fields. Multiple PHP attachments You can turn those file fields into associative arrays using square brackets as shown below, or add attribute multiple=”multiple” in file input tag. this way no matter how many fields we add, we can simply iterate each field and access their variables later. Have a look at HTML form code below :
HTML
1234567891011121314151617181920212223242526
<form method="post" action="send_attachments.php" enctype="multipart/form-data">
<label>
<span>Your Name</span> 
	<input type="text" value="Jon Snow" name="s_name" />
</label>
<label>
<span>Your Email</span>
	<input type="email" value=""  name="s_email" />
</label>
<label>
<span>Message</span>
	<textarea name="s_message"></textarea>
</label>
<label>
<span>Attachments</span>
<!-- File input fields, you can add as many as required-->
	<input type="file" name="file[]" />
    <input type="file" name="file[]" />
    <input type="file" name="file[]" />
<!-- OR -->
<! -- <input type="file" name="file[]" multiple="multiple" /> -->
</label>
<label>
<input type="submit" value="Send" />
</label>
</form>
This is basic HTML form, it’s not pretty right now but you can always make it better using different CSS styles to it, and using JavaScript you can also add-remove fields dynamically.

PHP Mail

Once you are done with HTML part, you can examine the code below and copy it in a file and name it as send_attachments.php, which is the PHP file pointed in action parameter in HTML form above.
PHP
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
<?php
if($_POST &#038;&#038; isset($_FILES['file']))
{
	$recipient_email 	= "[email protected]"; //recepient
	$from_email 		= "info@your_domain.com"; //from email using site domain.
	$subject			= "Attachment email from your website!"; //email subject line
	
	$sender_name = filter_var($_POST["s_name"], FILTER_SANITIZE_STRING); //capture sender name
	$sender_email = filter_var($_POST["s_email"], FILTER_SANITIZE_STRING); //capture sender email
	$sender_message = filter_var($_POST["s_message"], FILTER_SANITIZE_STRING); //capture message
	$attachments = $_FILES['file'];
	
	//php validation
    if(strlen($sender_name)<4){
        die('Name is too short or empty');
    }
	if (!filter_var($sender_email, FILTER_VALIDATE_EMAIL)) {
	  die('Invalid email');
	}
    if(strlen($sender_message)<4){
        die('Too short message! Please enter something');
    }
	
	$file_count = count($attachments['name']); //count total files attached
	$boundary = md5("sanwebe.com"); 
			
	if($file_count > 0){ //if attachment exists
		//header
        $headers = "MIME-Version: 1.0\r\n"; 
        $headers .= "From:".$from_email."\r\n"; 
        $headers .= "Reply-To: ".$sender_email."" . "\r\n";
        $headers .= "Content-Type: multipart/mixed; boundary = $boundary\r\n\r\n"; 
        
        //message text
        $body = "--$boundary\r\n";
        $body .= "Content-Type: text/plain; charset=ISO-8859-1\r\n";
        $body .= "Content-Transfer-Encoding: base64\r\n\r\n"; 
        $body .= chunk_split(base64_encode($sender_message)); 

		//attachments
		for ($x = 0; $x < $file_count; $x++){		
			if(!empty($attachments['name'][$x])){
				
				if($attachments['error'][$x]>0) //exit script and output error if we encounter any
				{
					$mymsg = array( 
					1=>"The uploaded file exceeds the upload_max_filesize directive in php.ini", 
					2=>"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form", 
					3=>"The uploaded file was only partially uploaded", 
					4=>"No file was uploaded", 
					6=>"Missing a temporary folder" ); 
					die($mymsg[$attachments['error'][$x]]); 
				}
				
				//get file info
				$file_name = $attachments['name'][$x];
				$file_size = $attachments['size'][$x];
				$file_type = $attachments['type'][$x];
				
				//read file 
				$handle = fopen($attachments['tmp_name'][$x], "r");
				$content = fread($handle, $file_size);
				fclose($handle);
				$encoded_content = chunk_split(base64_encode($content)); //split into smaller chunks (RFC 2045)
				
				$body .= "--$boundary\r\n";
				$body .="Content-Type: $file_type; name=\"$file_name\"\r\n";
				$body .="Content-Disposition: attachment; filename=\"$file_name\"\r\n";
				$body .="Content-Transfer-Encoding: base64\r\n";
				$body .="X-Attachment-Id: ".rand(1000,99999)."\r\n\r\n"; 
				$body .= $encoded_content; 
			}
		}

	}else{ //send plain email otherwise
       $headers = "From:".$from_email."\r\n".
        "Reply-To: ".$sender_email. "\n" .
        "X-Mailer: PHP/" . phpversion();
        $body = $sender_message;
	}
		
	 $sentMail = @mail($recipient_email, $subject, $body, $headers);
	if($sentMail) //output success or failure messages
	{       
		die('Thank you for your email');
	}else{
		die('Could not send mail! Please check your PHP mail configuration.');  
	}
}
?>
The PHP code simply iterates though uploaded files, creates base64 encoded strings and combines them in single mail body encapsulated in boundaries. That’s it, the PHP script now should send multiple attachments. If you encounter any error during file upload, you may need to set the value of upload_max_filesize and post_max_size in your php.ini, because it determines the size of file you can upload.
Check-out Ajax Contact Form with an Attachment for Ajax tutorial.
Download
  • 32 Comments

    Add Comment
    • Terry
      Thank you for this excellent script - among all the many other scripts which I tried, and which claimed to be able to send multiple attachments, yours is the only one which is sufficiently robust to be adapted for use on a variety of contact forms - it works both with and without attachments - brilliant !
    • Sumit
      Is it possible with one input type to send multiple attachment to emails.
    • Parth Diyora
      Thanks For this Amazing help full code
    • Hi,
      12345678
      $body = "--$boundary\r\n";
      $body .= "Content-Type: text/plain; charset=ISO-8859-1\r\n";
      $body .= "Content-Transfer-Encoding: base64\r\n\r\n";
      $body .= chunk_split(base64_encode($firstname));
      $body .= chunk_split(base64_encode($lastname));
      $body .= chunk_split(base64_encode($email));
      $body .= chunk_split(base64_encode($phonenumber));
      $body .= chunk_split(base64_encode($visa));
      The 4th line which says $visa is outputting garbage value. If I add anyother field in place of visa it shows garbage value. I am following the same process you have mentioned above please respond I am looking for a solution from one mont
    • Joe
      Thanks for the script! But it has issues and for me it's not working propper, if you haven't selected any file (empty file input fields) -> content is sent base64 encoded ... If you have at least one file selected, it works fine! Any idea???
    • When send mail form with attacment, they arent images, only plain text:
      1234567891011121314151617181920
      Content-Type: image/jpeg; name="d2.jpg"
      Content-Disposition: attachment; filename="d2.jpg"
      Content-Transfer-Encoding: base64
      X-Attachment-Id: 8881
      /9j/4AAQSkZJRgABAgEASABIAAD/4Q6BRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUA
      AAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAcAAAAcgEyAAIAAAAUAAAAjodp
      AAQAAAABAAAApAAAANAACvyAAAAnEAAK/IAAACcQQWRvYmUgUGhvdG9zaG9wIENTMyBXaW5kb3dz
      ADIwMTc6MDY6MjkgMTE6NDk6NTkAAAAAA6ABAAMAAAAB//8AAKACAAQAAAABAAAETKADAAQAAAAB
      AAABygAAAAAAAAAGAQMAAwAAAAEABgAAARoABQAAAAEAAAEeARsABQAAAAEAAAEmASgAAwAAAAEA
      AgAAAgEABAAAAAEAAAEuAgIABAAAAAEAAA1LAAAAAAAAAEgAAAABAAAASAAAAAH/2P/gABBKRklG
      AAECAABIAEgAAP/tAAxBZG9iZV9DTQAC/+4ADkFkb2JlAGSAAAAAAf/bAIQADAgICAkIDAkJDBEL
      CgsRFQ8MDA8VGBMTFRMTGBEMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAENCwsN
      Dg0QDg4QFA4ODhQUDg4ODhQRDAwMDAwREQwMDAwMDBEMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwM
      DAwM/8AAEQgAQwCgAwEiAAIRAQMRAf/dAAQACv/EAT8AAAEFAQEBAQEBAAAAAAAAAAMAAQIEBQYH
      CAkKCwEAAQUBAQEBAQEAAAAAAAAAAQACAwQFBgcICQoLEAABBAEDAgQCBQcGCAUDDDMBAAIRAwQh
      EjEFQVFhEyJxgTIGFJGhsUIjJBVSwWIzNHKC0UMHJZJT8OHxY3M1FqKygyZEk1RkRcKjdDYX0lXi
      ZfKzhMPTdePzRieUpIW0lcTU5PSltcXV5fVWZnaGlqa2xtbm9jdHV2d3h5ent8fX5/cRAAICAQIE
      BAMEBQYHBwYFNQEAAhEDITESBEFRYXEiEwUygZEUobFCI8FS0fAzJGLhcoKSQ1MVY3M08SUGFqKy
      gwcmNcLSRJNUoxdkRVU2dGXi8rOEw9N14/NGlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vYnN0dX
      ....
      What am i doing wrong?
    • Kunal
      I used above contact form but is not wrking . when data data submit the given error .This page isn’t working rishtiindia.in is currently unable to handle this request. HTTP ERROR 500 please help me
    • Deepa
      Hello, very nice n helpful. But I want to add Name n other details in body like message, Please help...
    • Asaba
      something wrong with the file that uploaded to the form it cant fetch any temporary name Warning: fopen(): Filename cannot be empty in /storage/ssd1/366/3397366/public_html/sendemail.php on line 32 Warning: fread() expects parameter 1 to be resource, boolean given in /storage/ssd1/366/3397366/public_html/sendemail.php on line 33 Warning: fclose() expects parameter 1 to be resource, boolean given in /storage/ssd1/366/3397366/public_html/sendemail.php on line 34
    • TEX
      Hello, u have an error in
      12
      $body .="Content-Type: $file_type; name="$file_name"\r\n";
      $body .="Content-Disposition: attachment; filename="$file_name"\r\n";
      should it look like this?
      12
      $body .="Content-Type: $file_type; name=" . $file_name ."\r\n";
      $body .="Content-Disposition: attachment; filename=" . $file_name ."\r\n";