Search code examples
phpfileemailpostpostfile

Send php mail with file asynch


This is really making me crazy.

This is the issue, I have X form with some text inputs and one input file. In my script I do a previous validation and after, send it to x.php file who sent the mail and returns a response, after that the page changes depending that response. The issue is the x.php file is no receiving the file by this way.

HTML

<form action="/" method="post" enctype="multipart/form-data" id="hv_form" name="hv_form">
    <input type="text" name="name" placeholder="Nombre completo" />
    <input type="email" name="email" placeholder="E-mail" />
    <input type="text" name="phone" placeholder="Teléfono" />
    <input type="file" name="hv_file" id="hv_file" />
           <label for="hv_file"> 
                  <img src="images/addFile.svg" />
                  Elige un archivo...
           </label> 
    <button class="submit submit_file trans35" type="submit">Enviar archivo</button>                        
</form>

JQUERY

function send_file(trigger, dataOrigin) {
 // trigger > the button inside form to submit data
 // dataOrifin > the form

    $(trigger).on( 'click', function(e) {
        e.preventDefault();

        var error = false,
            $name = $(dataOrigin +" [class*='name']").val(),
            $email = $(dataOrigin +" [class*='email']").val(),
            $phone = $(dataOrigin +" [class*='phone']").val(),
            $file = $(dataOrigin +" [id='hv_file']").val();

  //Check empty inputs or errors
        if($name.length == 0){
            var error = true;
            $(dataOrigin +" [class*='name']").queue(function(){$(this).addClass('cont_error').dequeue();}).delay(err_wt).queue(function(){$(this).removeClass('cont_error').dequeue();});
        } else {
            $(dataOrigin +" [class*='name']").removeClass('cont_error');
        }
        //. . . etc


 //Send message and file
        if (error == true) {
            //do something if previous error
        } else if (error == false) {

            $.post("send_file.php", $(dataOrigin).serialize(),function(result){
                var r = JSON.parse(result);
                    console.log( r );

                if (r[0] == 1) {
                    // if php file responses "1" means sent
                    // do something...
                    console.log( "[HV] "+dataOrigin +": Mensaje enviado");

                } else if (r[0] == 0) {
                    // if php file responses "0" means NOT sent
                    // do something...
                    console.log( "[HV] "+ dataOrigin +": Mensaje NO enviado");
                }
             });

       }

PHP CODE

<?php

    $email_to = '[email protected]';   //email de la empresa
    $business = 'xxxxxx';    //nombre de la empresa

    $name       = $_POST['name'];
    $email_from = $_POST['email'];
    $phone      = $_POST['phone'];
    $file       = $_FILES['hv_file'];

//Correo
    $headers = "From: Postulacion web <$email_from>" . "\r\n";
    $headers .= "Reply-To: $name <$email_from>\r\n";

    $headers .= "MIME-Version: 1.0\r\n"; 
    $headers .= "Content-type: text/html; charset=UTF-8 " . "\r\n";
    $headers .= "X-Mailer: PHP/" . phpversion(). "\r\n";

    $subject    =  "$name ha enviado su curriculum"; //Asunto del mensaje    
    $message_full = "Hello world";

    $r;
    if(mail($email_to, $subject, $message_full, $headers)){
        $r = '1';
    } else {
        $r = '0';
    }   
    $toSend = [$r, $file ]; 

    echo json_encode($toSend); 
?>

But by this way $_FILES (in php file) is always empty, what i'm doing wrong?

And if I remove 'preventDefault' and submit the form naturally by clicking the button, the php file does receive the file!

Pleaaasee help me! I'm full desperate!


Solution

  • I changed up your ajax a bit, but I have a solution that works. In your code, I could not see how you were calling your send_file() function. So I got rid of it and used the button to fire the jquery.

    Make sure you have jQuery installed.

    You will see some changes in your html as well. Everything gets id's and I changed the button to type="button".

    Your going to have to rewrite some of your form validation.

    But none the less this work and it should give you a good example to work from. This will work every time you hit the button.

    HTML

    <form action="/" method="post" enctype="multipart/form-data" id="hv_form" name="hv_form">
        <input id="name" type="text" name="name" placeholder="Nombre completo" />
        <input id="email" type="email" name="email" placeholder="E-mail" />
        <input id="phone" type="text" name="phone" placeholder="Teléfono" />
        <input id="hv_file" type="file" name="hv_file" />
               <label for="hv_file">
    
                      Elige un archivo...
               </label>
        <button id="sendFile" class="submit submit_file trans35" type="button">Enviar archivo</button>
    </form>
    

    jQuery

    <script>
    
    $(document).ready(function(){
    
      $('#sendFile').on( 'click', function(e) {
    
          e.preventDefault();
    
          var myForm = new FormData();
    
          myForm.append('name',    $('#name').val());
          myForm.append('email',   $('#email').val());
          myForm.append('phone',   $('#phone').val());
          myForm.append('hv_file', $('#hv_file')[0].files[0]);
    
          $.ajax({
            url: 'send_file.php',
            type: 'POST',
            data: myForm,
            success: function (result) {
    
              var r = JSON.parse(result);
              console.log( r );
    
              if (r[0] == 1) {
              // if php file responses "1" means sent
              // do something...
              //console.log( "[HV] "+dataOrigin +": Mensaje enviado");
    
                } else if (r[0] == 0) {
                // if php file responses "0" means NOT sent
                // do something...
                //console.log( "[HV] "+ dataOrigin +": Mensaje NO enviado");
                }
    
            },
            cache: false,
            contentType: false,
            processData: false
    
          });
    
      });
    
    });
    
    
    </script>
    

    Your PHP looked ok to me. But you do need to make sure you are validating your post & file in your PHP script to make sure nothing unwanted makes it through.