Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm just wondering why wordpress doesn't send confirmation mail every time user change his/her email address.

How do we know that email address is not fake or mistyped?

So can anyone give me some snippet to implement this function?


Here is the idea.

  1. user changes his/her mail
  2. We send confirmation email.
  3. If the user confirm that email in X days by clicking confirmation link, then the email should be changed. Else we should use existing email.
share|improve this question
So if the user changes his/her email do they get logged out and not allowed back in until they re-verify their email address? –  Brady Feb 9 '12 at 11:49
No, That will be bad. What if the user mistype the email address and get logged out? He/she can't verify it. So he/she will be blocked forever. We just giving warning message to verify his/her email address. If the user not verify his/her email in X hours (Say 24 hours) then the already verified mail should be used. –  Giri Feb 9 '12 at 13:48
Please put these details in the question. –  Brady Feb 9 '12 at 15:52

2 Answers 2

up vote 5 down vote accepted

Like SickHippie posted this functionality is native to WordPress but only for a multisite setup so here is the two functions you need to get this to work on a single site setup which are mostly code one for one from the core /wp-admin/user-edit.php file

function custom_send_confirmation_on_profile_email() {
    global $errors, $wpdb;
    $current_user = wp_get_current_user();
    if ( ! is_object($errors) )
        $errors = new WP_Error();

    if ( $current_user->ID != $_POST['user_id'] )
        return false;

    if ( $current_user->user_email != $_POST['email'] ) {
        if ( !is_email( $_POST['email'] ) ) {
            $errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address isn't correct." ), array( 'form-field' => 'email' ) );

        if ( email_exists( $_POST['email'] ) ) {
            $errors->add( 'user_email', __( "<strong>ERROR</strong>: The e-mail address is already used." ), array( 'form-field' => 'email' ) );
            delete_user_meta( $current_user->ID . '_new_email' );

        $hash = md5( $_POST['email'] . time() . mt_rand() );
        $new_user_email = array(
            'hash' => $hash,
            'newemail' => $_POST['email']
        update_user_meta( $current_user->ID . '_new_email', $new_user_email );

        $content = apply_filters( 'new_user_email_content', __( "Dear user,

    You recently requested to have the email address on your account changed.
    If this is correct, please click on the following link to change it:

    You can safely ignore and delete this email if you do not want to
    take this action.

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

    All at ###SITENAME###
    ###SITEURL###" ), $new_user_email );

        $content = str_replace( '###ADMIN_URL###', esc_url( admin_url( 'profile.php?newuseremail='.$hash ) ), $content );
        $content = str_replace( '###EMAIL###', $_POST['email'], $content);
        $content = str_replace( '###SITENAME###', get_site_option( 'site_name' ), $content );
        $content = str_replace( '###SITEURL###', home_url(), $content );

        wp_mail( $_POST['email'], sprintf( __( '[%s] New Email Address' ), get_option( 'blogname' ) ), $content );
        $_POST['email'] = $current_user->user_email;
add_action( 'personal_options_update', 'custom_send_confirmation_on_profile_email' );

// Execute confirmed email change. See send_confirmation_on_profile_email().
function verify_email_change(){
    global $errors, $wpdb;
    $current_user = wp_get_current_user();
    if (in_array($GLOBALS['pagenow'], array('profile.php')) && $current_user->ID > 0) {
        if (isset( $_GET[ 'newuseremail' ] ) && $current_user->ID ) {
            $new_email = get_user_meta( $current_user->ID . '_new_email' );
            if ( $new_email[ 'hash' ] == $_GET[ 'newuseremail' ] ) {
                $user->ID = $current_user->ID;
                $user->user_email = esc_html( trim( $new_email[ 'newemail' ] ) );
                if ( $wpdb->get_var( $wpdb->prepare( "SELECT user_login FROM {$wpdb->users} WHERE user_login = %s", $current_user->user_login ) ) )
                    $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->users} SET user_email = %s WHERE user_login = %s", $user->user_email, $current_user->user_login ) );
                wp_update_user( get_object_vars( $user ) );
                delete_user_meta( $current_user->ID . '_new_email' );
                wp_redirect( add_query_arg( array('updated' => 'true'), self_admin_url( 'profile.php' ) ) );
        } elseif ( !empty( $_GET['dismiss'] ) && $current_user->ID . '_new_email' == $_GET['dismiss'] ) {
            delete_user_meta( $current_user->ID . '_new_email' );
            wp_redirect( add_query_arg( array('updated' => 'true'), self_admin_url( 'profile.php' ) ) );
share|improve this answer
Hi, your verify_email_change function contains multisite related codes ({$wpdb->signups). Can you fix it? –  Giri Dec 13 '12 at 6:21
@Giri - just did m thanks. –  Bainternet Dec 14 '12 at 21:12

This is a strange 'feature'. The function is actually available inside WordPress (WordPress.com has it enabled for their managed blog service), but it is restricted to multisite. If you look in /wp-admin/includes/ms.php you'll find the function that handles this - line 239 send_confirmation_on_profile_email().

Presumably, you could move this function into your functions.php or into a plugin to gain this functionality, possibly with a bit of tweaking to get it to work right. It doesn't answer the "why", but neither does the trac ticket on this subject here.

ETA: Looking further into it, there's a few other functions you may need to duplicate as well - new_user_email_admin_notice() and update_option_new_admin_email() jump out as potentially necessary.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.