diff --git a/core/lib/Drupal/Component/Utility/Mail.php b/core/lib/Drupal/Component/Utility/Mail.php index 423cfb2668d..50c998686c7 100644 --- a/core/lib/Drupal/Component/Utility/Mail.php +++ b/core/lib/Drupal/Component/Utility/Mail.php @@ -2,6 +2,8 @@ namespace Drupal\Component\Utility; +@trigger_error('\Drupal\Component\Utility\Mail is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. See https://www.drupal.org/node/3207439', E_USER_DEPRECATED); + /** * Provides helpers to ensure emails are compliant with RFCs. * @@ -29,8 +31,15 @@ class Mail { * @return string * A RFC compliant version of the string, ready to be used as * "display-name" in mail originator header fields. + * + * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use + * \Symfony\Component\Mime\Header\MailboxHeader instead. + * + * @see https://www.drupal.org/node/3207439 */ public static function formatDisplayName($string) { + @trigger_error('\Drupal\Component\Utility\Mail::formatDisplayName() is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use \Symfony\Component\Mime\Header\MailboxHeader instead. See https://www.drupal.org/node/3207439', E_USER_DEPRECATED); + // 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. diff --git a/core/lib/Drupal/Component/Utility/Unicode.php b/core/lib/Drupal/Component/Utility/Unicode.php index a33250f9351..4a63ec2e477 100644 --- a/core/lib/Drupal/Component/Utility/Unicode.php +++ b/core/lib/Drupal/Component/Utility/Unicode.php @@ -393,8 +393,14 @@ public static function strcasecmp($str1, $str2) { * * @return string * The mime-encoded header. + * + * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use + * \Symfony\Component\Mime\Header\UnstructuredHeader instead. + * + * @see https://www.drupal.org/node/3207439 */ public static function mimeHeaderEncode($string, $shorten = FALSE) { + @trigger_error('\Drupal\Component\Utility\Unicode::mimeHeaderEncode() is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use \Symfony\Component\Mime\Header\UnstructuredHeader instead. See https://www.drupal.org/node/3207439', E_USER_DEPRECATED); if (preg_match('/[^\x20-\x7E]/', $string)) { // floor((75 - strlen("=?UTF-8?B??=")) * 0.75); $chunk_size = 47; @@ -423,8 +429,14 @@ public static function mimeHeaderEncode($string, $shorten = FALSE) { * * @return string * The mime-decoded header. + * + * @deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use + * iconv_mime_decode() instead. + * + * @see https://www.drupal.org/node/3207439 */ public static function mimeHeaderDecode($header) { + @trigger_error('\Drupal\Component\Utility\Unicode::mimeHeaderDecode() is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use iconv_mime_decode() instead. See https://www.drupal.org/node/3207439', E_USER_DEPRECATED); $callback = function ($matches) { $data = (strtolower($matches[2]) == 'b') ? base64_decode($matches[3]) : str_replace('_', ' ', quoted_printable_decode($matches[3])); if (strtolower($matches[1]) != 'utf-8') { diff --git a/core/lib/Drupal/Core/Mail/MailManager.php b/core/lib/Drupal/Core/Mail/MailManager.php index 4fd4f9ba7e6..05c0c8adfa9 100644 --- a/core/lib/Drupal/Core/Mail/MailManager.php +++ b/core/lib/Drupal/Core/Mail/MailManager.php @@ -5,7 +5,6 @@ use Drupal\Component\Render\MarkupInterface; use Drupal\Component\Render\PlainTextOutput; use Drupal\Component\Utility\Html; -use Drupal\Component\Utility\Mail as MailHelper; use Drupal\Core\Logger\LoggerChannelFactoryInterface; use Drupal\Core\Messenger\MessengerTrait; use Drupal\Core\Plugin\DefaultPluginManager; @@ -17,6 +16,8 @@ use Drupal\Core\Render\RendererInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\TranslationInterface; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Header\MailboxHeader; /** * Provides a Mail plugin manager. @@ -255,9 +256,12 @@ public function doMail($module, $key, $to, $langcode, $params = [], $reply = NUL // To prevent email from looking like spam, the addresses in the Sender and // Return-Path headers should have a domain authorized to use the // originating SMTP server. - $headers['Sender'] = $headers['Return-Path'] = $site_mail; + $headers['From'] = $headers['Sender'] = $headers['Return-Path'] = $site_mail; // Make sure the site-name is a RFC-2822 compliant 'display-name'. - $headers['From'] = MailHelper::formatDisplayName($site_config->get('name')) . ' <' . $site_mail . '>'; + if ($site_mail) { + $mailbox = new MailboxHeader('From', new Address($site_mail, $site_config->get('name') ?: '')); + $headers['From'] = $mailbox->getBodyAsString(); + } if ($reply) { $headers['Reply-to'] = $reply; } diff --git a/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php b/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php index 27e5c76e5d8..4a7031c4912 100644 --- a/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php +++ b/core/lib/Drupal/Core/Mail/Plugin/Mail/PhpMail.php @@ -2,10 +2,11 @@ namespace Drupal\Core\Mail\Plugin\Mail; -use Drupal\Component\Utility\Unicode; use Drupal\Core\Mail\MailFormatHelper; use Drupal\Core\Mail\MailInterface; use Drupal\Core\Site\Settings; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Header\UnstructuredHeader; /** * Defines the default Drupal mail backend, using PHP's native mail() function. @@ -75,13 +76,13 @@ public function mail(array $message) { unset($message['headers']['Return-Path']); } } - $mimeheaders = []; + $headers = new Headers(); foreach ($message['headers'] as $name => $value) { - $mimeheaders[] = $name . ': ' . Unicode::mimeHeaderEncode($value); + $headers->addHeader($name, $value); } $line_endings = Settings::get('mail_line_endings', PHP_EOL); // Prepare mail commands. - $mail_subject = Unicode::mimeHeaderEncode($message['subject']); + $mail_subject = (new UnstructuredHeader('subject', $message['subject']))->getBodyAsString(); // Note: email 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 @@ -89,7 +90,7 @@ public function mail(array $message) { $mail_body = 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. - $mail_headers = implode("\n", $mimeheaders); + $mail_headers = implode("\n", $headers->toArray()); $request = \Drupal::request(); diff --git a/core/misc/cspell/dictionary.txt b/core/misc/cspell/dictionary.txt index a8fa87d2c26..e2446b4948a 100644 --- a/core/misc/cspell/dictionary.txt +++ b/core/misc/cspell/dictionary.txt @@ -933,7 +933,6 @@ middlewares midgardmvc mikey milli -mimeheaders mimetypes minifyzombies minimatch diff --git a/core/modules/file/file.module b/core/modules/file/file.module index f47fd3321a9..5ea9a18292c 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -21,9 +21,9 @@ use Drupal\Core\File\Event\FileUploadSanitizeNameEvent; use Drupal\file\FileInterface; use Drupal\Component\Utility\NestedArray; -use Drupal\Component\Utility\Unicode; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Template\Attribute; +use Symfony\Component\Mime\Header\UnstructuredHeader; use Symfony\Component\Mime\MimeTypeGuesserInterface; /** @@ -594,10 +594,10 @@ function file_save_data($data, $destination = NULL, $replace = FileSystemInterfa * \Symfony\Component\HttpFoundation\StreamedResponse. */ function file_get_content_headers(FileInterface $file) { - $type = Unicode::mimeHeaderEncode($file->getMimeType()); + $type = new UnstructuredHeader('Content-Type', $file->getMimeType()); return [ - 'Content-Type' => $type, + 'Content-Type' => $type->getBodyAsString(), 'Content-Length' => $file->getSize(), 'Cache-Control' => 'private', ]; diff --git a/core/modules/system/tests/src/Kernel/Mail/MailTest.php b/core/modules/system/tests/src/Kernel/Mail/MailTest.php index af593f3f137..ddd07d45050 100644 --- a/core/modules/system/tests/src/Kernel/Mail/MailTest.php +++ b/core/modules/system/tests/src/Kernel/Mail/MailTest.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\system\Kernel\Mail; use Drupal\Component\Utility\Random; -use Drupal\Component\Utility\Unicode; use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Mail\MailFormatHelper; use Drupal\Core\Mail\Plugin\Mail\TestMailCollector; @@ -147,9 +146,9 @@ public function testFromAndReplyToHeader() { $captured_emails = \Drupal::state()->get('system.test_mail_collector'); $sent_message = end($captured_emails); // From header is correctly encoded. - $this->assertEquals('=?UTF-8?B?RHLDqXBhbCB0aGlzIGlzIGEgdmVyeSBsb25nIHRlc3Qgc2VudGVuY2UgdG8gdGU=?= ', $sent_message['headers']['From']); + $this->assertEquals('=?utf-8?Q?Dr=C3=A9pal?= this is a very long test sentence to test what happens with very long site names ', $sent_message['headers']['From']); // From header is correctly encoded. - $this->assertEquals('Drépal this is a very long test sentence to te ', Unicode::mimeHeaderDecode($sent_message['headers']['From'])); + $this->assertEquals('Drépal this is a very long test sentence to test what happens with very long site names ', iconv_mime_decode($sent_message['headers']['From'])); $this->assertFalse(isset($sent_message['headers']['Reply-to']), 'Message reply-to is not set if not specified.'); // Errors-to header must not be set, it is deprecated. $this->assertFalse(isset($sent_message['headers']['Errors-To'])); @@ -179,9 +178,9 @@ public function testFromAndReplyToHeader() { $captured_emails = \Drupal::state()->get('system.test_mail_collector'); $sent_message = end($captured_emails); // From header is correctly encoded. - $this->assertEquals('=?UTF-8?B?RHLDqXBhbCwgInNpXHRlIg==?= ', $sent_message['headers']['From']); + $this->assertEquals('=?utf-8?Q?Dr=C3=A9pal=2C_=22si=5Cte=22?= ', $sent_message['headers']['From']); // From header is correctly encoded. - $this->assertEquals($site_name . ' ', Unicode::mimeHeaderDecode($sent_message['headers']['From'])); + $this->assertEquals($site_name . ' ', iconv_mime_decode($sent_message['headers']['From'])); } /** diff --git a/core/tests/Drupal/Tests/Component/Utility/MailTest.php b/core/tests/Drupal/Tests/Component/Utility/MailTest.php index 5f303289190..3c49979f6ee 100644 --- a/core/tests/Drupal/Tests/Component/Utility/MailTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/MailTest.php @@ -4,15 +4,18 @@ use Drupal\Component\Utility\Mail; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; /** * Test mail helpers implemented in Mail component. * * @group Utility + * @group legacy * * @coversDefaultClass \Drupal\Component\Utility\Mail */ class MailTest extends TestCase { + use ExpectDeprecationTrait; /** * Tests RFC-2822 'display-name' formatter. @@ -21,6 +24,7 @@ class MailTest extends TestCase { * @covers ::formatDisplayName */ public function testFormatDisplayName($string, $safe_display_name) { + $this->expectDeprecation('\Drupal\Component\Utility\Unicode::mimeHeaderEncode() is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use \Symfony\Component\Mime\Header\UnstructuredHeader instead. See https://www.drupal.org/node/3207439'); $this->assertEquals($safe_display_name, Mail::formatDisplayName($string)); } diff --git a/core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php b/core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php index 714078241a8..5315b0ed28f 100644 --- a/core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/UnicodeTest.php @@ -4,6 +4,7 @@ use Drupal\Component\Utility\Unicode; use PHPUnit\Framework\TestCase; +use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; /** * Test unicode handling features implemented in Unicode component. @@ -13,14 +14,17 @@ * @coversDefaultClass \Drupal\Component\Utility\Unicode */ class UnicodeTest extends TestCase { + use ExpectDeprecationTrait; /** * Tests multibyte encoding. * * @dataProvider providerTestMimeHeader * @covers ::mimeHeaderEncode + * @group legacy */ public function testMimeHeaderEncode($value, $encoded) { + $this->expectDeprecation('\Drupal\Component\Utility\Unicode::mimeHeaderEncode() is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use \Symfony\Component\Mime\Header\UnstructuredHeader instead. See https://www.drupal.org/node/3207439'); $this->assertEquals($encoded, Unicode::mimeHeaderEncode($value)); } @@ -44,8 +48,10 @@ public function providerTestMimeHeader() { * * @dataProvider providerTestMimeHeaderDecode * @covers ::mimeHeaderDecode + * @group legacy */ public function testMimeHeaderDecode($value, $encoded) { + $this->expectDeprecation('\Drupal\Component\Utility\Unicode::mimeHeaderDecode() is deprecated in drupal:9.2.0 and is removed from drupal:10.0.0. Use iconv_mime_decode() instead. See https://www.drupal.org/node/3207439'); $this->assertEquals($value, Unicode::mimeHeaderDecode($encoded)); }