Take the 2-minute tour ×
Drupal Answers is a question and answer site for Drupal developers and administrators. It's 100% free, no registration required.

I would like to use the drupal_mail() function to send out emails but with a custom HTML template so that they are in keeping with my website design but I am a complete newbie to hooks and modules etc., so I'd appreciate some sort of explanation or beginners guide please.

I can create the template myself, I just need to know how to get drupal_mail() to use it. Thanks in advance.

share|improve this question

4 Answers 4

up vote 18 down vote accepted

If you are trying to send the mails via your custom module then you can follow the below mentioned guide. Say, I had one Module called "Commerce Canvas(commerce_canvas)" 1. First Alter the Drupal's mail function to support links and add other encoding types


/**
 * Implements hook_mail_alter()
 * @param string $message
 */
function commerce_canvas_mail_alter(&$message) {
    $headers = array(
        'MIME-Version' => '1.0',
        'Content-Type' => 'text/html; charset=iso-8859-1; format=flowed',
        'Content-Transfer-Encoding' => '8Bit',
        'X-Mailer' => 'Drupal',
    );
    foreach ($headers as $key => $value) {
        $message['headers'][$key] = $value;
    }
}
  1. Then next, hook the HOOK_mail in your module as

/**
 * Implements hook_mail()
 * @param string $key
 * @param string $message
 * @param unknown_type $params
 */
function commerce_canvas_mail($key, &$message, $params) {

    //Language Selection
    $options = array(
        'langcode' => $message['language']->language,
    );
    switch($key) {
        case "user_payment_notification" :
            $message['subject'] = isset($params['subject']) ? $params['subject'] : $message['subject'] = t('Payment recieved @site-name', array('@site-name' => variable_get('site_name', 'Express Canvas')), $options);
            $message['body'][] = isset($params['body']) ? $params['body'] : NULL;
            if (isset($params['headers']) && is_array($params['headers'])) {
                $message['headers'] += $params['headers'];
            }
            break;
    }
}


  1. Then you need to create a wrapper function to invoke the mail from your module.

function commerce_canvas_mail_send(array $values = array()) {
    $module = $values['module'];
    $key = $values['key'];
    $to = $values['to'];
    $from = $values['form'];
    $language = isset($values['lang']) ? $values['lang'] : language_default();
    $params = array(
        'subject' => $values['subject'],
        'body' => $values['body'],
    );
    if(array_key_exists('headers', $values)) {
        $params['headers'] = $values['headers']; //Assumed as an array
    }
    $send = TRUE;
    $mail = drupal_mail($module, $key, $to, $language, $params, $from, $send);
    if($mail['result']) {
        return TRUE;
    } else {
        $error_msg = 'Failed to send the email in commerce_canvas Module';
        watchdog('canvas-email', $error_msg, array(), WATCHDOG_ALERT);
        return FALSE;
    }
}

This function will send the email and as well as create debug messages if anything happens wrong. But still you won't be able to send the HTML mail because you need to extend the Drupal 7's default DefaultMailSystem with your own. So need to do as following,


class CommerceCanvasMailSystem extends DefaultMailSystem {
    /**
     * Concatenate and wrap the e-mail body for plain-text mails.
     *
     * @param $message
     *   A message array, as described in hook_mail_alter().
     *
     * @return
     *   The formatted $message.
     */
    public function format(array $message) {
        $message['body'] = implode("\n\n", $message['body']);
        return $message;
    }

    /**
     * Send an e-mail message, using Drupal variables and default settings.
     *
     * @see http://php.net/manual/en/function.mail.php
        * @see drupal_mail()
     *
     * @param $message
     *   A message array, as described in hook_mail_alter().
     * @return
     *   TRUE if the mail was successfully accepted, otherwise FALSE.
     */
    public function mail(array $message) {
        $mimeheaders = array();
        foreach ($message['headers'] as $name => $value) {
            $mimeheaders[] = $name . ': ' . mime_header_encode($value);
        }
        $line_endings = variable_get('mail_line_endings', MAIL_LINE_ENDINGS);
        return mail(
        $message['to'],
        mime_header_encode($message['subject']),
        // Note: e-mail uses CRLF for line-endings. PHP's API requires LF
        // on Unix and CRLF on Windows. Drupal automatically guesses the
        // line-ending format appropriate for your system. If you need to
        // override this, adjust $conf['mail_line_endings'] in settings.php.
        preg_replace('@\r?\n@', $line_endings, $message['body']),
        // For headers, PHP's API suggests that we use CRLF normally,
        // but some MTAs incorrectly replace LF with CRLF. See #234403.
        join("\n", $mimeheaders)
        );
    }
}


Next you need to register a new theme function that will call your custom template file in your hook_theme().


