Ajax Contact Form with an Attachment (jQuery & PHP)

    Rating: ★★★★☆
    View: 1318
    Download: 205
    Từ khóa:

    Take a look at the picture below, this is how our Ajax contact form is going to appear on the browser.

    Mark Up

    In order to send file as an attachment, first we must allow users to upload file using contact form. Let’s add file input field called “file_attach” to our markup along with other inputs. Notice we have 

     tag missing from the code? don’t worry we don’t need typical HTML form setting here, we can just collect fields value using jQuery .val() and files.

    Please Contact Us

    jQuery and Ajax

    Let’s write some jQuery code for our contact form. The code below is similar to Simple Ajax Contact form, the difference is $.ajax(), we will be using jQuery$.ajax() instead of $.post(), simply because it has more options, and allows us to have more control while uploading file to the server.

    $.ajax({
        url: 'contact_me.php',
        data: m_data,
        contentType: false,
        processData: false,
        type: 'POST',
        dataType:'json',
        success: function(data){
            //do stuff
        }
    });

    For example, the default jQuery contentType is set to application/x-www-form-urlencoded; charset=UTF-8, which means all characters will be encoded before sending to server, but it doesn’t work with file uploads. Hence, we need to turn this encoding off, so that data will be sent as multipart/form-data. Another option to turn off here is the processData, because we don’t want jQuery trying to transform file data into a huge query string, we want raw data to be sent to server.

    But before sending data to the server using XMLHttpRequest, we need to build aFormData by calling append() method. It transmits data in the same format as form’s submit() method would, as if the form encoding type were set to “multipart/form-data”.

    //data to be sent to server         
    var post_data = new FormData();    
    post_data.append( 'user_name', 'Name' );
    post_data.append( 'user_email', 'somemail@somedomain.com' );
    post_data.append( 'country_code', '00' );
    post_data.append( 'phone_number', '000000000');
    post_data.append( 'msg', 'Some text');
    post_data.append( 'file_attach', Attached File );

    Now let’s combine everything, and here’s the jQuery code the executes when user clicks submit button. As you can see there’s also simple validation code taken from previous example, which will just turn field border into red in case of empty fields.

        $("#submit_btn").click(function() {  
            var proceed = true;
            //simple validation at client's end
            //loop through each field and we simply change border color to red for invalid fields       
            $("#contact_form input[required=true], #contact_form textarea[required=true]").each(function(){
                $(this).css('border-color',''); 
                if(!$.trim($(this).val())){ //if this field is empty 
                    $(this).css('border-color','red'); //change border color to red   
                    proceed = false; //set do not proceed flag
                }
                //check invalid email
                var email_reg = /^([w-.]+@([w-]+.)+[w-]{2,4})?$/; 
                if($(this).attr("type")=="email" && !email_reg.test($.trim($(this).val()))){
                    $(this).css('border-color','red'); //change border color to red   
                    proceed = false; //set do not proceed flag              
                }   
            });
           
            if(proceed) //everything looks good! proceed...
            {
               //data to be sent to server         
                var m_data = new FormData();    
                m_data.append( 'user_name', $('input[name=name]').val());
                m_data.append( 'user_email', $('input[name=email]').val());
                m_data.append( 'country_code', $('input[name=phone1]').val());
                m_data.append( 'phone_number', $('input[name=phone2]').val());
                m_data.append( 'subject', $('select[name=subject]').val());
                m_data.append( 'msg', $('textarea[name=message]').val());
                m_data.append( 'file_attach', $('input[name=file_attach]')[0].files[0]);
                 
                //instead of $.post() we are using $.ajax()
                //that's because $.ajax() has more options and flexibly.
                $.ajax({
                  url: 'contact_me.php',
                  data: m_data,
                  processData: false,
                  contentType: false,
                  type: 'POST',
                  dataType:'json',
                  success: function(response){
                     //load json data from server and output message     
                    if(response.type == 'error'){ //load json data from server and output message     
                        output = '
    '+response.text+'
    '; }else{ output = '
    '+response.text+'
    '; } $("#contact_form #contact_results").hide().html(output).slideDown(); } }); } }); //reset previously set border colors and hide all message on .keyup() $("#contact_form input[required=true], #contact_form textarea[required=true]").keyup(function() { $(this).css('border-color',''); $("#result").slideUp(); }); });

    Once the form data is sent to server successfully, the server should return JSON data, which we will grab and output message within the #result div element.

    PHP Email

    In our PHP page which is contact_me.php, the most tricky part could be the Mail header, because while writing this tutorial I realized that most mail header examples (with attachment) just don’t work with most client. So I looked inside a working Gmail message source and borrowed it’s mail header for this tutorial. Here’s what I came up with.

    
    
    

    Some email clients seem to like double linebreaks between headers as shown above, otherwise the mail will appear blank and only way to view message is using view source. Also note that PHP mail tested on Windows ignored more than one linebreaks “ “, and inserting empty spaces do not work.

    So here’s complete code of contact_me.php, we will do simple server-side validation and play with PHP $_FILES (HTTP File Upload variable) before attaching file to mail header. Since attachment may not be mandatory in most cases, we will just switch to plain email header if we do not find $_FILES['file_attach'] variable.

    '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);
        $country_code   = filter_var($_POST["country_code"], FILTER_SANITIZE_NUMBER_INT);
        $phone_number   = filter_var($_POST["phone_number"], FILTER_SANITIZE_NUMBER_INT);
        $subject        = filter_var($_POST["subject"], FILTER_SANITIZE_STRING);
        $message        = filter_var($_POST["msg"], FILTER_SANITIZE_STRING);
       
        //additional php validation
        if(strlen($user_name)<4){ // If length is less than 4 it will output JSON error.
            $output = json_encode(array('type'=>'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(!filter_var($country_code, FILTER_VALIDATE_INT)){ //check for valid numbers in country code field
            $output = json_encode(array('type'=>'error', 'text' => 'Enter only digits in country code'));
            die($output);
        }
        if(!filter_var($phone_number, FILTER_SANITIZE_NUMBER_FLOAT)){ //check for valid numbers in phone number field
            $output = json_encode(array('type'=>'error', 'text' => 'Enter only digits in phone number'));
            die($output);
        }
        if(strlen($subject)<3){ //check emtpy subject
            $output = json_encode(array('type'=>'error', 'text' => 'Subject is required'));
            die($output);
        }
        if(strlen($message)<3){ //check emtpy message
            $output = json_encode(array('type'=>'error', 'text' => 'Too short message! Please enter something.'));
            die($output);
        }
       
        //email body
        $message_body = $message."
    
    ".$user_name."
    Email : ".$user_email."
    Phone Number : (".$country_code.") ". $phone_number ;
    
        ### 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
        {
            # Mail headers should work with most clients
            $headers = "MIME-Version: 1.0
    ";
            $headers = "X-Mailer: PHP/" . phpversion()."
    ";
            $headers .= "From: ".$from_email."
    ";
            $headers .= "Subject: ".$subject."
    ";
            $headers .= "Reply-To: ".$user_email."" . "
    ";
            $headers .= "Content-Type: multipart/mixed; boundary=".md5('boundary1')."
    
    ";
            
            $headers .= "--".md5('boundary1')."
    ";
            $headers .= "Content-Type: multipart/alternative;  boundary=".md5('boundary2')."
    
    ";
            
            $headers .= "--".md5('boundary2')."
    ";
            $headers .= "Content-Type: text/plain; charset=utf-8
    
    ";
            $headers .= $message_body."
    
    ";
            
            $headers .= "--".md5('boundary2')."--
    ";
            $headers .= "--".md5('boundary1')."
    ";
            $headers .= "Content-Type:  ".$file_type."; ";
            $headers .= "name="".$file_name.""
    ";
            $headers .= "Content-Transfer-Encoding:base64
    ";
            $headers .= "Content-Disposition:attachment; ";
            $headers .= "filename="".$file_name.""
    ";
            $headers .= "X-Attachment-Id:".rand(1000,9000)."
    
    ";
            $headers .= $encoded_content."
    ";
            $headers .= "--".md5('boundary1')."--";
        }else{
            //proceed with PHP email.
            $headers = 'From: '.$user_name.'' . "
    " .
            'Reply-To: '.$user_email.'' . "
    " .
            'X-Mailer: PHP/' . phpversion();
        }
       
        $send_mail = mail($to_email, $subject, $message_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 .' Thank you for your email'));
            die($output);
        }
    }

    That’s it, please remember some old unsupported browsers such as IE 8 may require some tweaking with jQuery code to work properly. You can just download the sample file and start testing out the script, but sorry I can not show you demo because it involves file uploading and sending email, you can try out the other demo here which works exactly same but without file uploading feature. Good luck!

    loading Đang tải...

    template được ưa chuộng