function drupal_mail_system

You are here

7 mail.inc drupal_mail_system($module, $key)
8 mail.inc drupal_mail_system($module, $key)

Returns an object that implements the MailSystemInterface interface.

Allows for one or more custom mail backends to format and send mail messages composed using drupal_mail().

An implementation needs to implement the following methods:

  • format: Allows to preprocess, format, and postprocess a mail message before it is passed to the sending system. By default, all messages may contain HTML and are converted to plain-text by the DefaultMailSystem implementation. For example, an alternative implementation could override the default implementation and additionally sanitize the HTML for usage in a MIME-encoded e-mail, but still invoking the DefaultMailSystem implementation to generate an alternate plain-text version for sending.
  • mail: Sends a message through a custom mail sending engine. By default, all messages are sent via PHP's mail() function by the DefaultMailSystem implementation.

The selection of a particular implementation is controlled via the variable 'mail_system', which is a keyed array. The default implementation is the class whose name is the value of 'default-system' key. A more specific match first to key and then to module will be used in preference to the default. To specify a different class for all mail sent by one module, set the class name as the value for the key corresponding to the module name. To specify a class for a particular message sent by one module, set the class name as the value for the array key that is the message id, which is "${module}_${key}".

For example to debug all mail sent by the user module by logging it to a file, you might set the variable as something like:

array(
  'default-system' => 'DefaultMailSystem',
  'user' => 'DevelMailLog',
);

Finally, a different system can be specified for a specific e-mail ID (see the $key param), such as one of the keys used by the contact module:

array(
  'default-system' => 'DefaultMailSystem',
  'user' => 'DevelMailLog',
  'contact_page_autoreply' => 'DrupalDevNullMailSend',
);

Other possible uses for system include a mail-sending class that actually sends (or duplicates) each message to SMS, Twitter, instant message, etc, or a class that queues up a large number of messages for more efficient bulk sending or for sending via a remote gateway so as to reduce the load on the local server.

Parameters

$module: The module name which was used by drupal_mail() to invoke hook_mail().

$key: A key to identify the e-mail sent. The final e-mail ID for the e-mail alter hook in drupal_mail() would have been {$module}_{$key}.

Return value

MailSystemInterface

2 calls to drupal_mail_system()
drupal_mail in includes/mail.inc
Composes and optionally sends an e-mail message.
SimpleTestMailCaptureTestCase::testMailSend in modules/simpletest/simpletest.test
Test to see if the wrapper function is executed correctly.

File

includes/mail.inc, line 258
API functions for processing and sending e-mail.

Code

function drupal_mail_system($module, $key) {
  $instances = &drupal_static(__FUNCTION__, array());

  $id = $module . '_' . $key;

  $configuration = variable_get('mail_system', array('default-system' => 'DefaultMailSystem'));

  // Look for overrides for the default class, starting from the most specific
  // id, and falling back to the module name.
  if (isset($configuration[$id])) {
    $class = $configuration[$id];
  }
  elseif (isset($configuration[$module])) {
    $class = $configuration[$module];
  }
  else {
    $class = $configuration['default-system'];
  }

  if (empty($instances[$class])) {
    $interfaces = class_implements($class);
    if (isset($interfaces['MailSystemInterface'])) {
      $instances[$class] = new $class();
    }
    else {
      throw new Exception(t('Class %class does not implement interface %interface', array('%class' => $class, '%interface' => 'MailSystemInterface')));
    }
  }
  return $instances[$class];
}

Comments

If you just need to send a very simple email (for example to notify an administrator of an error), you can use the following code. Note that this technique does not interface with the translation system, with the mail alter system, or anything else really. It just sends an email. For more complicated use cases you'll need to use drupal_mail().

<?php
$my_module
= 'foo';
$my_mail_token = 'bar';
$from = variable_get('system_mail', 'organization@example.com');
$message = array(
 
'id' => $my_module . '_' . $my_mail_token,
 
'to' => 'test@example.com',
 
'subject' => 'test',
 
'body' => 'test',
 
'headers' => array(
   
'From' => $from,
   
'Sender' => $from,
   
'Return-Path' => $from,
  ),
);
$system = drupal_mail_system($my_module, $my_mail_token);
if (
$system->mail($message)) {
 
// Success.
}
else {
 
// Failure.
}
?>

In order to make sure that your message body will be compatible with all Mail Systems make sure to call the Mail System's format method. (This especially applies to array based multi-line emails when using the DefaultMailSystem.)

