WordPress: Email Templating System for Your Custom Plugin

If you’re creating a plugin and you want an easy way to generate HTML emails within a standard template, then this code should get you most of the way there.  It allows for passing an array of data to the template, which is a must-have feature.  Importantly, it also provides a way for users to override the templates in their own theme.

The core template function:

function myprefix_get_email_from_template($template_name, $template_data) {
  $html = '';
  $path = false;
  
  $override_path = get_template_directory() . '/email/'.$template_name.'.php';
  $template_path = plugin_dir_path( __FILE__ ) . 'assets/email/'.$template_name.'.php';
  if (file_exists($override_path)) {
    $path = $override_path;
  }
  elseif (file_exists($template_path)) {
    $path = $template_path;
  }
  
  if ($path) {
    ob_start();
    include($path);
    $html = ob_get_clean();
  }
  
  return $html;
}

It first looks for the template in the “email” directory of the current theme. If not found, it defaults to the “assets/email” directory of the plugin.  You can change the plugin path to whatever you would like.

If the template file is found it will then start output buffering, capturing the output of the included template file into the $html variable.

To enable HTML in the wp_mail() function we need to create a filter function. This filter can be added immediately before calling wp_mail() and then removed immediately after.

// Function called by wp_mail_content_type filter to enable HTML enable.
function myprefix_wp_mail_content_type_html() {
  return 'text/html';
}

A sample implementation of the email template function, along with the code to actually send the email:

function myprefix_send_invitation_email() {
  $email_data = array(
    'recip_name'   => trim(sanitize_text_field($_POST['first_name']) . ' ' . sanitize_text_field($_POST['last_name'])),
    'email'        => sanitize_text_field($_POST['email']),
    'sender_name'  => get_customer_name($sender_id),
    'register_url' => get_site_url(null, '/my-account/?register=1&invite_token='.urlencode($invite_token))
  );
  $body = myprefix_get_email_from_template('invite-a-friend', $email_data);
  
  $subject =  'An invitation from ' . $email_data['sender_name'];
  $to = $email_data['recip_name'] . '<' . $email_data['email'] . '>';
  add_filter( 'wp_mail_content_type', 'myprefix_wp_mail_content_type_html' );
  $sent = wp_mail($to, $subject, $body);
  remove_filter( 'wp_mail_content_type', 'myprefix_wp_mail_content_type_html' );
}

Of course you will need to create templates also.  Here is a sample “invite-a-friend” template:

<?php include('head.php'); ?>
<?php if ($template_data['recip_name'] != '') { ?>
<p style="color:#ffffff; font-size:14px;">Dear <?php echo esc_html($template_data['recip_name']); ?>,</p>
<?php } ?>
<p style="color:#ffffff; font-size:14px;">Your friend, <?php echo esc_html($template_data['sender_name']); ?>, thinks that you will enjoy our website, and has invited you to join. If you are interested in becoming a member, simply follow the link below.</p>

<p style="color:#ffffff; font-size:14px;">Please <a href="<?php echo esc_attr($template_data['register_url']); ?>" style="color:#ffffff;">click here</a> to register today.</p>

<p style="color:#ffffff; font-size:14px;">Very best wishes,<br />The Example Company</p>

<?php include('foot.php'); ?>

All variables are included in the $template_data array, which we passed in from the myprefix_get_email_from_template() function.  Also note that the first and last line of the template are including head.php and foot.php, respectively. You’ll need to add those files into your plugins email templates directory.  This is where you’ll add your re-usable email template HTML.  At the least you’ll want to add <html> and <body> tags, and most likely you’ll add your company logo and some contact info.  I’m not going to go into the details of generating HTML for emails since that’s a whole other subject that already has volumes written about it.

If you want to use the template system, but be able to generate the entire email body on the fly, you can create a generic email template file such as assets/email/generic.php, with the following content:

<?php include('head.php'); ?>
<div style="color:#000000;">
<?php echo $template_data['content']; ?>
</div>
<?php include('foot.php'); ?>

Then you can use the following to return your custom HTML within the template, assuming that $body contains your HTML:

$email_msg = myprefix_get_email_from_template('generic', array('content' => $body));