updated mimemail

This commit is contained in:
Bachir Soussi Chiadmi 2019-01-27 14:43:42 +01:00
parent 5510ac0abf
commit 79db3e3896
16 changed files with 149 additions and 48 deletions

View File

@ -1,6 +1,29 @@
Mime Mail 7.x-1.x, xxxx-xx-xx
-----------------------
Mime Mail 7.x-1.1, 2018-10-17
-----------------------
- #161907 by RainbowLyte, sgabe: Fixed sanitization of additional mail parameter
- #2986204 by TR: Missing test dependencies
Mime Mail 7.x-1.0, 2017-05-14
-----------------------
- #2743229 by Bird-Kid, AdamPS: CSS doesn't get attached in PHP7
- #2858390 by Munavijayalakshmi, Jigar.addweb: Fix coding standard issues
- #2594743 by skipyT: Theme function called for plain messages also
- #2374673 by smokris: Prevent processing of already embedded images
- #1532352 by sgabe, Matt B: Add permission to view user specific settings
- #2783815 by argiepiano: Add 'Reply-to' field to "Send HTML mail to all users of a role" action
- #2796993 by Cauliflower: Return send status in Rules actions
- #2796965 by Cauliflower: Allow NULL values in Rules actions
- #1568680 by jamsilver: Use $message for themeing
- #2721799 by igorik, sgabe: Minor typo
- #2146513 by torotil, Anybody: Scan theme for other *css* file types
- #2678818 by hoebekewim, das-peter: Mime Mail Compress has a deprecated constructor
- #2553815 by nitrocad, anthonys: Imported font generates empty attachment
- #2562181 by rrfegade: Remove unused varibles
- #2562177 by rrfegade: Spelling errors
Mime Mail 7.x-1.0-beta4, 2015-08-02
-----------------------
- #2413495 by sgabe, siggi_kid: Public images not embedded when file default scheme is private

View File

@ -2,7 +2,7 @@
-- SUMMARY --
This is a Mime Mail component module (for use by other modules).
* It permits users to recieve HTML email and can be used by other modules. The mail
* It permits users to receieve HTML email and can be used by other modules. The mail
functionality accepts an HTML message body, mime-endcodes it and sends it.
* If the HTML has embedded graphics, these graphics are MIME-encoded and included
as a message attachment.

View File

@ -85,7 +85,7 @@ function mimemail_admin_settings() {
'#access' => count($formats) > 1,
'#attributes' => array('class' => array('filter-list')),
'#description' => t('The filter set that will be applied to the message body.
If you are using Mime Mail as default mail sytem, make sure to enable
If you are using Mime Mail as default mail system, make sure to enable
"Convert line breaks into HTML" and "Convert URLs into links" with a long
enough maximum length for e.g. password reset URLs!'),
);

View File

@ -75,13 +75,13 @@ function mimemail_parse($message) {
// We're dealing with a multi-part message.
$mail['parts'] = mimemail_parse_boundary($mail);
foreach ($mail['parts'] as $i => $part_body) {
foreach ($mail['parts'] as $part_body) {
$part = mimemail_parse_headers($part_body);
$sub_parts = mimemail_parse_boundary($part);
// Content is encoded in a multipart/alternative section.
if (count($sub_parts) > 1) {
foreach ($sub_parts as $j => $sub_part_body) {
foreach ($sub_parts as $sub_part_body) {
$sub_part = mimemail_parse_headers($sub_part_body);
if ($sub_part['content-type'] == 'text/plain') {
$mail['text'] = mimemail_parse_content($sub_part);

View File

@ -29,7 +29,6 @@ class MimeMailSystem implements MailSystemInterface {
}
$engine = variable_get('mimemail_engine', 'mimemail');
$mailengine = $engine . '_mailengine';
$engine_prepare_message = $engine . '_prepare_message';
if (function_exists($engine_prepare_message)) {

View File

@ -112,7 +112,7 @@ function mimemail_headers($headers, $from = NULL) {
* )
*/
function mimemail_extract_files($html) {
$pattern = '/(<link[^>]+href=[\'"]?|<object[^>]+codebase=[\'"]?|@import |[\s]src=[\'"]?)([^\'>"]+)([\'"]?)/mis';
$pattern = '/(<link[^>]+href=[\'"]?|<object[^>]+codebase=[\'"]?|@import (?:url\()?[\'"]?|[\s]src=[\'"]?)([^\'>")]+)([\'"]?)/mis';
$content = preg_replace_callback($pattern, '_mimemail_replace_files', $html);
$encoding = '8Bit';
@ -177,7 +177,7 @@ function _mimemail_file($url = NULL, $content = NULL, $name = '', $type = '', $d
$url = _mimemail_url($url, 'TRUE');
// The $url is absolute, we're done here.
$scheme = file_uri_scheme($url);
if ($scheme == 'http' || $scheme == 'https' || preg_match('!mailto:!', $url)) {
if ($scheme == 'http' || $scheme == 'https' || preg_match('!mailto:!', $url) || preg_match('!^data:!', $url)) {
return $url;
}
// The $url is a non-local URI that needs to be converted to a URL.
@ -209,11 +209,11 @@ function _mimemail_file($url = NULL, $content = NULL, $name = '', $type = '', $d
$type = $is_file ? file_get_mimetype($file) : file_get_mimetype($name);
}
$id = md5($file) .'@'. $_SERVER['HTTP_HOST'];
$id = md5($file) . '@' . $_SERVER['HTTP_HOST'];
// Prevent duplicate items.
if (isset($ids[$id])) {
return 'cid:'. $ids[$id];
return 'cid:' . $ids[$id];
}
$new_file = array(
@ -449,7 +449,6 @@ function mimemail_html_body($body, $subject, $plain = FALSE, $plaintext = NULL,
* A processed URL.
*/
function _mimemail_url($url, $to_embed = NULL) {
global $base_url;
$url = urldecode($url);
$to_link = variable_get('mimemail_linkonly', 0);
@ -541,7 +540,6 @@ function mimemail_address($address, $simplify = FALSE) {
if (is_array($address)) {
// It's an array containing 'mail' and/or 'name'.
if (isset($address['mail'])) {
$output = '';
if (empty($address['name']) || $simplify) {
return $address['mail'];
}

View File

@ -14,9 +14,13 @@ files[] = tests/mimemail.test
files[] = tests/mimemail_rules.test
files[] = tests/mimemail_compress.test
; Information added by Drupal.org packaging script on 2015-08-02
version = "7.x-1.0-beta4"
; Modules needed for testing
test_dependencies[] = rules
test_dependencies[] = entity
test_dependencies[] = entity_token
; Information added by Drupal.org packaging script on 2018-10-17
version = "7.x-1.1"
core = "7.x"
project = "mimemail"
datestamp = "1438530555"
datestamp = "1539793390"

View File

@ -35,6 +35,10 @@ function mimemail_menu() {
*/
function mimemail_permission() {
return array(
'view mimemail user settings' => array(
'title' => t('View Mime Mail user settings'),
'description' => t('View user specific settings for Mime Mail.'),
),
'edit mimemail user settings' => array(
'title' => t('Edit Mime Mail user settings'),
'description' => t('Edit user specific settings for Mime Mail.'),
@ -85,6 +89,7 @@ function mimemail_user_view($account, $view_mode, $langcode) {
$account->content['mimemail'] = array(
'#type' => 'user_profile_category',
'#title' => t('Email'),
'#access' => user_access('view mimemail user settings'),
);
$account->content['mimemail']['textonly'] = array(
@ -247,7 +252,9 @@ function mimemail_mailengine($op, $message = array()) {
$result = TRUE;
foreach ($recipients as $to) {
if (isset($return_path) && !empty($return_path)) {
// 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.
@ -359,7 +366,7 @@ function mimemail_prepare_message($message) {
$hook = array(
'mimemail_message__' . $key,
'mimemail_message__' . $module .'__'. $key,
'mimemail_message__' . $module . '__' . $key,
);
$variables = array(
@ -367,10 +374,13 @@ function mimemail_prepare_message($message) {
'key' => $key,
'recipient' => $to,
'subject' => $subject,
'body' => $body
'body' => $body,
'message' => $message
);
$body = theme($hook, $variables);
if (!$plain) {
$body = theme($hook, $variables);
}
foreach (module_implements('mail_post_process') as $module) {
$function = $module . '_mail_post_process';
@ -390,3 +400,22 @@ function mimemail_prepare_message($message) {
return $message;
}
/**
* 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;
}

View File

@ -32,35 +32,40 @@ function mimemail_rules_action_info() {
'label' => t('CC Recipient'),
'description' => t("The mail's carbon copy address. You may separate multiple addresses with comma."),
'optional' => TRUE,
'allow null' => TRUE,
),
'bcc' => array(
'type' => 'text',
'label' => t('BCC Recipient'),
'description' => t("The mail's blind carbon copy address. You may separate multiple addresses with comma."),
'optional' => TRUE,
'allow null' => TRUE,
),
'from_name' => array(
'type' => 'text',
'label' => t('Sender name'),
'description' => t("The sender's name. Leave it empty to use the site-wide configured name."),
'optional' => TRUE,
'allow null' => TRUE,
),
'from_mail' => array(
'type' => 'text',
'label' => t('Sender e-mail address'),
'description' => t("The sender's address. Leave it empty to use the site-wide configured address."),
'optional' => TRUE,
'allow null' => TRUE,
),
'reply_to' => array(
'type' => 'text',
'label' => t('Reply e-mail address'),
'description' => t("The address to reply to. Leave it empty to use the sender's address."),
'optional' => TRUE,
'allow null' => TRUE,
),
'list_unsubscribe' => array(
'type' => 'text',
'label' => t('Unsubscription e-mail and/or URL'),
'description' => t("An e-mail address and/or a URL which can be used for unsubscription. Values must be enclosed by angel brackets and separated by a comma."),
'description' => t("An e-mail address and/or a URL which can be used for unsubscription. Values must be enclosed by angle brackets and separated by a comma."),
'optional' => TRUE,
),
'subject' => array(
@ -100,6 +105,12 @@ function mimemail_rules_action_info() {
'default mode' => 'selector',
),
),
'provides' => array(
'send_status' => array(
'type' => 'boolean',
'label' => t('Send status'),
),
),
'base' => 'rules_action_mimemail',
'access callback' => 'rules_system_integration_access',
),
@ -120,7 +131,7 @@ function mimemail_rules_action_info() {
),
'active' => array(
'type' => 'boolean',
'label' =>('Send to active users'),
'label' => t('Send to active users'),
'description' => t('Send mail only to active users.'),
),
'from_name' => array(
@ -128,12 +139,21 @@ function mimemail_rules_action_info() {
'label' => t('Sender name'),
'description' => t("The sender's name. Leave it empty to use the site-wide configured name."),
'optional' => TRUE,
'allow null' => TRUE,
),
'from_mail' => array(
'type' => 'text',
'label' => t('Sender e-mail address'),
'description' => t("The sender's address. Leave it empty to use the site-wide configured address."),
'optional' => TRUE,
'allow null' => TRUE,
),
'reply_to' => array(
'type' => 'text',
'label' => t('Reply e-mail address'),
'description' => t("The address to reply to. Leave it empty to use the sender's address."),
'optional' => TRUE,
'allow null' => TRUE,
),
'subject' => array(
'type' => 'text',
@ -176,6 +196,12 @@ function mimemail_rules_action_info() {
'default mode' => 'selector',
),
),
'provides' => array(
'send_status' => array(
'type' => 'boolean',
'label' => t('Send status'),
),
),
'base' => 'rules_action_mimemail_to_users_of_role',
'access callback' => 'rules_system_integration_access',
),
@ -279,13 +305,15 @@ function rules_action_mimemail($key, $to, $cc = NULL, $bcc = NULL, $from_name =
'attachments' => $attachments,
);
drupal_mail('mimemail', $key, $to, $language, $params, $from);
$message = drupal_mail('mimemail', $key, $to, $language, $params, $from);
return array('send_status' => !empty($message['result']));
}
/**
* Action: Send HTML mail to all users of a specific role group(s).
*/
function rules_action_mimemail_to_users_of_role($key, $roles, $active, $from_name = NULL, $from_mail = NULL, $subject, $body, $plaintext = NULL, $attachments = array(), $use_userlang = FALSE, $langcode= NULL, $settings, RulesState $state, RulesPlugin $element) {
function rules_action_mimemail_to_users_of_role($key, $roles, $active, $from_name = NULL, $from_mail = NULL, $reply_to = NULL, $subject, $body, $plaintext = NULL, $attachments = array(), $use_userlang = FALSE, $langcode= NULL, $settings, RulesState $state, RulesPlugin $element) {
module_load_include('inc', 'mimemail');
// Set the sender name and from address.
@ -326,6 +354,7 @@ function rules_action_mimemail_to_users_of_role($key, $roles, $active, $from_nam
'action' => $element,
'state' => $state,
),
'reply-to' => $reply_to,
'plaintext' => $plaintext,
'attachments' => $attachments,
);
@ -352,6 +381,8 @@ function rules_action_mimemail_to_users_of_role($key, $roles, $active, $from_nam
$role_names = array_intersect_key(user_roles(TRUE), array_flip($roles));
watchdog('rules', 'Successfully sent HTML email to the role(s) %roles.', array('%roles' => implode(', ', $role_names)));
}
return array('send_status' => !empty($message['result']));
}
/**

View File

@ -6,9 +6,8 @@ dependencies[] = trigger
core = 7.x
; Information added by Drupal.org packaging script on 2015-08-02
version = "7.x-1.0-beta4"
; Information added by Drupal.org packaging script on 2018-10-17
version = "7.x-1.1"
core = "7.x"
project = "mimemail"
datestamp = "1438530555"
datestamp = "1539793390"

View File

@ -26,7 +26,8 @@ function mimemail_send_email_action($entity, $context) {
if (empty($context['node'])) {
if (get_class($entity) == 'OgMembership') {
$context['user'] = user_load($entity->etid);
} else {
}
else {
$context['node'] = $entity;
}
}

View File

@ -32,7 +32,7 @@ class mimemail_compress {
private $css = '';
private $unprocessable_tags = array('wbr');
public function mimemail_compress($html = '', $css = '') {
public function __construct($html = '', $css = '') {
$this->html = $html;
$this->css = $css;
}
@ -144,7 +144,7 @@ class mimemail_compress {
$node->setAttribute('style', $style);
// Convert float to align for images.
$float = preg_match ('/float:(left|right)/', $style, $matches);
$float = preg_match('/float:(left|right)/', $style, $matches);
if ($node->nodeName == 'img' && $float) {
$node->setAttribute('align', $matches[1]);
$node->setAttribute('vspace', 5);
@ -196,6 +196,23 @@ class mimemail_compress {
return $precedence;
}
/**
* Replace callback function that matches ID attributes.
*/
private static function replace_id_attributes($m) {
return (strlen($m[1]) ? $m[1] : '*') . '[@id="' . $m[2] . '"]';
}
/**
* Replace callback function that matches class attributes.
*/
private static function replace_class_attributes($m) {
return (strlen($m[1]) ? $m[1] : '*') .
'[contains(concat(" ",normalize-space(@class)," "),concat(" ","' .
implode('"," "))][contains(concat(" ",normalize-space(@class)," "),concat(" ","', explode('.', substr($m[2], 1))) .
'"," "))]';
}
/**
* Right now we only support CSS 1 selectors, but include CSS2/3 selectors are fully possible.
*
@ -206,6 +223,7 @@ class mimemail_compress {
// Already an XPath expression.
return $selector;
}
// Returns an Xpath selector.
$search = array(
'/\s+>\s+/', // Matches any F element that is a child of an element E.
@ -213,8 +231,6 @@ class mimemail_compress {
'/\s+/', // Matches any F element that is a descendant of an E element.
'/(\w)\[(\w+)\]/', // Matches element with attribute.
'/(\w)\[(\w+)\=[\'"]?(\w+)[\'"]?\]/', // Matches element with EXACT attribute.
'/(\w+)?\#([\w\-]+)/e', // Matches id attributes.
'/(\w+|\*)?((\.[\w\-]+)+)/e', // Matches class attributes.
);
$replace = array(
'/',
@ -222,10 +238,13 @@ class mimemail_compress {
'//',
'\\1[@\\2]',
'\\1[@\\2="\\3"]',
"(strlen('\\1') ? '\\1' : '*').'[@id=\"\\2\"]'",
"(strlen('\\1') ? '\\1' : '*').'[contains(concat(\" \",normalize-space(@class),\" \"),concat(\" \",\"'.implode('\",\" \"))][contains(concat(\" \",normalize-space(@class),\" \"),concat(\" \",\"',explode('.',substr('\\2',1))).'\",\" \"))]'",
);
return '//' . preg_replace($search, $replace, trim($selector));
$result = preg_replace($search, $replace, trim($selector));
$result = preg_replace_callback('/(\w+)?\#([\w\-]+)/', 'mimemail_compress::replace_id_attributes', $result);
$result = preg_replace_callback('/(\w+|\*)?((\.[\w\-]+)+)/', 'mimemail_compress::replace_class_attributes', $result);
return '//' . $result;
}
private function css_style_to_array($style) {

View File

@ -6,9 +6,8 @@ core = 7.x
files[] = mimemail_compress.inc
; Information added by Drupal.org packaging script on 2015-08-02
version = "7.x-1.0-beta4"
; Information added by Drupal.org packaging script on 2018-10-17
version = "7.x-1.1"
core = "7.x"
project = "mimemail"
datestamp = "1438530555"
datestamp = "1539793390"

View File

@ -4,9 +4,8 @@ dependencies[] = mimemail
package = Example modules
core = 7.x
; Information added by Drupal.org packaging script on 2015-08-02
version = "7.x-1.0-beta4"
; Information added by Drupal.org packaging script on 2018-10-17
version = "7.x-1.1"
core = "7.x"
project = "mimemail"
datestamp = "1438530555"
datestamp = "1539793390"

View File

@ -31,7 +31,7 @@ class MimeMailUnitTestCase extends DrupalUnitTestCase {
$chars = array('-', '.', '+', '_');
$name = $this->randomString();
$local = $this->randomName() . $chars[array_rand($chars)] . $this->randomName();
$domain = $this->randomName() . '-' . $this->randomName() . '.' . $this->randomName(rand(2,4));
$domain = $this->randomName() . '-' . $this->randomName() . '.' . $this->randomName(rand(2, 4));
$headers = mimemail_headers(array(), "$name <$local@$domain>");
$result = $headers['Return-Path'];
$expected = "<$local@$domain>";
@ -47,7 +47,7 @@ class MimeMailUnitTestCase extends DrupalUnitTestCase {
$expected = 'sites/default/files/styles/thumbnail/public/image.jpg';
$this->assertIdentical($result, $expected, 'Security token removed from styled image URL.');
$expected = $url = 'public://' . $this->randomName() . ' '. $this->randomName() . '.' . $this->randomName(3);
$expected = $url = 'public://' . $this->randomName() . ' ' . $this->randomName() . '.' . $this->randomName(3);
$result = _mimemail_url($url, TRUE);
$this->assertIdentical($result, $expected, 'Space in the filename of the attachment left intact.');
}
@ -89,7 +89,7 @@ class MimeMailWebTestCase extends DrupalWebTestCase {
array('mimemail_linkonly' => TRUE),
t('Save configuration'));
$url = 'public://' . $this->randomName() . ' '. $this->randomName() . '.jpg';
$url = 'public://' . $this->randomName() . ' ' . $this->randomName() . '.jpg';
$result = _mimemail_url($url, TRUE);
$expected = str_replace(' ', '%20', file_create_url($url));
$message = 'Stream wrapper converted to web accessible URL for linked image.';

View File

@ -10,7 +10,7 @@ function mimemail_theme_theme() {
return array(
'mimemail_message' => array(
'variables' => array('module' => NULL, 'key' => NULL, 'recipient' => NULL, 'subject' => NULL, 'body' => NULL),
'variables' => array('module' => NULL, 'key' => NULL, 'recipient' => NULL, 'subject' => NULL, 'body' => NULL, 'message' => array()),
'template' => 'mimemail-message',
'pattern' => 'mimemail_message__',
'file' => 'mimemail.theme.inc',
@ -36,7 +36,7 @@ function template_preprocess_mimemail_message(&$variables) {
$themepath = drupal_get_path('theme', $theme);
$sitestyle = variable_get('mimemail_sitestyle', 1);
$mailstyles = file_scan_directory($themepath, '#^mail\.css*$#');
$mailstyles = file_scan_directory($themepath, '#^mail(-.+)?\.(c|le|sc|sa)ss$#');
// Check recursively for the existence of a mail.css file in the theme folder.
if (!empty($mailstyles)) {