Programming a custom WordPress plugin for sending emails: Part 1

Programming a custom WordPress plugin for sending emails is a great idea for many reasons. Firstly,¬† sending mails is a vital feature of every modern WordPress website, especially in contact forms. Secondly, its a great way to increase your WordPress skills and to get familiar with the WP REST-API. Thirdly, the existing plugins like Contact Form 7 don’t give you a lot of freedom in their free version and are pretty bulky, which negatively affects the speed of your website. You don’t have this problem with a custom plugin.

Therefore, in this two part series I show you how to create a WordPress plugin from scratch with which you can use AJAX to send emails. You can find part two here. I will use PHP and Javascript for this. Here’s how it’s going to work:

  1. Create a new plugin directory and activate it in the WP admin Dashboard (Part 1)
  2. Use that plugin to register a new endpoint in the WP REST-API (Part 1)
  3. Create a function that sends a mail whenever the endpoint is hit (Part 1)
  4. Create a form in the frontend (Part 2)
  5. Create a Javascript function that takes the form inputs and sends them to the API (Part 2)
  6. Depending on the HTTP-response, display a success or an error message (Part 2)

 

Prerequisites

You obviously need to have a local WordPress installation a local PHP development environment. I currently use XAMPP for this. But other Software like MAMP or local by Flywheel will also do the job.

Getting started

To start off, I created a new WordPress project and a new theme that I called „test“. I will not bother you with the details of the installation, since this post focuses on another topic.

Creating the plugin

Next up, we need to actually create and register the plugin. In order to do so, we navigate into the /wp-content/plugins directory. There, we create a new folder. I’m going to call mine „test_sendMail“. It is of course up to you how you call this folder. However, the convention is to start the name off by the name of your theme.
In the newly created folder, we have to create a PHP file with the same name as the folder. In my case, this would be test_sendMail.php. In the end the folder structure looks like this:

wp-content
    plugins
        test_sendMail
            test_sendMail.php

 

For WordPress to notice and display the new plugin in the admin dashboard, we have to create a block comment at the top of he php file, like so:

<?php
/*
Plugin Name: Sending Mails
Description: Custom plugin for sending contact mails.
Version: 1.0.0
Author: Niclas Timm Dev
Author URI: you_domain.com
License: GPLv2 or later
*/

 

These infos will appear in the admin dashboard in the plugins section.
You must now got to your admin dashboard and activate the plugin.

Starting to code

Now that we are finally done with all the boring stuff, let’s start coding. For that, open the PHP file in your plugin directory.
Below the block comment from above, paste:

if (!defined("ABSPATH")) {
    exit;
}

 

This code prevents users from being able to access the plugin directly via the browser. This is obviously important for security reasons.

Register a new REST-API route

As indicated above, we will register a new route in the WordPress API. We can do this by leveraging a couple of predefined WordPress functions:

add_action("rest_api_init", function () {
    register_rest_route("/mail", "send", [
        "methods" => "post",
        "callback" => "sendMail" //sendMail will be defined below
    ]);
});

The „add_action“ function takes to arguments. The second one is a callback, the first argument defines when the callback should be fired. WordPress uses actions in so called „hooks“ that launch at execution or when a specific events occur. Here, it’s during the initiation of the REST-API routes („rest_api_init“). As a second parameter, we are providing the callback that will actually register the route. The „register_route_function“ takes three arguments.
The first one defines the namespace of the API endpoint. As we named it „/mail“, the full route so far ist /wp-json/mail.
The second one defines the base URL for that namespace. Thus, since we chose „send“, our full API endpoint route is /wp-json/mail/send.
The third argument takes an associative array. „method“ specifies the HTTP-method, in our case „post“, as we send data to the API. The second one is the callback that will be executed when the endpoint is hit. We will define that one in the next step.

Creating the function to send a mail

Getting the HTTP-request data

So now we will create the function that will actually send the mail. First of all, wen will name the function, create a try-catch-block and receive the data from the HTTP-request by the client:

function sendMail()
{
  $content = trim(file_get_contents("php://input")); //get request data

  $data = json_decode($content, true) //convert json in assoc. array
}
catch (\Throwable $th) {
  http_response_code(500);
  echo json_encode($th);
  exit;
    }

The first part of the function will store the data from the HTTP-request in a variable named $data.
As the request data will be in JSON format, it must be converted into a format that PHP can work with. This is done by using the function „json_decode“. It takes the json data as the first argument and a boolean as the second argument. If true, the json will be converted into an associative array. If false, it will be converted to a PHP object. We will work with an associative array here.

