8

does anybody know how to hook or filter the user-edit.php file so that an user's email address is disabled from editing akin to how the username is disabled ..??..

i can edit the core file (gasp) and include disabled="disabled" in the form and this works but i'm at a loss as to how to add the disable via hook or filter ..

i can also run a function like this that hides the email address via css

/* Change WordPress dashboard CSS */
function custom_admin_styles() {
echo '<style type="text/css">#email { display: none !important; }</style>';
}
add_action('admin_head', 'custom_admin_styles');

but that pulls out the whole email thus form looks funny and then i believe that with a DOM Editor like Firebug, one can still access that email field thus change it ... ugh ...

ideally, i would like to replace this entire user-edit.php code from this ->

<label for="email"><?php _e('E-mail'); ?> <span class="description"><?php _e('(required)'); ?></span></label></th><td><input type="text" name="email" id="email" value="<?php echo esc_attr($profileuser->user_email) ?>" disabled="disabled" class="regular-text" /> <span class="description"><?php _e('Emails cannot be changed.'); ?></span>

to something like this ->

<label for="email"><?php _e('E-mail'); ?> </label></th><td><?php echo esc_attr($profileuser->user_email) ?>" Please Contact Tech support to change your email

thanks in advance for any pointers you can share ... cordially, chuck scott

2
  • you can use JQuery .append to disable it but it's a hackish way
    – Bainternet
    Mar 10, 2011 at 21:05
  • For everyone how don´t no wich line it is in line 507 in wordpress version 5.6 Feb 5, 2021 at 17:16

7 Answers 7

6

The only correct solution

(Other answers I see are faulty, vulnerable or incomplete. All of them can be bypassed.)

This plugin does correctly:

class DisableMailChange
{

    public function __construct()
    {
        //prevent email change
        add_action( 'personal_options_update',  [$this, 'disable_mail_change_BACKEND'], 5  );
        add_action( 'show_user_profile',        [$this, 'disable_mail_change_HTML']  ); 
    }

    public function disable_mail_change_BACKEND($user_id) {
        if ( !current_user_can( 'manage_options' ) ) { 
            $user = get_user_by('id', $user_id ); $_POST['email']=$user->user_email; 
        } 
    }

    public function disable_mail_change_HTML($user) {
        if ( !current_user_can( 'manage_options' ) ) { 
            echo '<script>document.getElementById("email").setAttribute("disabled","disabled");</script>';
        } 
    }
}
new DisableMailChange();
1
  • If someone needs to disable the user email editing not only for their own profile, the modified backend function needs to be added to the 'edit_user_profile_update' action too. Oct 25, 2022 at 13:45
4

Not exact answer, but to prevent email change (actual change, not field edit) you could tweak around this action:

add_action( 'user_profile_update_errors', 'prevent_email_change', 10, 3 );

function prevent_email_change( $errors, $update, $user ) {

    $old = get_user_by('id', $user->ID);

    if( $user->user_email != $old->user_email   && (!current_user_can('create_users')) )
            $user->user_email = $old->user_email;
}
6
  • Is there any other better function than the user_profile_update_errors?
    – Starx
    Oct 28, 2015 at 16:52
  • Define better? Very old answer, I wouldn't remember on top of my head. :)
    – Rarst
    Oct 28, 2015 at 16:54
  • By better I mean any other function that doesn't need to hook to errors action. But then I read the hooks list and it does execute before the changes to the user is committed so its fine I think. I take my comment back :)
    – Starx
    Oct 28, 2015 at 18:13
  • You missed (!current_user_can('create_users'))...
    – T.Todua
    Feb 6, 2016 at 8:54
  • 1
    For those who are also looking for a WooCommerce action hook, there is one: do_action_ref_array( 'woocommerce_save_account_details_errors', array( &$errors, &$user ) ); Apr 10, 2019 at 20:42
2

Dirty hack, feel free to modify.

Only admins or users with edit_users cap "can change" email, others can't.

Theme functions.php:

class Edit_Email {
    function start() {
        ob_start();
    }

    function footer() {
        $content = ob_get_contents();

        ob_end_clean();

        $this->replace( $content );

        echo $content;
    }

    function replace( &$content ) {
        $pattern = array(
            '/E-mail <span.+?<\/span>/',
            '/<input type="text"(.*?)value="(\\S+@\\S+\\.\\w+)[^>]*\/>/'
        );

        $replacement = array(
            'E-mail',
            '<input type="hidden"\1value="\2" /> \2 Please Contact Tech support to change your email.'
        );

        $content = preg_replace( $pattern, $replacement, $content );
    }
}