/**
 * Implements hook_theme();
 */
function commerce_canvas_theme($existing, $type, $theme, $path) {
  if($type == 'module') {
    return array(
      'tracking_code_email' => array(
        'variables' => array(
          'image_path' => NULL,
          'user' => NULL,
          'page' => NULL,
        ),
        'template' => 'commerce-canvas-tracking-code',
        'path' => drupal_get_path('module', 'commerce_canvas').'/theme',
      ),

    );
  }
}

Last you need to call this theme function in time of sending the email as,



function a_custom_function($params) {

$email_text_user = theme('tracking_code_email', array(
                    'image_path' => $base_url . '/' . drupal_get_path('module', 'commerce_canvas') . '/images',
                    'user' => null,
                    'page' => array(
                        'greet_text' => t('Thank you for your order at Express Canvas. Your order is ready and has shipped. You may track your order using FedEx tracking with your tracking number: '.$order->field_tracking_number['und']['0']['value'].''),

                    ),
                ));
$sent_to_user = commerce_canvas_mail_send($email_values_user);

}

These are the full snippet to handle the HTML email correctly in Drupal 7 thus in the hook_theme you can give your custom template.

share|improve this answer
    
Thank you very much for your answer - it is exactly what I asked for! Unfortunately now that I've seen the work involved and that there are modules out there that could do everything for me I think I'll wait before I rush into creating my own hook. However, I can't thank you enough for your answer because it is everything I asked for. I wish I could upvote more than once –  Andy Jan 8 '13 at 19:28
    
Great answer. I love the way Drupal makes basic things so simple ;-) –  artfulrobot Jul 16 '13 at 21:11

If you want to theme the outgoing mails with the help of custom templates, you should use the HTML Mail module.

Lets you theme your messages the same way you theme the rest of your website.

It works well with other modules, like Print, Mail mime, etc.

You have to install the Mail System module in order to use HTML mail.

share|improve this answer
1  
Please note that HTML Mail works with the Mail Mime module, not Mime Mail (Mime Mail and HTML Mail do similar things and override each other). –  Patrick Kenny Jan 7 '13 at 14:32
    
@PatrickKenny - Thank you for correcting :-) –  AjitS Jan 7 '13 at 14:41
    
@indrock Thank you for your answer too. Do you know if I can use the HTML Mail module to theme emails sent using php code? –  Andy Jan 8 '13 at 19:20

To send HTML e-mail, you can use the Mimemail module. Once it's set up and configured, you can simply prepare the template, name it mimemail-message.tpl.php, drop it in your theme directory, and it will automatically be applied to all outgoing e-mail (assuming you have configured all mail to be sent out by Mimemail).

Setting up the module is probably easier than overriding drupal_mail().

share|improve this answer
    
Thank you for your answer! Can I send emails using PHP with this module? If so, could you show me how please? –  Andy Jan 6 '13 at 15:36
    
Mimemail, when combined with the Mail System module, will take over all e-mails sent by the site. Thus, all e-mails sent by any module, including custom modules, will automatically be sent out through Mimemail. If you want to limit which e-mails are affected, you can use the Mail System's modules configuration options. –  Patrick Kenny Jan 7 '13 at 0:35
1  
I think this's not what Andy asked exactly. True, you will need Mimemail module or roll your own MailSystem to do this but may be Andy asked about how to theme the email body which should be done in hook_mail() function and a theme('my_custom_theme') call in it ? –  Ayesh K Jan 7 '13 at 5:09
1  
I think @Andy wants to know if the Mimemail module has a function that can be called to send emails. –  kiamlaluno Jan 7 '13 at 14:18
    
@kiamlaluno You are correct, this is what I would like to know please –  Andy Jan 8 '13 at 19:06

Example usage:

    $module = 'module_name';
    $key = 'key';
    $language = language_default();
    $params = array();
    $from = NULL;
    $send = FALSE;
    $message = drupal_mail($module, $key, $email, $language, $params, $from, $send);

    $message['subject'] = $subject;
    $message['body'] = array();
    $message['body'][] = $line1;
    $message['body'][] = $line2;

    // Retrieve the responsible implementation for this message.
    $system = drupal_mail_system($module, $key);

    // Format the message body.
    $message = $system->format($message);

    // Send e-mail.
    $message['result'] = $system->mail($message);
share|improve this answer
3  
It is always recommended to send the mails using drupal_mail() rather than $system->mail(.. in order to use the hook_mail_alter function (which only works for mails sent using drupal_mail(). –  AjitS Jan 7 '13 at 7:57
    
I am fully aware of how to use the function (syntax/code wise), I would just like to know how to make a theme so that I can apply to all emails sent with drupal_mail etc, but thank you anyway –  Andy Jan 8 '13 at 19:11

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.