0

I'm havingo some trouble with a contact form I'm working on. I'm using ajax to submit it and I've noticed that from localhost and from the production server, the test messages I've sent will not be delivered. I'm not sure if it's a network delay or if this is caused because I'm using wordpress nonces.

Here is the code, I'm verifying the nonce like a normal post request without ajax, no error is logged but no message will be sent. Please help me.

HTML:

      <form method="POST" action="<?php echo esc_url(admin_url('admin-ajax.php')); ?>" id="message-form">
        <div class="form-row mb-3">
          <div class="col-sm-12 col-md-6 col-lg-6">
            <input type="text" class="form-control" id="" name="fname" placeholder="<?php _e('Nome'); ?>" required />
          </div>
          <div class="col-sm-12 col-md-6 col-lg-6">
            <input type="text" class="form-control" id="" name="lname" placeholder="<?php _e('Cognome'); ?>" required />
          </div>
          <div class="col-sm-12 col-md-6 col-lg-6">
            <input type="text" class="form-control" id="" name="phone" placeholder="<?php _e('Numero'); ?>" required />
          </div>
          <div class="col-sm-12 col-md-6 col-lg-6">
            <input type="email" class="form-control" id="" name="email" placeholder="<?php _e('Email'); ?>" required />
          </div>
          <div class="col-sm-12 col-md-12 col-lg-12">
            <input type="text" class="form-control" id="" name="subject" placeholder="<?php _e('Oggetto'); ?>" required />
          </div>
          <div class="col-sm-12 col-md-12 col-lg-12">
            <textarea class="form-control" name="message" placeholder="<?php _e('Messaggio'); ?>" required></textarea>
          </div>
        </div>
        <input type="hidden" name="action" value="send_message">
        <?php wp_nonce_field('send_message', 'message_hash'); ?>
        <a href="#" class="section-link hide" id="submit-form"><?php _e('Invia'); ?></a>
      </form>

JS:

  $('#submit-form').on('click', function(e){
    e.preventDefault();
    var data = $('#message-form').serialize();
    $.ajax({
      type: 'POST',
      url: wpcf.ajaxurl,
      data: data,
      success: function(response){
        $('#message-notice').css({'display':'block'});
        $('#message-form')[0].reset();
        setTimeout(function(){
          $('#message-notice').css({'display':'none'});
        }, 3000);
        console.log('Done!');
      }
    });
  });

PHP:

  /**
   * Form contatti front-end
   */
   function submit_contact_form()
   {
     if( !isset($_POST['message_hash']) || !wp_verify_nonce( $_POST['message_hash'], 'submit_message' ) ){
       echo 'Errore';
       exit;
     }
     // Customer contacts and message
     $email = sanitize_email($_POST['email']);
     $fname = sanitize_text_field($_POST['fname']);
     $lname = sanitize_text_field($_POST['lname']);
     $phone = sanitize_text_field($_POST['phone']);
     $subject = sanitize_text_field($_POST['subject']);
     $message = "Hai ricevuto un nuovo messaggio da: $fname $lname \n";
     $message .= "Puoi contattare l'utente utilizzando il numero:  $phone \n";
     $message .= "Testo del messaggio: \n";
     $message .= sanitize_textarea_field($_POST['message']);
     // send ticket
     $to = '[email protected]';
     $headers[] = "From: $fname $lname <$email>";
     wp_mail( $to, $subject, $message, $headers );
   }
   add_action( 'wp_ajax_send_message', 'submit_contact_form' );
   add_action( 'wp_ajax_nopriv_send_message', 'submit_contact_form' );

NB: I've localized the script in function files in this way, I'm not sure if this can be a problem, but I have already localized the ajax url for a dashboard widget and it will not work but on other website it's working well:

  function _res(){
    wp_enqueue_style('style', get_template_directory_uri().'/style.min.css');
    wp_register_script('main', get_template_directory_uri().'/assets/js/main.js', array('jquery'), null );
    $localize = array(
       'ajaxurl' => admin_url('admin-ajax.php'),
    );
    wp_localize_script('main', 'wpcf', $localize);
    wp_enqueue_script('main');
  }
  add_action('wp_enqueue_scripts', '_res');

1 Answer 1

0

About sending emails:

  • wp_mail by default utilizes default PHP's mailing setting, and PHP by default uses sendmail service so if you don't have one functioning on localhost you'll not be able to sendemails, you can use something like MailHog - to capture send emails for you on localhost and you'll actually will be able to see those messages - it's really good option for debugging.

  • on live sites host companies often just disable sendmail because they don't want their IP addresses get blacklisted because of probably spam sent from their client's hosted sites. So what you can do is you can install https://wordpress.org/plugins/wp-mail-smtp/ plugin and use your own let's say gmail account to send emails through, for testing it will work well. But for production usage it's still better to use some mail sending services like MailGun\SendGrid etc. While these services are paid they take care for you of issues for mass mailing sends.

