Commit 6cc95966 authored by mcdruid's avatar mcdruid

Issue #3098058 by mcdruid, SAVEL, alexpott, alexandra.vecher,...

Issue #3098058 by mcdruid, SAVEL, alexpott, alexandra.vecher, nikolas.tatianenko, kiamlaluno, sjerdo, RobLoach, catch, cburschka, carlos8f, penyaskito, gdud, theborg, pillarsdotnet, olamaekle, naxoc: [D7] Use site name in From: header for system e-mails
parent 62a95e34
......@@ -12,6 +12,12 @@
*/
define('MAIL_LINE_ENDINGS', isset($_SERVER['WINDIR']) || (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Win32') !== FALSE) ? "\r\n" : "\n");
/**
* Special characters, defined in RFC_2822.
*/
define('MAIL_RFC_2822_SPECIALS', '()<>[]:;@\,."');
/**
* Composes and optionally sends an e-mail message.
*
......@@ -148,8 +154,13 @@ function drupal_mail($module, $key, $to, $language, $params = array(), $from = N
// Return-Path headers should have a domain authorized to use the originating
// SMTP server.
$headers['From'] = $headers['Sender'] = $headers['Return-Path'] = $default_from;
if (variable_get('mail_display_name_site_name', FALSE)) {
$display_name = variable_get('site_name', 'Drupal');
$headers['From'] = drupal_mail_format_display_name($display_name) . ' <' . $default_from . '>';
}
}
if ($from) {
if ($from && $from != $default_from) {
$headers['From'] = $from;
}
$message['headers'] = $headers;
......@@ -557,10 +568,59 @@ function drupal_html_to_text($string, $allowed_tags = NULL) {
return $output . $footnotes;
}
/**
* Return a RFC-2822 compliant "display-name" component.
*
* The "display-name" component is used in mail header "Originator" fields
* (From, Sender, Reply-to) to give a human-friendly description of the
* address, i.e. From: My Display Name <xyz@example.org>. RFC-822 and
* RFC-2822 define its syntax and rules. This method gets as input a string
* to be used as "display-name" and formats it to be RFC compliant.
*
* @param string $string
* A string to be used as "display-name".
*
* @return string
* A RFC compliant version of the string, ready to be used as
* "display-name" in mail originator header fields.
*/
function drupal_mail_format_display_name($string) {
// Make sure we don't process html-encoded characters. They may create
// unneeded trouble if left encoded, besides they will be correctly
// processed if decoded.
$string = decode_entities($string);
// If string contains non-ASCII characters it must be (short) encoded
// according to RFC-2047. The output of a "B" (Base64) encoded-word is
// always safe to be used as display-name.
$safe_display_name = mime_header_encode($string, TRUE);
// Encoded-words are always safe to be used as display-name because don't
// contain any RFC 2822 "specials" characters. However
// mimeHeaderEncode() encodes a string only if it contains any
// non-ASCII characters, and leaves its value untouched (un-encoded) if
// ASCII only. For this reason in order to produce a valid display-name we
// still need to make sure there are no "specials" characters left.
if (preg_match('/[' . preg_quote(MAIL_RFC_2822_SPECIALS) . ']/', $safe_display_name)) {
// If string is already quoted, it may or may not be escaped properly, so
// don't trust it and reset.
if (preg_match('/^"(.+)"$/', $safe_display_name, $matches)) {
$safe_display_name = str_replace(array('\\\\', '\\"'), array('\\', '"'), $matches[1]);
}
// Transform the string in a RFC-2822 "quoted-string" by wrapping it in
// double-quotes. Also make sure '"' and '\' occurrences are escaped.
$safe_display_name = '"' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $safe_display_name) . '"';
}
return $safe_display_name;
}
/**
* Wraps words on a single line.
*
* Callback for array_walk() winthin drupal_wrap_mail().
* Callback for array_walk() within drupal_wrap_mail().
*/
function _drupal_wrap_mail_line(&$line, $key, $values) {
// Use soft-breaks only for purely quoted or unindented text.
......
......@@ -59,6 +59,81 @@ class MailTestCase extends DrupalWebTestCase implements MailSystemInterface {
$this->assertNull(self::$sent_message, 'Message was canceled.');
}
/**
* Checks for the site name in an auto-generated From: header.
*/
function testFromHeader() {
global $language;
$default_from = variable_get('site_mail', ini_get('sendmail_from'));
$site_name = variable_get('site_name', 'Drupal');
// Reset the class variable holding a copy of the last sent message.
self::$sent_message = NULL;
// Send an e-mail with a sender address specified.
$from_email = 'someone_else@example.com';
$message = drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language, array(), $from_email);
// Test that the from e-mail is just the e-mail and not the site name and
// default sender e-mail.
$this->assertEqual($from_email, self::$sent_message['headers']['From']);
// Check default behavior is only email in FROM header.
self::$sent_message = NULL;
// Send an e-mail and check that the From-header contains only default mail address.
variable_del('mail_display_name_site_name');
$message = drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language);
$this->assertEqual($default_from, self::$sent_message['headers']['From']);
self::$sent_message = NULL;
// Send an e-mail and check that the From-header contains the site name.
variable_set('mail_display_name_site_name', TRUE);
$message = drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language);
$this->assertEqual($site_name . ' <' . $default_from . '>', self::$sent_message['headers']['From']);
}
/**
* Checks for the site name in an auto-generated From: header.
*/
function testFromHeaderRfc2822Compliant() {
global $language;
$default_from = variable_get('site_mail', ini_get('sendmail_from'));
// Enable adding a site name to From.
variable_set('mail_display_name_site_name', TRUE);
$site_names = array(
// Simple ASCII characters.
'Test site' => 'Test site',
// ASCII with html entity.
'Test &amp; site' => 'Test & site',
// Non-ASCII characters.
'Tést site' => '=?UTF-8?B?VMOpc3Qgc2l0ZQ==?=',
// Non-ASCII with special characters.
'Tést; site' => '=?UTF-8?B?VMOpc3Q7IHNpdGU=?=',
// Non-ASCII with html entity.
'T&eacute;st; site' => '=?UTF-8?B?VMOpc3Q7IHNpdGU=?=',
// ASCII with special characters.
'Test; site' => '"Test; site"',
// ASCII with special characters as html entity.
'Test &lt; site' => '"Test < site"',
// ASCII with special characters and '\'.
'Test; \ "site"' => '"Test; \\\\ \"site\""',
// String already RFC-2822 compliant.
'"Test; site"' => '"Test; site"',
// String already RFC-2822 compliant.
'"Test; \\\\ \"site\""' => '"Test; \\\\ \"site\""',
);
foreach ($site_names as $original_name => $safe_string) {
variable_set('site_name', $original_name);
// Reset the class variable holding a copy of the last sent message.
self::$sent_message = NULL;
// Send an e-mail and check that the From-header contains is RFC-2822 compliant.
drupal_mail('simpletest', 'from_test', 'from_test@example.com', $language);
$this->assertEqual($safe_string . ' <' . $default_from . '>', self::$sent_message['headers']['From']);
}
}
/**
* Concatenate and wrap the e-mail body for plain-text mails.
*
......
......@@ -701,3 +701,18 @@
* optimization and revert to the original behaviour.
*/
# $conf['variable_initialize_wait_for_lock'] = FALSE;
/**
* Use site name as display-name in outgoing mail.
*
* Drupal can use the site name (i.e. the value of the site_name variable) as
* the display-name when sending e-mail. For example this would mean the sender
* might be "Acme Website" <acme@example.com> as opposed to just the e-mail
* address alone. In order to avoid disruption this is not enabled by default
* for existing sites. The feature can be enabled by setting this variable to
* TRUE.
*
* @see https://tools.ietf.org/html/rfc2822
* @see drupal_mail()
*/
$conf['mail_display_name_site_name'] = TRUE;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment