drupal_mail

Versions
5
drupal_mail($mailkey, $to, $subject, $body, $from = NULL, $headers = array())
6 – 7
drupal_mail($module, $key, $to, $language, $params = array(), $from = NULL, $send = TRUE)

Compose and optionally send an e-mail message.

Sending an e-mail works with defining an e-mail template (subject, text and possibly e-mail headers) and the replacement values to use in the appropriate places in the template. Processed e-mail templates are requested from hook_mail() from the module sending the e-mail. Any module can modify the composed e-mail message array using hook_mail_alter(). Finally drupal_mail_send() sends the e-mail, which can be reused if the exact same composed e-mail is to be sent to multiple recipients.

Finding out what language to send the e-mail with needs some consideration. If you send e-mail to a user, her preferred language should be fine, so use user_preferred_language(). If you send email based on form values filled on the page, there are two additional choices if you are not sending the e-mail to a user on the site. You can either use the language used to generate the page ($language global variable) or the site default language. See language_default(). The former is good if sending e-mail to the person filling the form, the later is good if you send e-mail to an address previously set up (like contact addresses in a contact form).

Taking care of always using the proper language is even more important when sending e-mails in a row to multiple users. Hook_mail() abstracts whether the mail text comes from an administrator setting or is static in the source code. It should also deal with common mail tokens, only receiving $params which are unique to the actual e-mail at hand.

An example:

<?php

function example_notify($accounts) {
foreach ($accounts as $account) {
$params['account'] = $account;
// example_mail() will be called based on the first drupal_mail() parameter.
      drupal_mail('example', 'notice', $account->mail, user_preferred_language($account), $params);
}
}

function example_mail($key, &$message, $params) {
$language = $message['language'];
$variables = user_mail_tokens($params['account'], $language);
switch($key) {
case 'notice':
$message['subject'] = t('Notification from !site', $variables, $language->language);
$message['body'][] = t("Dear !username\n\nThere is new content available on the site.", $variables, $language->language);
break;
}
}

?>

Parameters

$module A module name to invoke hook_mail() on. The {$module}_mail() hook will be called to complete the $message structure which will already contain common defaults.

$key A key to identify the e-mail sent. The final e-mail id for e-mail altering will be {$module}_{$key}.

$to The e-mail address or addresses where the message will be sent to. The formatting of this string must comply with RFC 2822. Some examples are: user@example.com user@example.com, anotheruser@example.com User <user@example.com> User <user@example.com>, Another User <anotheruser@example.com>

$language Language object to use to compose the e-mail.

$params Optional parameters to build the e-mail.

$from Sets From to this value, if given.

$send Send the message directly, without calling drupal_mail_send() manually.

Return value

The $message array structure containing all details of the message. If already sent ($send = TRUE), then the 'result' element will contain the success indicator of the e-mail, failure being already written to the watchdog. (Success means nothing more than the message being accepted at php-level, which still doesn't guarantee it to be delivered.)

▾ 6 functions call drupal_mail()

contact_mail_page_submit in modules/contact/contact.pages.inc
Process the site-wide contact page form submission.
contact_mail_user_submit in modules/contact/contact.pages.inc
Process the personal contact page form submission.
hook_watchdog in developer/hooks/core.php
Log an event message
system_send_email_action in modules/system/system.module
Implementation of a configurable Drupal action. Sends an email.
_update_cron_notify in modules/update/update.fetch.inc
Perform any notifications that should be done once cron fetches new data.
_user_mail_notify in modules/user/user.module
Conditionally create and send a notification email when a certain operation happens on the given user account.

Code

includes/mail.inc, line 82

<?php
function drupal_mail($module, $key, $to, $language, $params = array(), $from = NULL, $send = TRUE) {
  $default_from = variable_get('site_mail', ini_get('sendmail_from'));

  // Bundle up the variables into a structured array for altering.
  $message = array(
    'id'       => $module .'_'. $key,
    'to'       => $to,
    'from'     => isset($from) ? $from : $default_from,
    'language' => $language,
    'params'   => $params,
    'subject'  => '',
    'body'     => array()
  );

  // Build the default headers
  $headers = array(
    'MIME-Version'              => '1.0',
    'Content-Type'              => 'text/plain; charset=UTF-8; format=flowed; delsp=yes',
    'Content-Transfer-Encoding' => '8Bit',
    'X-Mailer'                  => 'Drupal'
  );
  if ($default_from) {
    // To prevent e-mail from looking like spam, the addresses in the Sender and
    // Return-Path headers should have a domain authorized to use the originating
    // SMTP server. Errors-To is redundant, but shouldn't hurt.
    $headers['From'] = $headers['Sender'] = $headers['Return-Path'] = $headers['Errors-To'] = $default_from;
  }
  if ($from) {
    $headers['From'] = $from;
  }
  $message['headers'] = $headers;

  // 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);

  // Concatenate and wrap the e-mail body.
  $message['body'] = is_array($message['body']) ? drupal_wrap_mail(implode("\n\n", $message['body'])) : drupal_wrap_mail($message['body']);

  // Optionally send e-mail.
  if ($send) {
    $message['result'] = drupal_mail_send($message);

    // Log errors
    if (!$message['result']) {
      watchdog('mail', 'Error sending e-mail (from %from to %to).', array('%from' => $message['from'], '%to' => $message['to']), WATCHDOG_ERROR);
      drupal_set_message(t('Unable to send e-mail. Please contact the site administrator if the problem persists.'), 'error');
    }
  }

  return $message;
}
?>

If you want to just send a freaking e-mail...

webchick - Tue, 2009-11-03 22:10

...like you could in Drupal 5, without going through this convoluted e-mail template registry system, you can call the drupal_mail_send() function directly.

For example:

<?php
$message
= array(
 
'to' => 'example@mailinator.com',
 
'subject' => t('Example subject'),
 
'body' => t('Example body'),
 
'headers' => array('From' => 'example@mailinator.com'),
);

drupal_mail_send($message);
?>

I'm sure someone from the i18n team will jump in here and explain why this is pure, unadulterated evil, but sometimes this is all you need. :P

Caveats:

- Because drupal_mail() isn't called, other modules will not be able to hook_mail_alter() your output, which can cause unexpected results.
- drupal_mail_send() is ignorant about which language to send the message in, so this needs to be figured out beforehand.
- You'll have to manually specify any other e-mail headers that are required ('Content-Type', etc.). These are normally taken care of for you by drupal_mail().

In the case where your module sends several different types of e-mails, and you want those e-mail templates to be editable (for example, user module's various registration notification/password reset/etc. e-mails), using hook_mail() is still the best way to go.

Login or register to post comments
 
 

All source code and documentation on this site is released under the terms of the GNU General Public License, version 2 and later. Drupal is a registered trademark of Dries Buytaert.