最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - ajax contact form not submit message

programmeradmin2浏览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');

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');
Share Improve this question asked Mar 16, 2020 at 11:15 sialfasialfa 32910 silver badges29 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 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/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.

发布评论

评论列表(0)

  1. 暂无评论