2015-04-19 16:46:59 +02:00

407 lines
11 KiB
Plaintext

<?php
/**
* @file
* Enables Drupal to send email directly through Mandrill.
*
* Overriding mail handling in Drupal to make Mandrill the default
* transport layer, requires to change the mail_system variable's
* default value array('default-system' => 'DefaultMailSystem').
* This module uses array('default-system' => 'MailChimpMandrillMailSystem').
*/
define('MANDRILL_QUEUE', 'mandrill_queue');
define('MANDRILL_EMAIL_REGEX', '/^\s*(.+?)\s*<\s*([^>]+)\s*>$/');
/**
* Implements hook_help().
*/
function mandrill_help($path, $arg) {
switch ($path) {
case 'admin/help#mandrill':
return t('Allow for site emails to be sent through Mandrill.');
}
}
/**
* Implements hook_menu().
*/
function mandrill_menu() {
$items = array();
$items['admin/config/services/mandrill'] = array(
'title' => 'Mandrill',
'page callback' => 'drupal_get_form',
'page arguments' => array('mandrill_admin_settings'),
'access arguments' => array('administer mandrill'),
'description' => 'Send emails through the Mandrill transactional email service.',
'file' => 'mandrill.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
$items['admin/config/services/mandrill/settings'] = array(
'title' => 'Settings',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => 0,
);
$items['admin/config/services/mandrill/test'] = array(
'title' => 'Send test email',
'page callback' => 'drupal_get_form',
'page arguments' => array('mandrill_test_form'),
'access callback' => 'mandrill_test_access',
'description' => 'Send a test email using the Mandrill API.',
'file' => 'mandrill.admin.inc',
'type' => MENU_LOCAL_TASK,
'weight' => 1,
);
return $items;
}
/**
* Access callback for sending test email.
*
* @return bool
* True if current user has access to send test messages
*/
function mandrill_test_access() {
$a = user_access('administer mandrill');
$b = variable_get('mandrill_api_key');
return $a & !empty($b);
}
/**
* Implements hook_permission().
*/
function mandrill_permission() {
return array(
'administer mandrill' => array(
'title' => t('Administer Mandrill'),
'description' => t('Perform administration tasks for the Mandrill email service.'),
"restrict access" => TRUE,
),
);
}
/**
* Implements hook_cron_queue_info().
*/
function mandrill_cron_queue_info() {
$queues = array();
$queues[MANDRILL_QUEUE] = array(
'worker callback' => 'mandrill_queue_worker_mailsend',
'time' => variable_get('mandrill_queue_worker_timeout', 15),
);
return $queues;
}
/**
* Sends a queued email.
* @see mandrill_cron_queue_info()
*/
function mandrill_queue_worker_mailsend($data) {
// Send the message stored in the queue item.
mandrill_mailsend(
$data['message'],
$data['function'],
$data['args']
);
}
/**
* Implements hook_mail().
*/
function mandrill_mail($key, &$message, $params) {
if ($key == 'test') {
$message['subject'] = $params['subject'];
$message['body'] = $params['body'];
if ($params['include_attachment']) {
$message['attachments'][] = drupal_realpath('misc/druplicon.png');
$message['body'] .= ' ' . t('The Drupal icon is included as an attachment to test the attachment functionality.');
}
}
}
/**
* Abstracts sending of messages, allowing queueing option.
*
* @param array $message
* A message array formatted for Mandrill's sending API, plus 2 additional
* indexes for the send_function and an array of $args, if needed by the send
* function.
*
* @return bool
* TRUE if no exception thrown
*/
function mandrill_mailsend($message, $function, $args = array()) {
try {
if (!function_exists($function)) {
watchdog('mandrill', 'Error sending email from %from to %to. Function %function not found.',
array(
'%from' => $message['from_email'],
'%to' => $message['to'],
'%function' => $function,
),
WATCHDOG_ERROR
);
return FALSE;
}
$params = array($message) + $args;
$results = call_user_func_array($function, $params);
foreach ($results as $result) {
// Allow other modules to react based on a send result.
module_invoke_all('mandrill_mailsend_result', $result);
switch ($result['status']) {
case "error":
case "invalid":
case "rejected":
$to = isset($result['email']) ? $result['email'] : 'recipient';
$status = isset($result['status']) ? $result['status'] : 'message';
$error_message = isset($result['message']) ? $result['message'] : 'no message';
watchdog('mandrill', 'Failed sending email from %from to %to. @status: @message',
array(
'%from' => $message['from_email'],
'%to' => $to,
'@status' => $status,
'@message' => $error_message,
),
WATCHDOG_ERROR
);
return FALSE;
case "queued":
watchdog('mandrill', 'Email from %from to %to queued by Mandrill App.',
array(
'%from' => $message['from_email'],
'%to' => $result['email'],
),
WATCHDOG_INFO
);
break;
}
}
return TRUE;
}
catch (MandrillException $e) {
watchdog('mandrill', 'Error sending email from %from to %to. @code: @message',
array(
'%from' => $message['from_email'],
'%to' => $message['to'],
'@code' => $e->getCode(),
'@message' => $e->getMessage(),
),
WATCHDOG_ERROR
);
return FALSE;
}
}
/**
* The actual function that calls the API send message.
*
* This is the default function used by mandrill_mailsend().
*
* @array $message
* Associative array containing message data.
*
* @return array
* Results of sending the message.
*
* @throws MandrillException
*/
function mandrill_sender_plain($message) {
if ($mailer = mandrill_get_api_object()) {
return $mailer->messages_send($message);
}
else {
throw new MandrillException('Missing API key.');
}
}
/**
* Return Mandrill API object for communication with the mailchimp server.
*
* @param bool $reset
* Pass in TRUE to reset the statically cached object.
* @param string $classname
* The Mandrill class to use for sending emails. Passing a parameter allows
* the class used to be overridden, E.g., for tests.
*
* @throws MandrillException
*
* @return Mandrill|bool
* Mandrill Object upon success
* FALSE if variable_get('mandrill_api_key') is unset
*/
function mandrill_get_api_object($reset = FALSE, $classname = 'DrupalMandrill') {
$api =& drupal_static(__FUNCTION__, NULL);
if ($api === NULL || $reset === TRUE) {
$api_key = variable_get('mandrill_api_key', '');
$api_timeout = variable_get('mandrill_api_timeout', 60);
if (empty($api_key)) {
return FALSE;
}
$api = new $classname($api_key, $api_timeout);
}
return $api;
}
/**
* Display the names of the modules that are using Mailsystem.
*
* This is consistent with with Mailsystem's display. In the future, if
* Mailsystem were to provide an API for their labeling, that should be used.
*
* @return array
* Array of all module names indexing to their "display" names,
* and some special items for non-module values like null, default-system,
* and some clarification talked onto the end of the Mandrill module's name.
*/
function mandrill_get_module_key_names() {
$name_array = array(
'' => '--none--',
'default-system' => "Site-wide default",
);
$descriptions = array();
foreach (system_rebuild_module_data() as $item) {
if ($item->status) {
$descriptions[$item->name] = (empty($item->info['package']) ? '' : $item->info['package']) . ' » ' . t('!module module', array('!module' => $item->info['name']));
}
}
asort($descriptions);
$mailsystem_settings = mailsystem_get();
unset($mailsystem_settings['default-system']);
foreach ($mailsystem_settings as $id => $class) {
// Separate $id into $module and $key.
$module = $id;
while ($module && empty($descriptions[$module])) {
// Remove a key from the end.
$module = implode('_', explode('_', $module, -1));
}
// If an array key of the $mail_system variable is neither "default-system"
// nor begins with a module name, then it should be unset.
if (empty($module)) {
// This shouldn't happen.
}
// Set $title to the human-readable module name.
$title = preg_replace('/^.* » /', '', $descriptions[$module]);
if ($key = substr($id, strlen($module) + 1)) {
$title .= " ($key key)";
}
$name_array[$id] = $title;
}
return $name_array;
}
/**
* Get a list of mandrill template objects.
*
* @return array
* An of available templates with complete data or NULL if none are available.
*/
function mandrill_get_templates() {
// Only show the template settings if the mandrill api can be called.
$templates = NULL;
try {
$mailer = mandrill_get_api_object();
$templates = $mailer->templates_list();
}
catch (MandrillException $e) {
drupal_set_message(t('Mandrill: %message', array('%message' => check_plain($e->getMessage()))), 'error');
watchdog_exception('mandrill', $e);
}
return $templates;
}
/**
* Get a list of subaccounts.
*/
function mandrill_get_subaccounts() {
$subaccounts = array();
try {
$mandrill = mandrill_get_api_object();
$subaccounts = $mandrill->subaccounts();
}
catch (MandrillException $e) {
drupal_set_message(t('Mandrill: %message', array('%message' => check_plain($e->getMessage()))), 'error');
watchdog_exception('mandrill', $e);
}
return $subaccounts;
}
/**
* Helper to return a comma delimited list of mail keys to not log content for.
*
* @return string
* a comma delimited list of mail keys
*/
function mandrill_mail_key_blacklist() {
return variable_get('mandrill_mail_key_blacklist', 'user_password_reset');
}
/**
* Helper to generate an array of recipients.
*
* @param mixed $to
* a comma delimited list of email addresses in 1 of 2 forms:
* user@domain.com
* any number of names <user@domain.com>
*
* @return array
* array of email addresses
*/
function mandrill_get_to($to) {
$recipients = array();
$to_array = explode(',', $to);
foreach ($to_array as $email) {
if (preg_match(MANDRILL_EMAIL_REGEX, $email, $matches)) {
$recipients[] = array(
'email' => $matches[2],
'name' => $matches[1],
);
}
else {
$recipients[] = array('email' => $email);
}
}
return $recipients;
}
/**
* Determine if mail should be processed asynchronously.
*
* @return bool
* True if asyncronous processing is enabled
*/
function mandrill_process_async() {
return variable_get('mandrill_process_async', FALSE);
}
/**
* Returns an array containing the from information for a Mandrill message.
*
* @return array
* array(
* 'email' => 'admin@example.com',
* 'name' => 'My Site',
* )
*/
function mandrill_from() {
$default_from = variable_get('site_mail', ini_get('sendmail_from'));
$email = variable_get('mandrill_from', $default_from);
$name = variable_get('mandrill_from_name', variable_get('site_name'));
return array(
'email' => $email,
'name' => $name,
);
}