Home » Php » php – Using Ajax in WordPress to send mail

php – Using Ajax in WordPress to send mail

Posted by: admin July 12, 2020 Leave a comment

Questions:

I’m trying to use Ajax to send an email through a web form I created, but I’m lost. I have no idea how Ajax functions in WordPress.

I firstly created an action

add_action( 'wp_ajax_siteWideMessage', 'wpse_sendmail' );

The function that’s supposed to retrieve the data and send the mail is:

function wpse_sendmail()
{
    $for = like_escape($_POST['forwhat']);
    $email = like_escape($_POST['email']);
    $headers = 'From: '.$email ."\r\n".'Reply-To: '.$email;
    $message = like_escape($_POST['message_message']);
    $respond = like_escape($_POST['message_email']);

    wp_mail( "[email protected]", "(OTN) Support: ".$support, $message, $headers); 
}

Finally, the js is like so:

$("#contact-send").click(function(){
    var forwhat = $("#contact-for").val();
    var name = $("#contact-name").val();
    var email = $("#contact-email").val();

    $.post( "<?php echo esc_js( site_url() ) ?>", { siteWideMessage:"null", forwhat: forwhat, name: name, email:email }, function(){
            console.log("success");
    });
});

I’m not too sure what I’m missing here. Can someone help me understand WordPress’s Ajax process?


UPDATE

I updated my code to this so far:

PHP

add_action( 'wp_ajax_siteWideMessage', 'wpse_sendmail' );
add_action( 'wp_ajax_nopriv_siteWideMessage', 'wpse_sendmail' );

function wpse_sendmail()
{
    $for = $_POST['forwhat'];
    $email = $_POST['email'];
    $headers = 'From: '.$email ."\r\n".'Reply-To: '.$email;
    $message = $_POST['message_message'];
    $respond = $_POST['message_email'];

    /*if(wp_mail( "[email protected]", "(OTN) Support: ".$for, $message, $headers))
    {
        echo "WOOHOO";
    }*/

    if($for)
    {
        //Just to see if there is any response.
        echo "Whoohoo";
    }

    die();
}

Js

$("#contact-send").click(function(){
    var forwhat = $("#contact-for").val();
    var name = $("#contact-name").val();
    var email = $("#contact-email").val();

    var data = { action:'siteWideMessage', forwhat:forwhat, name:name, email:email };
    $.post('<?php echo admin_url("admin-ajax.php"); ?>', data, function(response) {
        alert(response);
    });
});

WordPress is still not responding with my AJAX command. I’m using the inspect element, and I see no data being passed around.

How to&Answers:

At first you need to add two actions, one for the non-logged in user explicitly required to make it working, for example something like this (Basically in your functions.php file):

add_action( 'wp_ajax_siteWideMessage', 'wpse_sendmail' );
add_action( 'wp_ajax_nopriv_siteWideMessage', 'wpse_sendmail' );

Then, you need to make the request to the admin-ajax.php so in the jQuery function, you may use something like this:

$("#contact-send").click(function(e){

    e.preventDefault(); // if the clicked element is a link

    //...

    var data = { 'action':'siteWideMessage', 'more':'values' };

    $.post('<?php echo admin_url('admin-ajax.php'); ?>', data, function(response) {
        console.log(response);
    });

});

Make sure you put exit/die at the end of your handler in server side, for example:

function wpse_sendmail()
{
    // Process the post data...

    if(mail(...)) {
        echo 'success';
    }
    else {
        echo 'failed';
    }

    die();
}

In your success callback, the response variable will get the response sent from the server side, i.e. success/failed. There are better ways to do this (Using wp_localize_script etc). Read this detailed article. Also, if you want to return a json response then you may use $.json('url', data, func).

If you are confused then let me tell you that, you should make the request to admin-ajax.php and pass the action with the request and in this case it is siteWideMessage, so WordPress will call the handler that’s registered using add_action hook and in your case it’s wpse_sendmail.Eid Mubarak 🙂

Answer:

I had to do something slightly differently to get this to work.

First I added a hidden input on my template page and gave it the value of the ajax url like this:

<input type="hidden" id="ajax_url" value="<?php echo admin_url('admin-ajax.php'); ?>"/>

Then I had this in my functions.php

add_action( 'wp_ajax_siteWideMessage', 'wpse_sendmail' );
add_action( 'wp_ajax_nopriv_siteWideMessage', 'wpse_sendmail' );

function wpse_sendmail() {
  echo "hewwo world";

  die();
}

And my js in a seperate js file as such:

$("#submit-form").click(function(e){

  e.preventDefault(); // if the clicked element is a link

  $.post($("#ajax_url").val(), {
      action: 'siteWideMessage',
      // and the rest
  }, function(response) {
      // handle a successful response
      console.log(response)
  });

});

This works for me.

Answer:

Looking at the documentation for wp_ajax_(action), it looks like you simply need to set the action parameter to “siteWideMessage”. For example…

$.post(<?= json_encode(admin_url('admin-ajax.php')) ?>, {
    action: 'siteWideMessage',
    // and the rest
}, function(response) {
    // handle a successful response
});

Answer:

You can do this the wordpress way, or you can do this the easy way. I would make a plugin to hold AJAX-handling code.

<?php
/*
Plugin Name: AJAX Receiver
*/


add_action('admin_menu', 'ajax_receiver_menu');
function ajax_receiver_menu() {
    $parent_slug = null; // Child of null, so this menu item has no link to it in the dashboard.
    $menu_title  = "AJAX Receiver menu"; // This menu title will not be visible.
    $page_title  = "AJAX_Receiver"; // No one will visit this page.
    $menu_slug   = 'ajax_receiver'; // This is the last part of the URL you post to.
    $callback    = 'ajax_receiver_menu_content';
    add_submenu_page($parent_slug, $page_title, $menu_title, $capability, $menu_slug, $callback);
}



function ajax_receiver_menu_content() {
    // check request variables, do other logic.
    echo "This is the response to your AJAX request.";
}

Then, you can send a normal post request.

$.post( "/wp-admin/admin.php?page=ajax_receiver", { siteWideMessage:"null", forwhat: forwhat, name: name, email:email }, function(data){
        console.log(data); // You should see "This is the response to your AJAX request." in your console.
});

This is definitely not how you’re “supposed” to do it, but I’ve found this to be much easier to work with. The critical part is that the submenu doesn’t know if it’s echoing “This is the response to your AJAX request” in response to an AJAX request, or a normal page request. In fact, you could point your browser to "/wp-admin/admin.php?page=ajax_receiver" and you would just see “This is the response to your AJAX request” in unstyled text at the top of your screen.