And let's dig into how you can improve your code so it will help you to diagnose what's going on.

First if you make an ajax handler it's good to leverage sending data back to js, via wp_send_json_success() and wp_send_json_error() functions so your $.ajax will go to .done() only if you've really returned successful response, with HTTP code 200, and it will go to .fail() if your php code returned an error.

Let's see how our ajax handler may look like.

/**
 * Form contatti front-end
 */
function submit_contact_form() {
    if ( ! isset( $_POST['message_hash'] ) || ! wp_verify_nonce( $_POST['message_hash'], 'submit_message' ) ) {
        wp_send_json_error( array( 'error' => 'wrong_nonce' ) );
        exit;
    }
    // Customer contacts and message
    $email    = sanitize_email( $_POST['email'] );
    $fname    = sanitize_text_field( $_POST['fname'] );
    $lname    = sanitize_text_field( $_POST['lname'] );
    $phone    = sanitize_text_field( $_POST['phone'] );
    $subject  = sanitize_text_field( $_POST['subject'] );
    $message  = "Hai ricevuto un nuovo messaggio da: $fname $lname \n";
    $message .= "Puoi contattare l'utente utilizzando il numero:  $phone \n";
    $message .= "Testo del messaggio: \n";
    $message .= sanitize_textarea_field( $_POST['message'] );
    // send ticket
    $to        = '[email protected]';
    $headers[] = "From: $fname $lname <$email>";
    $mail_result = wp_mail( $to, $subject, $message, $headers );
    if( $mail_result ) {
        wp_send_json_success(['message'=>'mail_sent']);
    }else {
        wp_send_json_error(['error'=>'email_sending_error']);
    }
}
add_action( 'wp_ajax_send_message', 'submit_contact_form' );
add_action( 'wp_ajax_nopriv_send_message', 'submit_contact_form' );

And JS code which will handle it gracefully, to not blindly believe that if data was sent they were processed.

$('#submit-form').on('click', function(e){
    e.preventDefault();
    var data = $('#message-form').serialize();
    $.ajax({
        type: 'POST',
        url: wpcf.ajaxurl,
        data: data,
    }).done(function handleAjaxSuccess(response){
        console.log('success', response);
        $('#message-notice').css({'display':'block'});
        $('#message-form')[0].reset();
        setTimeout(function(){
            $('#message-notice').css({'display':'none'});
        }, 3000);
        console.log('Done!');
    }).fail(function handleAjaxError(jqXhr,errorText){
        console.warn('Error'); // just for you to see what's going on, here you can also display some error message to user.
        console.warn(errorText);
        console.warn(jqXhr);
    });
});

I've used named js functions so in case of error you'll get better understanding where it has happened rather then relying on js anonymous functions.

And one small edit for localize script: It's always better to first enqueue script then localize it.

wp_enqueue_script('main');
wp_localize_script('main', 'wpcf', $localize);

You can also simplify it to:

function _res() {
    wp_enqueue_style( 'my-plugin-style', get_template_directory_uri() . '/style.min.css' );
    wp_enqueue_script( 'my-plugin-main', get_template_directory_uri() . '/assets/js/main.js', array( 'jquery' ), null, true );
    wp_localize_script(
        'my-plugin-main',
        'wpcf',
        array(
            'ajaxurl' => admin_url( 'admin-ajax.php' ),
        )
    );
}
add_action( 'wp_enqueue_scripts', '_res' );

Also don't forget to set unique handle names for css and js your are linking, because main is something really broad and you can override either some other plugin's js\css code linkage or wp core's. And it's definitely not the thing we might want to do.

After making those changes you'll be able to diagnose what's going on in browser's console seeing messages returned to you by php.

6
  • On localhost the php mail function works well, I'm able to recieve the wordpress error emails that the CMS will send if a problem occurs. I'm having this issue only for this project, but I think that this is because there's some network delay ? no error on console or php error are displayed
    – sialfa
    Commented Mar 16, 2020 at 12:15
  • @sialfa Have you tried updating js \ php code to one i've provided?
    – Mikhail
    Commented Mar 16, 2020 at 12:58
  • @sialfa Also check spam folder of your destination mailbox as it may just get into spam.
    – Mikhail
    Commented Mar 16, 2020 at 12:58
  • I've tested the email sending using a plugin and the email is sent correctly. I'm not sure where the problem is inside the code.
    – sialfa
    Commented Mar 17, 2020 at 11:02
  • I've commented the nonce check and the form is now submitting the emails. I don't think that there are errors in the code relative to this part. Maybe there is another way to check the nonce when the request is made using ajax? I'm on netsons on the production host, but this problem isn't affecting aruba.
    – sialfa
    Commented Mar 17, 2020 at 11:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.