In hook_mail() I might discover that some part of the email couldn't be generated (maybe when trying to load a variable from an external system it fails).

How can I cancel the sending? I don't want to send an email with an error message in it.

Example code:

function mymodule_mail($key, &$message, $params) {
  switch ($key) {
    case 'some_email':
      $foo = Something::fetchSomething($params['bar']);
      if (!$foo) {
        // I don't want to send this email any more
      else {
        $message['body'][] = t('Important information about @foo.' ['@foo' => $foo]);

Does that make sense? Or should all parameters be loaded and processed before hook_mail() and in hook_mail() you assume to always have those params available?

  • Just remove the to address maybe? Or don't set a body? It was something like that in D7, probably similar in D8. If all else fails, you can set $message['send'] = FALSE; in hook_mail_alter()
    – Clive
    Aug 8, 2017 at 14:38

1 Answer 1


You can do the access check from hook_mail_alter instead of hook_mail (let it prepare the default message based on parameters, and alter it later) by something like:

function HOOK_mail_alter(&$message) {
  // can add additional check for particular mails here,
  // by checking the value in $message['id']
  if (TRUE) {
    $message['send'] = FALSE;

Note: You should clear the cache in order to make the changes effective.

  • Thanks for letting me know about $message['send']. It seems that $message['send'] = FALSE also works in hook_mail(). Is there any reason not to?
    – Rob
    Aug 9, 2017 at 16:34
  • 1
    Only thing would be that it's undocumented so it could theoretically stop working any time. The likelihood is probably quite small though
    – Clive
    Aug 9, 2017 at 16:53

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.