Hoping someone can help.

I am trying to change the "Notice of Email Change" text within the email you receive when updating an email address.

Here is what I have so far

add_filter( 'password_change_email', 'red_change_password_mail_message', 10, 3 );

function red_change_password_mail_message( $pass_change_mail, $user, $userdata ) {

 $new_message_txt = __( 'Hi [first_name] [last_name], 

 This notice confirms that your email was changed on IBEW Local 353.

 If you did not change your email, please contact the Site Administrator at [email protected]

 This email has been sent to [user_email]

 All at IBEW Local 353' );
 $pass_change_mail[ 'message' ] = $new_message_txt;
 return $pass_change_mail;


As you can see I want to personalize the email message with their first and last name. What would be the best way to do this and would anyone be able to provide me with a example to start me off please.

  • What if users don't have a first or last name? The benefit of the username is that it's mandatory. Would it be acceptable to first check if both first and last name are set and if so use them, otherwise if only first name is available use that, and finally if neither are set, use the username? Commented Jun 6, 2017 at 21:20
  • 1
    I have created a custom Registration form which has set the first and last name to required fields to omit that issue. :) Good looking out :) Commented Jun 6, 2017 at 22:56

2 Answers 2


The filter to use to modify the e-mail sent to a user when they change their e-mail address is email_change_email. Note that this is different from password_change_email which you've used in your original code. That filter allows you to modify the e-mail sent to the user when their password is changed.

These two filters work similarly but it's important to make a distinction between the two. Both filters appear in wp-includes/user.php.

  • In the code below, we use the email_change_email to modify the message text. The new placeholders, ###FIRST_NAME### and ###LAST_NAME### have been added to the code (and docs) below.

  • The standard placeholders wherever possible in the message text, instead of hardcoding the strings.

  • Also, a text domain was added to the customized message text. It's always a good practice to add a text domain to strings that are passed to gettext functions ( __(), _e(), etc.).

 * Filters the contents of the email sent when the user's email is changed.
 * @param array $email_change_email {
 *            Used to build wp_mail().
 *            @type string $to      The intended recipients.
 *            @type string $subject The subject of the email.
 *            @type string $message The content of the email.
 *                The following strings have a special meaning and will get replaced dynamically:
 *                - ###USERNAME###    The current user's username.
 *                - ###FIRST_NAME###  The current user's first name.
 *                - ###LAST_NAME###   The current user's last name.
 *                - ###ADMIN_EMAIL### The admin email in case this was unexpected.
 *                - ###EMAIL###       The old email.
 *                - ###SITENAME###    The name of the site.
 *                - ###SITEURL###     The URL to the site.
 *            @type string $headers Headers.
 *        }
 * @param array $user The original user array.
 * @param array $userdata The updated user array.
add_filter( 'email_change_email', 'red_email_change_email', 10, 3 );
function red_email_change_email( $email_change_email, $user, $userdata ) {

    $new_message_txt = __( 'Hi ###FIRST_NAME### ###LAST_NAME###, 

This notice confirms that your email was changed on ###SITENAME###.

If you did not change your email, please contact the Site Administrator at

This email has been sent to ###EMAIL###

All at ###SITENAME###' );

    $email_change_email['message']  = $new_message_txt;

    $email_change_email['message'] = str_replace( '###FIRST_NAME###', $user['first_name'], $email_change_email['message'] );
    $email_change_email['message'] = str_replace( '###LAST_NAME###',  $user['last_name'],  $email_change_email['message'] );

    // Debugging helper. Uncomment to turn on.
    // update_option( 'wpse_debug_email_change_email_user', $user );

    return $email_change_email;


I've verified that this code does output the first and last names of the user. This information is coming from the user meta table, but it's already set up for us via the $user array by the core. I've manually replaced any personal info with**REMOVED**.

Example e-mail:

Hi Dave (first name) Romsey (last name),

This notice confirms that your email was changed on WP Theme Testing.

If you did not change your email, please contact the Site Administrator at

This email has been sent to **REMOVED**

All at WP Theme Testing

Here's the contents of the $user array:

    [ID] => 1
    [user_login] => dave
    [user_pass] => **REMOVED**
    [user_nicename] => dave
    [user_email] => **REMOVED**
    [user_url] => http://example.com/
    [user_registered] => 2016-02-14 05:29:13
    [user_activation_key] => 
    [user_status] => 0
    [display_name] => dave
    [first_name] => Dave (first name)
    [last_name] => Romsey (last name)
    [nickname] => dave
    [description] => This is the author’s test! <a href=\"#\">test link</a>
    [rich_editing] => true
    [comment_shortcuts] => false
    [admin_color] => fresh
    [use_ssl] => 0
    [show_admin_bar_front] => true
    [locale] => 

Here's a function that will display the $user array in the console of the admin area once the debugging line has been activated in the original code above.

 * Debugging helper. Outputs $user array to console in admin area. 
 * This data is saved via debugging line in red_email_change_email().
add_action( 'admin_head', 'wpse_debug_option' );
function wpse_debug_option() {
    $value = get_option( 'wpse_debug_email_change_email_user' );
    echo '<script>console.log( ' . json_encode( $value ) . ');</script>';
  • 1
    Thank you for this great insight, and yes as I was recycling some of the code from another function I forgot to change the password to email, so glad you spotted that. Commented Jun 6, 2017 at 22:49
  • When I try this code; the process still runs as normal however there is no first or last name, I am thinking its due to being in the user_meta table as opposed to the users table but may be wrong. Other then that it runs like a dream. :) Commented Jun 7, 2017 at 0:04
  • I've added some additional information that might help with debugging. I'm wondering if maybe you are storing the first and last names in different user meta keys? Mine are vanilla WP, first_name and last_name. Commented Jun 7, 2017 at 0:49
  • 1
    Hi Dave, when I view the user_meta table in phpmyadmin it shows the same name for the first_name and last_name column. I found the issue and it is now working perfectly. It appears that as I am using the Profile Builder Plugin, even when I updated first and last name in the dashboard for the user within the profile page on the frontend that data wa not there. As such no name was populating the email. I entered the name and BOOM you became my lifesaver. Thank you for such a great explanation as it has really assisted me in better understanding this type of task. Commented Jun 7, 2017 at 1:01
  • Thanks for the detailed feedback. I'll leave the debugging info since it might help someone in the future with a similar setup. Take care! Commented Jun 7, 2017 at 1:05

You're already passing a $user object into your function, so you should be able to substitute in $user->first_name and $user->last_name.

So just change $new_message_txt to:

$new_message_txt = __('Hi ' . $user->first_name ' . ' ' . $user->last_name . ',
...(rest of your message)
... ' . $pass_change_mail . '... end of your message');
  • Will this work even though first name and last name are within the user_meta table as opposed to the users table? Commented Jun 7, 2017 at 0:07
  • It should, since you're passing an entire $user object to it. As with any code, try it on a staging site and test it out to make sure all is working as planned before deploying to a live site.
    – WebElaine
    Commented Jun 7, 2017 at 14:21
  • Sorry WebElaine, I posted that comment prior to debugging the above solution. Both did work in the end but I marked the other as the answer as for the community I felt it was more detail oriented but both were amazing viable answers and I am sure will help many more. Thanks again. Commented Jun 7, 2017 at 17:11

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.