I have an external service registering and altering the status of Drupal users, performing user_save() on several occasions depending on the service response. So i am blocking and unblockiing users and other operations.

My problem is i cant find a descent way to override this code inside user_save()

// Send emails after we have the new user object.
if ($account->status != $account->original->status) {
 // The user's status is changing; conditionally send notification email.
 $op = $account->status == 1 ? 'status_activated' : 'status_blocked';
 _user_mail_notify($op, $account);

ideally i would like to have full control on what is going to be sent depending on user role, the account status etc. say for example

// pseudo code
if (user_is_external and statusChanged){
  dont send email
} else {

Is this possible? thanks

2 Answers 2


Maybe you should take a look at drupal_mail function

// Invoke hook_mail_alter() to allow all modules to alter the resulting e-mail.
drupal_alter('mail', $message);

// The original caller requested sending. Sending was canceled by one or
// more hook_mail_alter() implementations. We set 'result' to NULL, because
// FALSE indicates an error in sending.
if (empty($message['send'])) {
  $message['result'] = NULL;

Then hook_mail_alter

From description

$message: An array containing the message data. Keys in this array include:

'send': Set to FALSE to abort sending this email message.

'params': An array of optional parameters supplied by the caller of drupal_mail() that is used to build the message before hook_mail_alter() is invoked.

Parameters usually contain $message['params']['account'], so you can abort e-mail sending by role or other way.

Example (not tested) aborting any e-mail to account with specific role:

function MY_MODULE_mail_alter(&$message) {
  $role = 'CUSTOM_ROLE';
  if (!isset($message['params']['account'])) return;
  $account = $message['params']['account'];
  if (is_array($account->roles) && in_array($role, array_values($account->roles))) {
    $message['send'] = NULL;

There is an issue then sending custom e-mails, $account contain sender account object, not receiver. But for default notifications this should work. So don't forget to check $message['key'] for default notification types from _user_mail_notify, it always provide $account object mail is sending to:

'register_admin_created': Welcome message for user created by the admin.
'register_no_approval_required': Welcome message when user self-registers.
'register_pending_approval': Welcome message, user pending admin approval.
'password_reset': Password recovery request.
'status_activated': Account activated.
'status_blocked': Account blocked.
'cancel_confirm': Account cancellation request.
'status_canceled': Account canceled.

The decision not to send email is Not made in the user_save function but rather in _user_mail_notify(). That function checks the variables table.

The only way I see for you to acquire this control (without hacking core) is for you to disable all related user email for the core email functions, and to write your own module using hook_user_insert and hook_user_update.

  • And how to control all related user email?
    – Pan Chrono
    Feb 27, 2013 at 10:37
  • Several can be disabled at /config/people/accounts. The rest can be disabled with entries in the variables table. The entries will have the form 'user_mail_' . $op . '_notify' and should be set to FALSE. Look at the API entry for _user_mail_notify for a list of the op's.
    – Triskelion
    Feb 27, 2013 at 17:03

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.