Here is a modified example that is much safer and not significantly more complicated.

<?php
$my_module
= 'foo';
$my_mail_token = 'bar';
$from = variable_get('system_mail', 'organization@example.com');
$message = array(
 
'id' => $my_module . '_' . $my_mail_token,
 
'to' => 'test@example.com',
 
'subject' => 'test',
 
'body' => 'test',
 
'headers' => array(
   
'From' => $from,
   
'Sender' => $from,
   
'Return-Path' => $from,
  ),
);
$system = drupal_mail_system($my_module, $my_mail_token);

// The format function must be called before calling the mail function.
$message = $system->format($message);

if (

$system->mail($message)) {
 
// Success.
}
else {
 
// Failure.
}
?>

In message array:

<?php
$message
= array(
 
'id' => $my_module . '_' . $my_mail_token,
 
'to' => 'test@example.com',
 
'subject' => 'test',
 
'body' => 'test',
 
'headers' => array(
   
'From' => $from,
   
'Sender' => $from,
   
'Return-Path' => $from,
  ),
);
?>

Body must be array too

<?php
'body' => array('test')
?>

Otherwise, you'll get

Warning: implode() [function.implode]: Invalid arguments passed in DefaultMailSystem->format() (line 23 of /home/u59384/idea.rick.ru/www/modules/system/system.mail.inc).

Because "format" method use implode() to get body strings together.

Thanks for the help! I made a step-by-step snippet for Drupal 7 that's ready to go:

https://gist.github.com/2844687

<?php
/**
* Sends a simple email.
* [or] Tested on 2012-05-31 using Drupal 7.12
*
* Usage:
* 1) Paste all the below code into your module or include
* 2) Configure the two @FIXME's.
* 3) Visit /_custom_simple_mail to get an email.
*
* Credits:
* @see http://api.drupal.org/api/drupal/includes%21mail.inc/function/drupal_mail_system/7#comment-17489
* @see http://www.midwesternmac.com/blogs/jeff-geerling/wrapper-function-simple
*
*/

/**
* Send a simple email to specified recipient.
*
* @param string $message_subject
* @param string $message_body
*/

function _custom_simple_mail($message_subject, $message_body) {
 
// @FIXME Set this value to your email address.
 
$my_email = 'myname@gmail.com';
 
 
// These value can remain empty.
 
$my_module = '';
 
$my_mail_token = '';
 
 
$from = variable_get('system_mail', $my_email);
 
$message = array(
   
'id' => $my_module . '_' . $my_mail_token,
   
'to' => $my_email,
   
'subject' => $message_subject,
   
'body' => array($message_body),
   
'headers' => array(
     
'From' => $from,
     
'Sender' => $from,
     
'Return-Path' => $from,
    ),
  );
 
$system = drupal_mail_system($my_module, $my_mail_token);

 

// The format function must be called before calling the mail function.
 
$message = $system->format($message);

  if (

$system->mail($message)) {
   
drupal_set_message('_custom_simple_mail SUCCESS');
  }
  else {
   
drupal_set_message('_custom_simple_mail FAILURE');
  }
}

/**
* Implements HOOK_init to test _custom_simple_mail.
*
* @FIXME Change 'mymodule' to your actual enabled custom module's machine name.
*/
function mymodule_init() {
  if (
arg(0) == '_custom_simple_mail' ) {
   
drupal_set_message('Testing _custom_simple_mail()...');
    if (
function_exists('_custom_simple_mail')) {
     
_custom_simple_mail('Test message subject', 'Test message body');
    } else {
     
drupal_set_message('<strong>Oops!</strong> Function _custom_simple_mail() was not found.', 'error');
    }
  }
}
?>

For some reason, the headers from http://api.drupal.org/api/drupal/includes!mail.inc/function/drupal_mail/7 aren't included, atleast not in my module, so I added them manually, solving the problem with characters like Æ, Ø and Å.

My $message array looks like this:

<?php
  $message
= array(
   
'id' => $my_module . '_' . $my_mail_token,
   
'to' => $my_email,
   
'subject' => $message_subject,
   
'body' => array($message_body),
   
'headers' => array(
     
'From' => $from,
     
'Sender' => $from,
     
'Return-Path' => $from,
     
'MIME-Version' => '1.0',
     
'Content-Type' => 'text/plain; charset=UTF-8; format=flowed; delsp=yes',
     
'Content-Transfer-Encoding' => '8Bit',
     
'X-Mailer' => 'Drupal',
    ),
  );
?>