Wrapper function for simple drupal_mail() sending in Drupal 7

Email is such a pain (I should know, as I'm currently working on a site that's sending 10-20,000 emails per day to 40,000+ users. Spam prevention, SPF records, bounce handling, abuse reports, deliverability, send rates, etc. are all huge hassles that must be dealt with when handling more than a few hundred emails a day.

For testing, I often like throwing in a quick bit of code to send me or someone else a simple email with a few bits of information when something happens on the site, or to test email addresses or formatting. Therefore I like having a quick one-line function call to send an email. In Drupal 6, there was a handy drupal_mail_send() function that would use some default settings and allow you to quickly shoot off a simple email (not translated, not pluggable, etc., but easy to implement).

Drupal 7 did away with that function, and instead, the simplest way to send an email in Drupal 7 requires some 20+ lines of code. Not fun when I'm trying to set up a few quick one-off emails that just need a 'from', 'to', 'subject', and 'message'. For these emails, I don't care about message translation, mail altering, etc. I just want an email shot off as quickly and simply as possible.

So, I wrote a quick wrapper function that I've placed in a custom.module that lets me just throw in the four default parameters, and sends an email. It doesn't hook into any of the system's mail handling capabilities, and isn't super-robust, but it lets me develop much faster:

<?php
/**
 * Simple wrapper function for drupal_mail() to avoid extraneous code.
 */
function custom_drupal_mail($from = 'default_from', $to, $subject, $message) {
 
$my_module = 'custom';
 
$my_mail_token = microtime();
  if (
$from == 'default_from') {
   
// Change this to your own default 'from' email address.
   
$from = variable_get('system_mail', 'My Email Address <example@example.com>');
  }
 
$message = array(
   
'id' => $my_module . '_' . $my_mail_token,
   
'to' => $to,
   
'subject' => $subject,
   
'body' => array($message),
   
'headers' => array(
     
'From' => $from,
     
'Sender' => $from,
     
'Return-Path' => $from,
    ),
  );
 
$system = drupal_mail_system($my_module, $my_mail_token);
 
$message = $system->format($message);
  if (
$system->mail($message)) {
    return
TRUE;
  }
  else {
    return
FALSE;
  }
}
?>

Now, sending an email is as simple as:

<?php
  custom_drupal_mail
('default_from', 'John Doe <jdoe@example.com>', 'Test Email Subject', 'Test Email Body.');
?>

[Edit: Updated with some suggestions from API comments and RichardLynch on IRC. Additionally, if you want to find a simple way to send HTML emails with Drupal and a custom module, see this answer about HTML email sending in D7 on Stack Exchange].

Jeff Geerling is the owner of Midwestern Mac, LLC. He is an active contributor in the Drupal community, and has primarily been a Mac user since the 1990s. He is the author of Ansible for DevOps, and learns and uses whatever tool or language is best for the job.

Comments

Gábor Hojtsy's picture

This assumes that you handle all message localization yourself out of this function. Like figure out which language to use for a user and translating the text to that language. The core mail system delegates that to the {module}_mail() callbacks. You certainly can't skip that code, unless, obviously its custom code you are not about to share with the international community.

Jeff Geerling's picture

I guess I wasn't clear in the post, but this is so that I can quickly send administrative emails to myself or others on the development team from the server; for this, we're all speaking the site language, and don't need to worry about translation, mail altering, etc.

I just wanted a really quick and easy way to fire off a Drupal email in code for testing. And it seems like many others I've encountered would like the same. Not to mention, this function would be fine for most small community Drupal sites, where translation isn't on the docket. (not recommended, but still hundreds of times more memorizable).

Personal site: jeffgeerling.com.

mobydick426's picture

Thanks for this.

When I try to use your function, the body is always empty.

Have you some idea why please ?

Oren's picture

This didn't work for me, but following the link to drupal.org, I was able to find a working snippet. Here's what worked for me:

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');
    }
  }
}

Marc Linn's picture

The original code posted here (with edits I guess) worked great for me! Just starting w/ D7, going through all the "worked great before but no longer" issues... this helps a lot, thank you.

nooshin's picture

how to send html emails? I mean how can I set text/html header for my email in this function?

Puscasu Adrian's picture

The original code worked great after I uninstalled :
Emogrifier
Pathologic
Echo
Include
Transliteration
Some of the above modules made the body content full of garbage.

Add new comment