if ( ! current_user_can( 'edit_users' ) && ( $pagenow == 'profile.php' ) ) :
    $edit_email = new Edit_Email();
    $edit_email->start();

    add_action( 'admin_footer', array( &$edit_email, 'footer' ) );
endif;
1
  • AVOID THIS ANSWER!. worst and wrongest solution, leading to security issues. html modifications are just nothing - the request should be blocked in backend! (even the strangest way to modify the html, while you could have just used css to hide with display:none)
    – T.Todua
    Apr 6, 2020 at 12:33
2

In addition to Rarst's answer:

To prevent email change server side

add_action( 'user_profile_update_errors', 'prevent_email_change', 10, 3 );

function prevent_email_change( $errors, $update, $user ) {

    $old = get_user_by('id', $user->ID);

    if( $user->user_email != $old->user_email   && (!current_user_can('create_users')) )
            $user->user_email = $old->user_email;
}

To disable WordPress user email profile fields

add_action('admin_init', 'user_profile_fields_disable');

function user_profile_fields_disable() {

    global $pagenow;

    // apply only to user profile or user edit pages
    if ($pagenow!=='profile.php' && $pagenow!=='user-edit.php') {
        return;
    }

    // do not change anything for the administrator
    if (current_user_can('administrator')) {
        return;
    }

    add_action( 'admin_footer', 'user_profile_fields_disable_js' );

}

function user_profile_fields_disable_js() {
?>
    <script>
        jQuery(document).ready( function($) {
            var fields_to_disable = ['email'];
            for(i=0; i<fields_to_disable.length; i++) {
                if ( $('#'+ fields_to_disable[i]).length ) {
                    $('#'+ fields_to_disable[i]).attr("disabled");
                    $('#'+ fields_to_disable[i]).after("<span class=\"description\"> " + fields_to_disable[i] + " cannot be changed.</span>");
                }
            }
        });
    </script>
<?php
}

Resources

https://www.role-editor.com/hide-disable-wordpress-user-profile-fields/

1

You can use JQuery to disable the email (and any other fields in the edit profile page).

For example, something like this in a plugin:

  //Disables certain fields (email, password) in WP Admin edit user page (user-edit.php)
   global $pagenow;
   if ( $pagenow == 'user-edit.php' ) {
        add_action( 'admin_footer', 'disable_userprofile_fields' );
   }

    /**
    * Disables certain fields (email, password) in WP Admin edit user page (user-edit.php)
    */
    function disable_userprofile_fields() {
    ?>
        <script>
            jQuery(document).ready( function($) {
                if ( $('input[name=email]').length ) {
                    $('input[name=email]').attr("disabled", "disabled");
                }
                if ( $('input[name=pass1]').length ) {
                    $('input[name=pass1]').attr("disabled", "disabled");
                }
                if ( $('input[name=pass2]').length ) {
                    $('input[name=pass2]').attr("disabled", "disabled");
                }
            });
        </script>
    <?php
    }
0

This should do it:

    add_action( 'personal_options_update', 'disable_email_change_back'); // own profile
    add_action( 'edit_user_profile_update', 'disable_email_change_back'); // others profiles
    function disable_email_change_back($user_id) {
        $user = get_user_by('ID', $user_id);
        $_POST['email'] = $user->user_email;
    }
    
    add_action( 'show_user_profile', 'disable_email_change_front'); // own profile
    add_action( 'edit_user_profile', 'disable_email_change_front'); // others profiles
    function disable_email_change_front($profileuser) {
        echo '<script>document.getElementById("email").setAttribute("disabled","disabled");</script>';
    }
-1

The hack given below has been tested with WordPress 3.1.

Open user-edit.php, find:

<th><label for="email"><?php _e('E-mail'); ?> <span class="description"><?php _e('(required)'); ?></span></label></th>
<td><input type="text" name="email" id="email" value="<?php echo esc_attr($profileuser->user_email) ?>" class="regular-text" /></span>

and replace with:

<th><label for="email"><?php _e('E-mail'); ?> <span class="description"></span></label></th>
<td><input type="hidden" name="email" id="email" value="<?php echo esc_attr($profileuser->user_email) ?>" class="regular-text" /><?php echo esc_attr($profileuser->user_email) ?></span>

It is just a workaround that visually removes the ability to change email addresses, not actually disable the feature.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy