There is a limit to what you can do to a mail with hook_mail_alter() because your module won't have access to the $params variable that was used to build the $message in the first place.

Example: emails sent by contact module. http://api.drupal.org/api/function/drupal_mail/7 invokes http://api.drupal.org/api/function/contact_mail/7. The latter has the full $params. If you want to modify the message using http://api.drupal.org/api/function/hook_mail_alter/7 you only get the $message to play with, so if you want to do anything major to it you will probably need to override the caller of drupal_mail(). In this case that would be http://api.drupal.org/api/function/contact_personal_form_submit/7 or http://api.drupal.org/api/function/contact_site_form_submit/7; seems this could be more efficient if $params were passed to the mail alter hooks.

Note that the $params concept (and http://api.drupal.org/api/function/hook_mail/7) only arrived with Drupal 6, so extending $params to the mail alter hooks seems a natural follow-up.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

gpk’s picture

Title: Make $params available to hook_mail_alter() » Document that $params is available to hook_mail_alter()
Component: base system » documentation
Category: feature » bug

Closer inspection of http://api.drupal.org/api/function/drupal_mail/7 shows that $params is available as $message['params'], so this is just a matter of documentation in http://api.drupal.org/api/function/hook_mail_alter/7.

dale42’s picture

Assigned: Unassigned » dale42
dale42’s picture

This is $message array in DRUPAL-7-0-UNSTABLE-8 when a user is created.

Array
(
    [id] => user_register_admin_created
    [to] => receipient@example.com
    [from] => sender@example.com
    [language] => stdClass Object
        (
            [language] => en
            [name] => English
            [native] => English
            [direction] => 0
            [enabled] => 1
            [plurals] => 0
            [formula] => 
            [domain] => 
            [prefix] => 
            [weight] => 0
            [javascript] => 
        )

    [params] => Array
        (
            [account] => stdClass Object
                (
                    [uid] => 3
                    [name] => dale
                    [pass] => $P$Cha0L3u8gAM0BjrYQ2qxlilSsM17W61
                    [mail] => receipient@example.com
                    [theme] => 
                    [signature] => 
                    [created] => 1249429682
                    [access] => 1249429682
                    [login] => 0
                    [status] => 1
                    [timezone] => America/Los_Angeles
                    [language] => 
                    [picture] => 
                    [init] => receipient@example.com
                    [data] => a:1:{s:5:"block";a:0:{}}
                    [block] => Array
                        (
                        )

                    [roles] => Array
                        (
                            [2] => authenticated user
                        )

                    [password] => dale
                )

        )

    [subject] => This is the subject line
    [body] => Array
        (
            [0] => This is the message text
        )

    [headers] => Array
        (
            [MIME-Version] => 1.0
            [Content-Type] => text/plain; charset=UTF-8; format=flowed; delsp=yes
            [Content-Transfer-Encoding] => 8Bit
            [X-Mailer] => Drupal
            [Errors-To] => sender@example.com
            [Return-Path] => sender@example.com
            [Sender] => sender@example.com
            [From] => sender@example.com
        )

)
dale42’s picture

Status: Active » Needs review
FileSize
2.36 KB

Attached patch updates the function comments adding the 'params' and 'language' keys. Also updated some of the text to make it more compliant to the style guidelines.

/**
 * Perform alterations before an email is sent by Drupal. For example:
 * add a common site footer, an additional message header, or
 * modify the mesage text.
 *
 * @param $message
 *   An array containing the message data. Keys in this
 *   array include:
 *  - 'id':
 *     An id to identify the mail sent. Look at module source code
 *     or drupal_mail() for possible id values.
 *  - 'to':
 *     The address or addresses the message will be sent to. The
 *     formatting of this string must comply with RFC 2822.
 *  - 'from':
 *     The address the message will be marked as being from, which is
 *     either a custom address or the site-wide default email address.
 *  - 'subject':
 *     Subject of the email to be sent. This must not contain any newline
 *     characters, or the email may not be sent properly.
 *  - 'body':
 *     An array of lines containing the message to be sent. Drupal will format
 *     the line endings for RFC 2822.
 *  - 'headers':
 *     Associative array containing mail headers, such as From, Sender,
 *     MIME-Version, Content-Type, etc.
 *  - 'params': An array of parameters supplied by the caller of drupal_mail().
 *  - 'language': A language object supplied by the caller of drupal_mail().
 *
 * @see drupal_mail()
 */
dale42’s picture

Emma Jane did a quick look and gave feedback via IRC. Newly updated text:

/**
 * Perform alterations before an email is sent by Drupal. For example:
 * add a common site footer, an additional message header, or * modify the
 * mesage text.
 *
 * @param $message
 *   An array containing the message data. Keys in this array include:
 *  - 'id':
 *     An id identifying the message.
 *  - 'to':
 *     The address or addresses the message will be sent to. The
 *     formatting of this string must comply with RFC 2822.
 *  - 'from':
 *     The address the message will be marked as being from, which is
 *     either a custom address or the site-wide default email address.
 *  - 'subject':
 *     Subject of the email to be sent. This must not contain any newline
 *     characters, or the email may not be sent properly.
 *  - 'body':
 *     An array of lines containing the message to be sent. Message body line
 *     endings are formatted for RFC 2822 compliance.
 *  - 'headers':
 *     Associative array containing mail headers, such as From, Sender,
 *     MIME-Version, Content-Type, etc.
 *  - 'params': An array of parameters supplied by the caller of drupal_mail().
 *  - 'language': A language object supplied by the caller of drupal_mail().
 *
 * @see drupal_mail()
 */
awmckinley’s picture

FileSize
2.51 KB

I noticed that "mesage" is misspelled on the third line, and there seems to be a little line-break inconsistency. Otherwise, it makes perfect sense to me!

Here's the patch with "message" and line-breaks fixed.

* add a common site footer, an additional message header, or modify the
* message text.

and

*  - 'params':
*     An array of parameters supplied by the caller of drupal_mail().
*  - 'language':
*     A language object supplied by the caller of drupal_mail().

to match "'id':" line above.

Status: Needs review » Needs work

The last submitted patch failed testing.

dale42’s picture

Status: Needs work » Needs review
FileSize
2.51 KB

Rerolled patch with corrected text

awmckinley’s picture

Whoops! Sorry about that.

boombatower’s picture

+++ modules/system/system.api.php	5 Aug 2009 03:13:15 -0000
@@ -590,32 +590,35 @@ function hook_profile_alter(&$account) {
+ * add a common site footer, an additional message header, or * modify the

"site footer" seems odd, maybe just "footer".

Seems to be an extra * before modify.

dale42’s picture

Good catch, errant * removed. Text updated. 5th time a charm?

gpk’s picture

Well if we are being picky about layout etc... ;)

The initial function description should be on one line.

Then any additional info/examples can be in a block underneath.

This makes the layout better on pages such as http://api.drupal.org/api/file/modules/system/system.api.php/7.

"for example: add a common footer, an additional message header, or modify the message text."
I find this a bit confusing, because "message header" refers to the email headers, whereas "add a common footer" presumably means add text to the bottom of the body, i.e. is a specific example of modifying the message text. This was less confusing in the original IMO.

The problem with indentation in the original was merely that the first "bullet" line was missing a space. Otherwise it was all correct.

Suggest changing "An id identifying the message." to "The message identifier"

"Message body line endings are formatted for RFC 2822 compliance."
We have lost the important point that Drupal does the line ending formatting.

TBH I'm wondering whether the textual changes are worth doing in this issue, since we are now diverging from the documentation in drupal_mail(), on which the comments here seem to have been based originally, and also have diverged from the original intent of this issue.

Would it be better just to fix the original $params question, and the simple layout/formatting issue with the indent of the first bullet, and then pick up any textual improvements in a separate issue (and perhaps look at the documentation of hook_mail() at the same time)?

That might move things along more quickly.

dale42’s picture

FileSize
3.01 KB

@gpk: Regarding the initial function description being one line. I checked the existing api doc and there is no consistency, and I can't find a writing guideline reference. If you know where this is specified, would appreciate the URL. Since the first paragraph appears in the hook summary, I suspect the guideline is understandability. In this specific case, I agree with you.

Regarding simply adding the new parameters, it started that way and one of the doc team suggested further improvements so here we are :-)

Your comments made me take a closer look at the actual function. This description should be more accurate all round.

/**
 * Alter an email message created with the drupal_mail() function.
 *
 * hook_mail_alter() allows modification of email messages created and sent
 * with drupal_mail(). Usage examples include adding and/or changing message
 * text, message fields, and message headers.
 *
 * Email messages sent using functions other than drupal_mail() will not
 * invoke hook_mail_alter(). While Drupal core modules use drupal_mail() for
 * email messages, contributed modules using other functions will not be
 * subject to this hook.
 *
 * @param $message
 *   An array containing the message data. Keys in this array include:
 *  - 'id':
 *     The drupal_mail() id of the message.
 *  - 'to':
 *     The address or addresses the message will be sent to. The
 *     formatting of this string must comply with RFC 2822.
 *  - 'from':
 *     The address the message will be marked as being from, which is
 *     either a custom address or the site-wide default email address.
 *  - 'subject':
 *     Subject of the email to be sent. This must not contain any newline
 *     characters, or the email may not be sent properly.
 *  - 'body':
 *     An array of strings containing the message text. The message body is
 *     created by concatenating the individual array strings into a single text 
 *     string using "\n\n" as a separator.
 *  - 'headers':
 *     Associative array containing mail headers, such as From, Sender,
 *     MIME-Version, Content-Type, etc.
 *  - 'params':
 *     An array of optional parameters used to build the message before
 *     hook_mail_alter() is invoked.
 *  - 'language':
 *     The language object used to build the message before hook_mail_alter()
 *     is invoked.
 *
 * @see drupal_mail()
 */
