views:

80

answers:

1

hi,

what's the point to have hook_mail_alter if I already have hook_mail ?

For example, I saw that hook_mail_alter is used to add a footer to my mail message. But I could use hook_mail to add it, instead of using 2 functions... what am I missing ?

Maybe it is done to add the footer after some other function is invoked ?

thanks

+4  A: 

hook_mail() should be used from a module to alter its own mail message, while hook_mail_alter() should be used from a module to alter the message sent by other modules.

This is clear from the following code taken from drupal_mail():

// Build the e-mail (get subject and body, allow additional headers) by
// invoking hook_mail() on this module. We cannot use module_invoke() as
// we need to have $message by reference in hook_mail().
if (function_exists($function = $module .'_mail')) {
  $function($key, $message, $params);
}

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

$module is the first parameter passed to drupal_mail().
It's clear the function doesn't invoke the implementation of hook_mail() of every module implementing it, but it invokes the hook just for the module calling the function.

There are other differences, such as when the two hooks are invoked (hook_mail_alter() cannot set the language for the message, which is set before hook_mail_alter() is invoked), and the parameters they get (hook_mail($key, &$message, $params) versus hook_mail_alter(&$message)).

kiamlaluno
@kiamlaluno: "It's clear the function doesn't invoke the implementation of hook_mail() of every module implementing it". Does it invoke the implementation of hook_mail_alter of every module instead ?
Patrick
@Patrick: Yes, it does. That is the purpose of `drupal_alter()`: to call every module implementing the alter hook that matches the name passed as first argument to the function.
kiamlaluno
@Patrick: after a hook (say, hook_example) is invoked, and something calls `drupal_alter`, `hook_example_alter` is run. So `hook_*_alter` is always run after the regular hook. See http://api.drupal.org/api/function/drupal_alter/6 and the functions that call it to get an idea of how it works.
Mark Trapp
`hook_example_alter()` will be invoked if a module calls `drupal_alter('example')`; not all the modules that use `hook_example()` use also `hook_example_alter()`. It is true that generally `hook_example_alter() is invoked after `hook_example()`.
kiamlaluno
@kiamlaluno: ok Thanks. One more thing.. just for my understanding: if I invoke "module_invoke_all('mail')", I would invoke all hooks (and probably sending wrong e-mails without reason.. so it is not a substitute for mail_alter, but just to understand..). Correct ?
Patrick
@Patrick: That is correct. Some implementations of `hook_mail()` don't check the first parameter (compare [`user_mail()`](http://api.drupal.org/api/function/user_mail/6) with [`contact_mail()`](http://api.drupal.org/api/function/contact_mail/6)) because they just send a type of message. If you would call `module_invoke_all('mail')`, those implementations would think they are getting a message they sent, and they would probably alter the message in a way that is not correct.
kiamlaluno

related questions