0

I am looking to send out emails to users in my WordPress site/system. I want to have emails that say something like:

You have X credits remaining to fulfill Y.

Your deadline is Z.

X,Y,Z would be information pulled from custom fields i have created in the system and/or from sql queries.

I am looking for either a plugin or some tips as to how to go about doing this manually through code. I will be sending these out on demand as well as monthly, etc.

Thank you for your guidance, and let me know if you could use more information. I tried to keep it as simple as possible. Maybe wp-mail is the way to go?

6
  • Can you be more specific about what your fields are and what code you’ve tried? Commented Jun 22, 2018 at 17:22
  • I have not tried any code yet, as I am looking for how to go about doing so. I am trying to pull in numbers and words from custom fields assigned to custom post types. so in the user_meta table i would want to draw from, say, something like "wpcf-credits-remaining" etc Commented Jun 22, 2018 at 18:10
  • Look at the wp_mail function. You can use that anywhere to send an email from your site. You can construct any message body you like in code with all the relevant fields in. Commented Jun 22, 2018 at 18:28
  • This looks good, and I see the general idea of wp_mail, but I am still not sure how I would go about making a "nice" email that isn't just a string of text for the "body". I want a nicely formatted email with fonts, colors, images, etc. I have looked into setting up a cron job to fire it off monthly as well. Just trying to figure out how to make the email outside of the wp_mail call. Commented Jun 22, 2018 at 19:01
  • OK, I can show you how to use wp_mail, how to include post meta fields in your email, how to make WP send HTML mail. HTML in email is a bit of a speciality and so I'd say the exact HTML and any styling are a bit outside the scope of a WordPress question. Bear with me while I work up an answer. Commented Jun 22, 2018 at 19:30

1 Answer 1

1

The Basics

You can send an email from anywhere within WordPress using wp_mail():

wp_mail( $to, $subject, $message, $headers, $attachments )

$to can be a string or an array for multiple recipients. Any RFC 2822 compliant address will work, so you can include a real name as well as an email address.

$subject & $message are strings and $message can be a string of HTML.

Optionally, $headers can be a string or an array of additional email headers and $attachments can be an array of files to attach.

HTML Email

If you are using HTML for the content, then before sending the email you can add a simple function to a filter that will handle setting the mime type correctly for you:

function wpse306737_set_html_content_type($content_type){
    return 'text/html';
}

add_filter( 'wp_mail_content_type', 'wpse306737_set_html_content_type' );

After sending your email it's good practice to remove this filter again so that you don't affect any email that might be sent later in the WP code run:

remove_filter( 'wp_mail_content_type', 'wpse306737_set_html_content_type' );

The From: Address

By default emails come from wordpress@sitename. You can use filters to change this:

add_filter( 'wp_mail_from', 'wpse306737_mail_from' );
add_filter( 'wp_mail_from_name', 'wpse306737_mail_from_name' );

function wpse306737_mail_from() {
    return '[email protected]';
}

function wpse306737_mail_from_name() {
    return 'John Smith';
}

You can also set headers if you prefer,

$headers[] = 'From: John Smith <[email protected]>';

but WP filters seem more in keeping with the WP Way.

Other Headers

$headers[] = 'Cc: The Shop <[email protected]>';
$headers[] = 'Bcc: Jane Jones <[email protected]>';

Building the Message

The message is just a string, so concatenate plain text, HTML and any data from WP that you want. If we are using post meta fields and are in the loop, then:

$message = '';
$custom_fields = get_post_custom();
$message .= 'You have ' . $custom_fields['X'] . ' credits remaining to fulfill ' . $custom_fields['Y'] . '.';
$message .= 'Your deadline is ' . $custom_fields['Z'] . '.';

A note on retrieving meta data

get_post_custom() returns all custom fields for the current post when you're within the loop. You can call it with a post ID to get the meta data for particular post: get_post_custom(3) for example.

get_post_custom() will return an array of all post meta, some of it possibly serialised, some of it possibly in arrays and so you may find it better to use a number of calls to get_post_meta() which will let you get your data by metakey and specify whether it may be single or multiple values: get_post_meta( 3, 'total_points', true ) will return a single value for the meta field with key total_points attached to the post with ID 3.

You don't state how the data you want to use is stored, but there are equivalent functions for retrieving user meta, term meta and comment meta. get_user_meta(), get_term_meta() & get_comment_meta() all work in the same way as get_post_meta().

In fact if you look at the source code, WP will happily return any meta as long as there is a database table for it, so you could even use built-in functions and take advantage of the WordPress meta cache for your own database tables if your tables have suitable names. The get_{type}_meta() functions I've referred to all call upon get_metadata(). Calling get_metadata( 'thing', 3 ) will check for a WP db table called thingmeta and will use it to retrieve meta data. get_metadata() also has a filter get_{$meta_type}_metadata to short-circuit this database lookup allowing you to substitute any data source that you like.

Sending the Mail

Putting all this together, you get:

add_filter( 'wp_mail_from', 'wpse306737_mail_from' );
add_filter( 'wp_mail_from_name', 'wpse306737_mail_from_name' );

function wpse306737_mail_from() {
    return '[email protected]';
}

function wpse306737_mail_from_name() {
    return 'John Smith';
}

$headers = array(); // let's be safe
$headers[] = 'Cc: The Shop <[email protected]>';
$headers[] = 'Bcc: Jane Jones <[email protected]>';

$message = '';
$custom_fields = get_post_custom();
$message .= '<p>You have ' . $custom_fields['X'] . ' credits remaining to fulfill ' . $custom_fields['Y'] . '.</p>';
$message .= '<p><strong>Your deadline is ' . $custom_fields['Z'] . '.</strong></p>';

$to = 'Site User <[email protected]>';
$subject = 'Meet your deadline!';

function wpse306737_set_html_content_type($content_type){
    return 'text/html';
}

add_filter( 'wp_mail_content_type', 'set_html_content_type' );

wp_mail( $to, $subject, $message, $headers );

remove_filter( 'wp_mail_content_type', 'set_html_content_type' );

Sending Loads of Email

You might want to preserve your server's reputation and improve deliverability by sending the email out through a valid SMTP account or a transactional email service, so that you can take advantage of SPF, DKIM and DMARC.

4
  • Nice answer, but maybe a word or two about the (context) restriction of using get_post_custom() and what post it's referring to here and an extra check for existence of array keys to avoid PHP notices. Also what about output escaping - e.g. the case of a user adding evil HTML+JS into the custom fields?
    – birgire
    Commented Jun 23, 2018 at 8:34
  • 1
    All good points. I did try to get the questioner to provide more context. I’ll think about some edits. Commented Jun 23, 2018 at 9:02
  • @birgire Updated to allow for just about any source of metadata you can think of :-). I'll think about sanitisation too. Commented Jun 23, 2018 at 17:07
  • I wanted to thank you Andy before I go try my hand at all this. I can't believe the quality of the answer! I'll get back to this thread soon with my experience. Commented Jun 25, 2018 at 2:08

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.