if a user changes his email address, I want him to lose a specific role (if he had that role in the first place). To make matters more complicated, we have the "email confirm" module enabled and this bitchy little module uses user_presave() in a way that leaves no traces of an email change when it is called during the edit of a profile. So I wrote a module and gave it weight -1 to make sure it gets a chance to compare $edit->mail to the users current mail before "email confirm" begins to work.

My code looks like this (version with a lot of debug statements that will be removed in the live environment):

function xyz_user_presave(&$edit, $account, $category) {
  if (!empty($edit['mail']) && (!empty($account->mail) && $account->mail != $edit['mail']) && !user_access('administer users') && !drupal_installation_attempted()) {
    // remove xyz role if the users changes his email address
    $user = user_load_by_mail($account->mail);
    $role = user_role_load_by_name('xyz');
    if (array_key_exists($role->rid, $user->roles)){
      drupal_set_message('In if-clause.');
      $return1 = print_r($user->roles, TRUE);
      $user2 = user_save($user, array('roles' => array_filter($user->roles, function($item) use ($role) {return $item != $role->name;})));
      $user3 = user_load_by_mail($account->mail);
      $return2 = print_r($user3->roles, TRUE);
      if (!$user2){
        drupal_set_message('User_save() failed.');      

If I log in with a test user that has role xyz and change his email address at the "edit profile" site, i receive these status messages:

  • In if-clause.
  • Array ( [2] => authenticated user [5] => abc [8] => xyz )
  • Array ( [2] => authenticated user [5] => abc )

The debug messages tell me that:

  1. It has been found out, that the user has the role xy and therefor the if-clause was entered.
  2. Before the call to user_save(), the user had the role xyz
  3. After the call to user_save(), the user was freshly loaded and he did not have the role xyz anymore

Yet despite all this, the user does not lose the role, no matter how often I change the email address or flush the cache.

My question now is: What the hell?

Using user_save() in the user_presave() function seems to be odd, but when I put the $roles array in $edit without the xyz-role, I receive pdo exception that states, that the roles are already set for this user.

1 Answer 1


This did the trick.

function xyz_user_presave(&$edit, $account, $category) {
  if (!empty($edit['mail']) && (!empty($account->mail) && $account->mail != $edit['mail']) && !user_access('administer users') && !drupal_installation_attempted()) {
    $role_position = array_search('xyz', $account->roles);
    // Use !== or === here since $role_position may be zero or FALSE
    if ($role_position !== FALSE) {
      $edit['roles'] = $account->roles;

I still do not know what's wrong with the code in the initial post, but whatever...

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.