jhodgdon’s picture

Status: Needs review » Patch (to be ported)

Doc header conventions are found here: http://drupal.org/node/1354

This documentation is good, and a vast improvement over the previous doc.

jhodgdon’s picture

Status: Patch (to be ported) » Reviewed & tested by the community

Sorry, finger slipped.

webchick’s picture

Status: Reviewed & tested by the community » Needs work

Wow! Great job on this!! Some comments...

+++ modules/system/system.api.php	5 Aug 2009 20:06:00 -0000
@@ -590,32 +590,45 @@ function hook_profile_alter(&$account) {
+ * Email messages sent using functions other than drupal_mail() will not
+ * invoke hook_mail_alter(). While Drupal core modules use drupal_mail() for
+ * email messages, contributed modules using other functions will not be
+ * subject to this hook.
  *

This sounds scary. Could you explain this more? Under what circumstances would a contrib module not be calling drupal_mail()?

+++ modules/system/system.api.php	5 Aug 2009 20:06:00 -0000
@@ -590,32 +590,45 @@ function hook_profile_alter(&$account) {
- *     An id to identify the mail sent. Look at module source code
- *     or drupal_mail() for possible id values.
- *   - 'to'
+ *     The drupal_mail() id of the message.

I actually think the old text was more helpful here. Or maybe not helpful, but it gave me a clue where to start looking.

Since this is the most important aspect of this function, we should probably take the opportunity to document it well here.

+++ modules/system/system.api.php	5 Aug 2009 20:06:00 -0000
@@ -590,32 +590,45 @@ function hook_profile_alter(&$account) {
+ *  - 'params':
+ *     An array of optional parameters used to build the message before
+ *     hook_mail_alter() is invoked.

What sort of parameters?

This review is powered by Dreditor.

dale42’s picture

Status: Needs work » Needs review
FileSize
3.23 KB

webchick: This sounds scary. Could you explain this more? Under what circumstances would a contrib module not be calling drupal_mail()?

I wouldn't attempt to second-guess a contrib author's decision process on why they did or didn't use drupal_mail()! :-) The text was added to make it clear there could be situations where messages could be sent without using hook_mail()/drupal_mail() Paragraph updated to read:

 * Email messages sent using functions other than drupal_mail() will not
 * invoke hook_mail_alter(). For example, a contributed module directly
 * calling the drupal_mail_send() or PHP mail() function will not invoke this
 * hook. All core modules use drupal_mail() for messaging, it is best practice
 * but not manditory in contributed modules.

For "id" I've added the sentence, "Look at module source code or drupal_mail() for possible id values.", back in.

For "params" I've used a variation of the language used in the hook_mail() description: "'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." If params is going to be documented, I'd recommend documenting it in hook_mail().

Dries’s picture

Status: Needs review » Fixed

I read through this and it looked great. Committed.

Status: Fixed » Closed (fixed)
Issue tags: -email

Automatically closed -- issue fixed for 2 weeks with no activity.