mimemail.module in Mime Mail 6
Same filename and directory in other branches
Component module for sending MIME-encoded e-mails.
File
mimemail.moduleView source
<?php
/**
* @file
* Component module for sending MIME-encoded e-mails.
*/
/**
* Implements hook_menu().
*/
function mimemail_menu() {
$path = drupal_get_path('module', 'mimemail') . '/includes';
$items['admin/settings/mimemail'] = array(
'title' => 'Mime Mail',
'description' => 'HTML E-mail settings',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'mimemail_admin_settings',
),
'access arguments' => array(
'administer site configuration',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'mimemail.admin.inc',
'file path' => $path,
);
$items['mimemail'] = array(
'page callback' => 'mimemail_post',
'access callback' => 'mimemail_incoming_access',
'type' => MENU_CALLBACK,
'file' => 'mimemail.incoming.inc',
'file path' => $path,
);
return $items;
}
/**
* Access callback to process incoming messages.
*/
function mimemail_incoming_access() {
return variable_get('mimemail_incoming', FALSE);
}
/**
* Implements hook_perm().
*/
function mimemail_perm() {
return array(
'send arbitrary files - Warning: has security implications!',
'edit mimemail user settings',
);
}
/**
* Implements hook_user().
*/
function mimemail_user($op, &$edit, &$account, $category = '') {
if ($op == 'form' && $category == 'account') {
$form = array();
$form['mimemail'] = array(
'#type' => 'fieldset',
'#title' => t('Email settings'),
'#weight' => 5,
'#collapsible' => TRUE,
'#access' => user_access('edit mimemail user settings'),
);
$form['mimemail']['mimemail_textonly'] = array(
'#type' => 'checkbox',
'#title' => t('Plaintext email only'),
'#default_value' => isset($account->mimemail_textonly) ? $account->mimemail_textonly : 0,
'#description' => t('Check this option if you do not wish to receive email messages with graphics and styles'),
);
return $form;
}
return;
}
/**
* Implements hook_theme().
*/
function mimemail_theme() {
module_load_include('theme.inc', 'mimemail', 'theme/mimemail');
return mimemail_theme_theme();
}
/**
* Implements hook_mail().
*
* Set's the message subject and body as configured in the $settings of the action.
*/
function mimemail_mail($key, &$message, $params) {
$account = $params['account'];
$variables = array(
'%site_name' => variable_get('site_name', 'Drupal'),
'%username' => $account->name,
);
// Replace variables.
if (isset($params['node']) && is_object($params['node'])) {
$node = $params['node'];
$variables += array(
'%author' => $account->mail,
'%uid' => $node->uid,
'%node_url' => url('node/' . $node->nid, array(
'absolute' => TRUE,
)),
'%node_type' => $node->type,
'%title' => $node->title,
'%teaser' => $node->teaser,
'%body' => $node->body,
);
}
// Prepare the array of the attachments.
$attachments = array();
$attachments_string = trim($params['attachments']);
if (!empty($attachments_string)) {
$attachment_lines = array_filter(explode("\n", trim($attachments_string)));
foreach ($attachment_lines as $key => $attachment_line) {
$attachment = explode(':', trim($attachment_line), 2);
$attachments[] = array(
'filepath' => $attachment[1],
'filemime' => $attachment[0],
);
}
}
// We handle different address headers if set.
$address_headers = array(
'cc' => 'Cc',
'bcc' => 'Bcc',
'reply_to' => 'Reply-to',
);
foreach ($address_headers as $param_key => $address_header) {
$params[$param_key] = empty($params[$param_key]) ? array() : explode(',', $params[$param_key]);
if (!empty($params[$param_key])) {
foreach ($params[$param_key] as $key => $address) {
$params[$param_key][$key] = strtr(str_replace(array(
"\r",
"\n",
), '', trim($address)), $variables);
}
$message['headers'][$address_header] = implode(',', $params[$param_key]);
}
}
$message['to'] = strtr($message['to'], $variables);
$message['subject'] = strtr($params['subject'], $variables);
$message['body'][] = check_markup(strtr($params['message_html'], $variables), $params['message_html_filter'], FALSE);
$message['params']['plaintext'] = strtr($params['message_plaintext'], $variables);
$message['params']['attachments'] = $attachments;
}
/**
* Default engine's prepare function.
*
* @param
* Same parameters as mimemail() except $send.
*
* @return
* The $message array structure containing all details of the message.
*/
function mimemail_prepare_message($sender, $recipient, $subject, $body, $plaintext = NULL, $headers = array(), $text = NULL, $attachments = array(), $mailkey = '') {
module_load_include('inc', 'mimemail');
$site_name = variable_get('site_name', 'Drupal');
$site_mail = variable_get('site_mail', ini_get('sendmail_from'));
// Override site mails default sender when using default engine.
if (variable_get('mimemail_engine', 'mimemail') == 'mimemail') {
if (empty($sender) || $sender == $site_mail) {
$mimemail_name = variable_get('mimemail_name', $site_name);
$mimemail_mail = variable_get('mimemail_mail', $site_mail);
$sender = array(
'name' => !empty($mimemail_name) ? $mimemail_name : $site_name,
'mail' => !empty($mimemail_mail) ? $mimemail_mail : $site_mail,
);
}
elseif (is_array($sender)) {
if (empty($sender['name'])) {
$sender['name'] = variable_get('mimemail_name', $site_name);
}
if (empty($sender['mail'])) {
$sender['mail'] = variable_get('mimemail_mail', $site_mail);
}
}
}
// Body is empty, this is a plaintext message.
if (empty($body)) {
$plaintext = 1;
}
elseif (is_null($plaintext)) {
if (is_object($recipient)) {
if (isset($recipient->mimemail_textonly)) {
$plaintext = $recipient->mimemail_textonly;
}
}
elseif (is_string($recipient) && valid_email_address($recipient)) {
if (is_object($r = user_load(array(
'mail' => $recipient,
))) && isset($r->mimemail_textonly)) {
$plaintext = $r->mimemail_textonly;
$recipient = $r;
// Pass the user object to the address function.
}
}
}
$subject = str_replace(array(
" \n",
"\n",
), '', trim(drupal_html_to_text($subject)));
$body = theme(array(
'mimemail_message__' . $mailkey,
'mimemail_message',
), $subject, $body, $mailkey, $recipient);
foreach (module_implements('mail_post_process') as $module) {
$function = $module . '_mail_post_process';
$function($body, $mailkey);
}
$plaintext = $plaintext || variable_get('mimemail_textonly', 0);
$sender = mimemail_address($sender);
$subject = mime_header_encode($subject);
$mail = mimemail_html_body($body, $subject, $plaintext, $text, $attachments);
$headers = array_merge($headers, $mail['headers']);
$message = array(
'address' => mimemail_address($recipient),
'subject' => $subject,
'body' => $mail['body'],
'sender' => $sender,
'headers' => mimemail_headers($headers, $sender),
);
return $message;
}
/**
* Send a MIME-encoded e-mail message.
*
* @param $message
* The message array.
*
* @return
* TRUE if the mail was successfully accepted for delivery, FALSE otherwise.
*/
function mimemail_send_message($message) {
$engine = variable_get('mimemail_engine', 'mimemail');
$mailengine = $engine . '_mailengine';
if (!$engine || !function_exists($mailengine)) {
return FALSE;
}
return $mailengine('send', $message);
}
/**
* Compose and optionally send a MIME-encoded e-mail message.
*
* Determines the mail engine to use, then prepares the message by calling
* it's prepare function. Uses the default engine, If another one does not exist.
*
* @param $sender
* The email address or user object who is sending the message.
* @param $recipient
* An email address or user object who is receiving the message.
* @param $subject
* A subject line string.
* @param $body
* The message body in HTML format.
* @param $plaintext
* Whether to send the message as plaintext only or HTML. If set to 1, Yes
* or TRUE, then the message will be sent as plaintext.
* @param $headers
* Optional e-mail headers in a keyed array.
* @param $text
* Optional plaintext portion of a multipart e-mail.
* @param $attachments
* An array of arrays which describe one or more attachments.
* Existing files can be added by path, dinamically-generated files
* can be added by content. The internal array consists of the following parts:
* - filepath: Relative Drupal path to an existing file (filecontent is NULL).
* - filecontent: The actual content of the file (filepath is NULL).
* - filename: The filename of the file.
* - filemime: The MIME type of the file.
* The array of arrays looks something like this:
* Array
* (
* [0] => Array
* (
* [filepath] => '/sites/default/files/attachment.txt'
* [filecontent] => 'My attachment.'
* [filename] => 'attachment.txt'
* [filemime] => 'text/plain'
* )
* )
* @param $mailkey
* An identifier for the message.
* @param $send
* Send the message directly.
*
* @return
* An array containing the MIME-encoded message, including headers and body.
*/
function mimemail($sender, $recipient, $subject, $body, $plaintext = NULL, $headers = array(), $text = NULL, $attachments = array(), $mailkey = '', $send = TRUE) {
$engine = variable_get('mimemail_engine', 'mimemail');
$mailengine = $engine . '_mailengine';
$engine_prepare_message = $engine . '_prepare_message';
if (!$engine || !function_exists($mailengine)) {
return FALSE;
}
if (function_exists($engine_prepare_message)) {
$message = $engine_prepare_message($sender, $recipient, $subject, $body, $plaintext, $headers, $text, $attachments, $mailkey);
}
else {
$message = mimemail_prepare_message($sender, $recipient, $subject, $body, $plaintext, $headers, $text, $attachments, $mailkey);
}
// Optionally send e-mail.
if ($send) {
$message['result'] = mimemail_send_message($message);
}
return $message;
}
/**
* Retreives a list of all available mailer engines.
*
* @return
* An array of mailer engine names.
*/
function mimemail_get_engines() {
$engines = array();
foreach (module_implements('mailengine') as $module) {
$function = $module . '_mailengine';
if (function_exists($function)) {
$engines[$module] = $function('name') . ' - ' . $function('description');
}
}
return $engines;
}
/**
* The default mailengine.
*
* @param $op
* The operation to perform on the message.
* @param $message
* The message to be sent.
*
* @return
* Returns TRUE if the operation was successful or FALSE if it was not.
*/
function mimemail_mailengine($op, $message = array()) {
module_load_include('inc', 'mimemail');
// Default values.
$message = array_merge(array(
'address' => '',
'subject' => '',
'body' => '',
'sender' => '',
'headers' => '',
), $message);
switch ($op) {
case 'name':
return t('Mime Mail');
case 'description':
return t("Default mailing engine using drupal_mail().");
// Not implemented.
case 'settings':
return FALSE;
case 'multiple':
case 'single':
case 'send':
if (!is_array($message['address'])) {
$message['address'] = array(
$message['address'],
);
}
// If 'Return-Path' isn't already set in php.ini, we pass it separately
// as an additional parameter instead of in the header.
// However, if PHP's 'safe_mode' is on, this is not allowed.
if (isset($message['headers']['Return-Path']) && !ini_get('safe_mode')) {
$return_path_set = strpos(ini_get('sendmail_path'), ' -f');
if (!$return_path_set) {
$return_path = trim($message['headers']['Return-Path'], '<,>');
unset($message['headers']['Return-Path']);
}
}
$status = TRUE;
foreach ($message['address'] as $to) {
$subject = $message['subject'];
$body = $message['body'];
$headers = mimemail_rfc_headers($message['headers']);
// We validate the return path, unless it is equal to the site mail, which
// we assume to be safe.
if (isset($return_path) && !empty($return_path) && (variable_get('site_mail', ini_get('sendmail_from')) === $return_path || mimemail_isshellsafe($return_path))) {
if (isset($_SERVER['WINDIR']) || strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE) {
// On Windows, PHP will use the value of sendmail_from for the
// Return-Path header.
$old_from = ini_get('sendmail_from');
ini_set('sendmail_from', $return_path);
$status = @mail($to, $subject, $body, $headers) && $status;
ini_set('sendmail_from', $old_from);
}
else {
// On most non-Windows systems, the "-f" option to the sendmail command
// is used to set the Return-Path.
$status = @mail($to, $subject, $body, $headers, '-f' . $return_path) && $status;
}
}
else {
// The optional $additional_parameters argument to mail() is not allowed
// if safe_mode is enabled. Passing any value throws a PHP warning and
// makes mail() return FALSE.
$status = @mail($to, $subject, $body, $headers) && $status;
}
}
return $status;
}
return FALSE;
}
/**
* Overrides Drupal's default mail sending process.
*/
if (strpos(variable_get('smtp_library', ''), 'mimemail') !== FALSE && !function_exists('drupal_mail_wrapper')) {
function drupal_mail_wrapper(&$message) {
$from = $message['from'];
$to = $message['to'];
$subject = $message['subject'];
if (preg_match('/plain/', $message['headers']['Content-Type'])) {
$format = variable_get('mimemail_format', FILTER_FORMAT_DEFAULT);
$body = check_markup($message['body'], $format, FALSE);
}
else {
$body = $message['body'];
}
$plaintext = isset($message['plaintext']) ? $message['plaintext'] : NULL;
$headers = isset($message['headers']) ? $message['headers'] : array();
$text = isset($message['text']) ? $message['text'] : NULL;
$attachments = isset($message['attachments']) ? $message['attachments'] : array();
$mailkey = isset($message['id']) ? $message['id'] : '';
$message = mimemail($from, $to, $subject, $body, $plaintext, $headers, $text, $attachments, $mailkey);
return $message['result'];
}
}
/**
* Disallows potentially unsafe shell characters.
*
* @param string $string
* The string to be validated.
*
* @return bool
* True if the string is shell-safe.
*/
function mimemail_isshellsafe($string) {
if (escapeshellcmd($string) !== $string || !in_array(escapeshellarg($string), array(
"'{$string}'",
"\"{$string}\"",
))) {
return FALSE;
}
if (preg_match('/[^a-zA-Z0-9@_\\-.]/', $string) !== 0) {
return FALSE;
}
return TRUE;
}
Functions
Name | Description |
---|---|
mimemail | Compose and optionally send a MIME-encoded e-mail message. |
mimemail_get_engines | Retreives a list of all available mailer engines. |
mimemail_incoming_access | Access callback to process incoming messages. |
mimemail_isshellsafe | Disallows potentially unsafe shell characters. |
mimemail_mail | Implements hook_mail(). |
mimemail_mailengine | The default mailengine. |
mimemail_menu | Implements hook_menu(). |
mimemail_perm | Implements hook_perm(). |
mimemail_prepare_message | Default engine's prepare function. |
mimemail_send_message | Send a MIME-encoded e-mail message. |
mimemail_theme | Implements hook_theme(). |
mimemail_user | Implements hook_user(). |