如何使用drupal_mail()通过自定义模板发送电子邮件


31

我想使用该drupal_mail()功能发送电子邮件,但使用自定义HTML模板,以使其与我的网站设计保持一致,但是我是钩子和模块等的完全新手,因此,我希望您提供一些解释或请初学者指导。

我可以自己创建模板,我只需要知道如何drupal_mail()使用它即可。

Answers:


39

如果您尝试通过自定义模块发送邮件,则可以遵循以下提到的指南。说,我有一个名为“商务画布(commerce_canvas)”的模块。1.首先更改Drupal的邮件功能以支持链接并添加其他编码类型


/**
 * 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. 然后,将HOOK_mail挂接到模块中

/**
 * 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. 然后,您需要创建一个包装器函数来调用模块中的邮件。

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

如果发生任何错误,此功能将发送电子邮件并创建调试消息。但是仍然不能发送HTML邮件,因为您需要用自己的扩展Drupal 7的默认DefaultMailSystem。因此需要执行以下操作,


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


接下来,您需要注册一个新的主题函数,该函数将在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',
      ),

    );
  }
}

最后,您需要在发送电子邮件时调用此主题功能,



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

}

这些是在Drupal 7中正确处理HTML电子邮件的完整代码段,因此在hook_theme中,您可以提供自定义模板。


1
非常感谢您的回答-这正是我要的!不幸的是,现在我已经看到了所涉及的工作,并且那里有可以为我做所有事情的模块,我想我会等着急于创建自己的钩子。但是,对于您的回答,我非常感谢,因为这就是我所要求的一切。我希望我能给予好评不止一次
安迪

11
好答案。我喜欢Drupal使基本事情变得如此简单的方式;-)
artfulrobot

1
But still you won't be able to send the HTML mail..., 对。
Ejaz 2014年

@Ejay,是的,可以。做到这一点。
Aneek Mukhopadhyay 2014年

1
记录:使用以下模块更容易:drupal.org/project/simple_mail
2015年

11

如果要在自定义模板的帮助下将外发邮件设置为主题,则应使用HTML Mail模块。

让您以与主题网站其余部分相同的方式来主题化您的消息。

它与其他模块(例如PrintMail mime等)很好地配合使用。

您必须安装邮件系统模块才能使用HTML邮件。


1
请注意,HTML Mail与Mail Mime模块一起使用,而不与Mime Mail一起使用(Mime Mail和HTML Mail做类似的事情,并且彼此替代)。
Patrick Kenny 2013年

@indrock谢谢您的回答。您知道我是否可以使用HTML Mail模块将使用php代码发送的主题电子邮件作为主题吗?
安迪

4

用法示例:

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

4
这是我们推荐发送使用电子邮件drupal_mail(),而不是$system->mail(..为了使用hook_mail_alter功能(该功能仅适用于发送邮件使用drupal_mail()
AjitS

我完全知道如何使用该功能(语法/代码明智),我只想知道如何制作主题,以便可以将其应用于以此类推的所有电子邮件drupal_mail,但无论如何还是要谢谢
Andy

我正在使用此代码,它的工作正常,但有一封空白邮件已发送。
vishal sirsodiya

3

要发送HTML电子邮件,可以使用Mimemail模块。设置和配置好模板之后,您只需准备模板,命名模板,mimemail-message.tpl.php将其放在主题目录中,它就会自动应用于所有外发电子邮件(假设您已配置所有邮件由Mimemail发送) 。

设置模块可能比覆盖容易drupal_mail()


谢谢您的回答!我可以在此模块中使用PHP发送电子邮件吗?如果是这样,您能告诉我如何吗?
安迪

当与邮件系统模块结合使用时,Mimemail将接管该站点发送的所有电子邮件。因此,任何模块发送的所有电子邮件(包括自定义模块)都将自动通过Mimemail发送出去。如果要限制受影响的电子邮件,可以使用邮件系统的模块配置选项。
Patrick Kenny

1
我认为这不是Andy确切要求的。是的,您将需要Mimemail模块或滚动您自己的MailSystem来执行此操作,但是Andy可能会询问如何为电子邮件正文设置主题,这应该在hook_mail()函数中进行,并在其中调用theme('my_custom_theme')?
AyeshK 2013年

1
我认为@Andy想知道Mimemail模块是否具有可以调用以发送电子邮件的功能。
kiamlaluno

@kiamlaluno你是正确的,这是我想知道的
Andy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.