Now we extract the important data from the $data array that we just created:

function sendMail()
{
  $content = trim(file_get_contents("php://input")); //get request data

  $data = json_decode($content, true) //convert json in assoc. array


  //ADDED:
  $name = $data["name"];
  $email = $data["email"];
  $msg = $data["msg"];
}

This will extract the name, email address and message body from the HTTP-request and store them in separate variables. It is of course necessary that the request sends this data to our endpoint. If not, the catch-block will execute.

Validate HTTP-request data

We reached the point where our WordPress plugin for sending emails needs to validate the data we received from the client. We do this the following way:

function sendMail()
{
  $content = trim(file_get_contents("php://input")); //get request data

  $data = json_decode($content, true) //convert json in assoc. array

  $name = $data["name"];
  $email = $data["email"];
  $msg = $data["msg"];


  //ADDED:
  if ($name == null || $email == null ||  $msg == null) {
  http_response_code(400);
  $response = array(
  "error" => "Please fill all inputs with valid values."
  );
  echo json_encode($response);
  exit;
  }
}

Here, we check if any of the three inputs were left blank. If so, we send a response with the status code 400 to the client. Also, we create an associative array with an error message, transform it into json-format and send it to the client. We then exit the whole sendMail function without executing any further code.

Prepare the mail content

To eventually send the mail we of course have to define its content. As we will use the native PHP mail() function, we need the receiver, the subject, the header and the body of the mail.

function sendMail()
{
  $content = trim(file_get_contents("php://input")); //get request data

  $data = json_decode($content, true) //convert json in assoc. array

  $name = $data["name"];
  $email = $data["email"];
  $msg = $data["msg"];

  if ($name == null || $email == null ||  $msg == null) {
  http_response_code(400);
  $response = array(
  "error" => "Please fill all inputs with valid values."
  );
  echo json_encode($response);
  exit;
  }


  //ADDED:
  $to = "your@email.com";

  $header = array(
  "From" => "also_your@email.com",
  'X-Mailer' => 'PHP/' . phpversion()
  );

  $subject = "New contact request!";
  $message = "You have a new contact request \n\n\nName:\n"
    . $name . "\n\n"
    . "Mail:\n"
    . $email  . "\n\n"
    . "Message:\n"
    . $msg;
        
}

The $to variable defines who will receive the mail. You should enter your own email address here. In the header, we can define who the sender of the mail should be. You should choose a mail address that you own as well. The „X-Mailer“ option actually is optional and should only be set if you wanted to send an HTML-email. I kept it here for the purpose of completion. Defining the $subject and $message are pretty straight forward.

Send the mail

The only thing left in the plugin file is to actually send the mail. As stated above, we will use the native mail() function for this:

function sendMail()
{
  $content = trim(file_get_contents("php://input")); //get request data

  $data = json_decode($content, true) //convert json in assoc. array

  $name = $data["name"];
  $email = $data["email"];
  $msg = $data["msg"];

  if ($name == null || $email == null ||  $msg == null) {
  http_response_code(400);
  $response = array(
     "error" => "Please fill all inputs with valid values."
      );
      echo json_encode($response);
      exit;
  }


  $to = "your@email.com";

  $header = array(
    "From" => "also_your@mail.com",
    'X-Mailer' => 'PHP/' . phpversion()
  );

  $subject = "New contact request!";
  $message = "You have a new contact request \n\n\nName:\n"
     . $name . "\n\n"
     .  "Mail:\n"
     . $email  . "\n\n"
     . "Message:\n"
     . $msg;
        

  //ADDED:
  mail($to, $subject, $message, $header);
  http_response_code(200);
  $response = array(
    "msg" => "Die Mail was sent successfully."
     );
   echo json_encode($response);
   exit;
}

The mail function takes the receiver, subject, message and header as arguments, which we defined above. After the mail is sent, we send an HTTP response status code of 200 and send a json response to the client. The only thing left is to exit the function. And thats it!

The problem with PHP mail()

The code above is perfectly fine for creating a custom WordPress plugin for sending emails. If you actually try it out, however, you will find out that no mail will be send. This is because local development environments like XAMPP or MAMP do not have an email service. Thus, sending mails with the mail() function only works in production. This is the major drawback of using mail(). I can assure you, anyhow, that the given code works perfectly fine ūüėČ

Conclusion

Creating a new REST-API route in WordPress isn’t that hard. Neither is sending a mail with PHP. However, so far we only covered what happens when the endpoint is actually hit. Therefore, part 2 of this series will show you how to make a request to this endpoint with Javascript. Stay tuned!