hook_mail() should be used from the module to modify its own mail message, and hook_mail_alter() should be used from the module to modify the message sent by other modules.
This can be seen 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 clears this function, does not call the hook_mail() implementation of each module that implements it, but calls only the module that calls the function.
There are other differences, for example, when calling two hooks ( hook_mail_alter() cannot set the language for the message that was set before calling hook_mail_alter() ) and the parameters that they receive ( hook_mail($key, &$message, $params) compared to hook_mail_alter(&$message) ).
source share