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 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?php
if($_POST && isset($_FILES['file']))
{
    $recipient_email    = "recipient@yourmail.com"; //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

  1. this form not sent an email and name. please tell how to resolve this……

     Reply
  2. Hello, It doesnt sent inputed email and name, how can i fix it ?

     Reply
  3. That very good example, but it doesnt sent inputed email and name, how can i fix it ?

     Reply
  4. hello! how do i call this php code from ajax request?

     Reply
  5. will you please add loop in this code to make this work for multiple file attachment.


    ‘error’,
    ‘text’ => ‘Sorry Request must be Ajax POST’
    ));
    die($output); //exit script outputting json data
    }

    //Sanitize input data using PHP filter_var().
    $user_name = filter_var($_POST[“user_name”], FILTER_SANITIZE_STRING);
    $user_email = filter_var($_POST[“user_email”], FILTER_SANITIZE_EMAIL);
    $message = filter_var($_POST[“msg”], FILTER_SANITIZE_STRING);

    //additional php validation
    if(strlen($user_name)’error’, ‘text’ => ‘Name is too short or empty!’));
    die($output);
    }
    if(!filter_var($user_email, FILTER_VALIDATE_EMAIL)){ //email validation
    $output = json_encode(array(‘type’=>’error’, ‘text’ => ‘Please enter a valid email!’));
    die($output);
    }

    if(strlen($message)’error’, ‘text’ => ‘Too short message! Please enter something.’));
    die($output);
    }

    //email body
    $message_body = $message.”\n\n”.$user_name.”\nEmail : “.$user_email;

    ### Attachment Preparation ###
    $file_attached = false;
    if(isset($_FILES[‘file_attach’])) //check uploaded file
    {
    //get file details we need
    $file_tmp_name = $_FILES[‘file_attach’][‘tmp_name’];
    $file_name = $_FILES[‘file_attach’][‘name’];
    $file_size = $_FILES[‘file_attach’][‘size’];
    $file_type = $_FILES[‘file_attach’][‘type’];
    $file_error = $_FILES[‘file_attach’][‘error’];

    //exit script and output error if we encounter any
    if($file_error>0)
    {
    $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” );

    $output = json_encode(array(‘type’=>’error’, ‘text’ => $mymsg[$file_error]));
    die($output);
    }

    //read from the uploaded file & base64_encode content for the mail
    $handle = fopen($file_tmp_name, “r”);
    $content = fread($handle, $file_size);
    fclose($handle);
    $encoded_content = chunk_split(base64_encode($content));
    //now we know we have the file for attachment, set $file_attached to true
    $file_attached = true;
    }

    if($file_attached) //continue if we have the file
    {
    $boundary = md5(“sanwebe”);

    //header
    $headers = “MIME-Version: 1.0\r\n”;
    $headers .= “From:”.$from_email.”\r\n”;
    $headers .= “Reply-To: “.$user_email.”” . “\r\n”;
    $headers .= “Content-Type: multipart/mixed; boundary = $boundary\r\n\r\n”;

    //plain 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($message_body));

    //attachment
    $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{
    //proceed with PHP email.
    $headers = “From:”.$from_email.”\r\n”.
    ‘Reply-To: ‘.$user_email.” . “\n” .
    ‘X-Mailer: PHP/’ . phpversion();
    $body = $message_body;
    }

    $send_mail = mail($to_email, $subject, $body, $headers);

    if(!$send_mail)
    {
    //If mail couldn’t be sent output error. Check your PHP email configuration (if it ever happens)
    $output = json_encode(array(‘type’=>’error’, ‘text’ => ‘Could not send mail! Please check your PHP mail configuration.’));
    die($output);
    }else{
    $output = json_encode(array(‘type’=>’message’, ‘text’ => ‘Hi ‘.$user_name . ‘ your Resume has been submitted successfully!, we will catch you asap! Thank you.’));
    die($output);
    }
    }
    ?>

     Reply
  6. Saran, I have found the answer here: http://blog.teamtreehouse.com/uploading-files-ajax

    Attach files to FormData need by such way:

    // Loop through each of the selected files.
    for (var i = 0; i < files.length; i++) {
    var file = files[i];

    // Add the file to the request.
    formData.append('files[]', file, file.name);
    }

    and then it's possible to get it in php file through "$attachments = $_FILES['files'];"

    THANK YOU AGAIN FOR YUPR TOTORIALS! :)

     Reply
  7. Saran, thanks

    Everything works very well.

    But I can’t combine it with ajax form totorial.

    Why did you create this example without ajax – it’s some issues with multiple files? Or no, and it should work the same if we have single or multiple attachment?

     Reply
  8. I got an error “Missing a temporary folder”. What folder do I have to create?

     Reply
    • Open php.ini file look at the value for upload_tmp_dir and double check that the path exists. And that apache has write access to it.

  9. i would like to know how to add image in mysql using php with employee id,name of employee,salery,department and photo of employee.can you please help me with the code please?Thank you

     Reply
  10. $recepient_email = “recepient@yourmail.com”;
    $sentMail = @mail($recipient_email, $subject, $body, $headers);
    Change $recepient_email on $recipient_email

     Reply
  11. Great tutorial Saran.
    The article is really insightful thanks you for the share..

     Reply
  12. Can i ask something? How to make form email direct with PHP.. Thx

     Reply
  13. Thanks for the tutorial Saran.
    The code is perfect and works great!
    I was wondering how to implement reCaptcha. I have tried to add it in many different ways with no success so far. It’s probably something really simple that I am missing. If you have time to correspond, it would be very helpful. Thanks again.

     Reply
  14. Thanks for posting this, Saran! It was super helpful.

    I tried this on my website – from the error handling, it looks like the email and attachment were successfully sent, but I didn’t receive it in my inbox. Is there any additional validation needed to receive the inputted info and files in an inbox?

     Reply
    • Hi make sure you are able to send simple PHP mails, if not there could be problem with your mail server.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      <?php
      $to      = 'you@email.com';
      $subject = 'mail test';
      $message = 'testing email';
      $headers = 'From: info@yourdomain.com' . "\r\n" .
          'Reply-To: sender@email.com' . "\r\n" .
          'X-Mailer: PHP/' . phpversion();
      mail($to, $subject, $message, $headers);
      ?>
Message Type : Question Comment ?
  • Question : Can include code, jsFiddle, codePen etc using Markdown Syntax.
  • Comment : Short comments and questions.