From 2b28a56d8ac9a2393924a0b201cc39bd86fc4d15 Mon Sep 17 00:00:00 2001 From: "Alexia E. Smith" Date: Tue, 10 Apr 2018 17:10:33 -0500 Subject: [PATCH] mail: Always quote uncoded names in MailAddress Otherwise, names that contain whitespace (but no special characters that need Q-encoding) will be sent as-is in an email header. While that's valid by RFC 1036, RFC 5322 and others, some mail programs fail to correctly process spaces. Avoid these problems by simply quoting the name always - except for cases which are Q-encoded, which must remain unquoted to be valid (and also cannot contain spaces, thus unaffected). Before: > From: Foo Bar After: > From "Foo Bar" Update test to work with the new criteria. Bug: T191931 Change-Id: I4b2a0a80e8b43ecc943939fc5ebaa356a4f840e0 --- includes/mail/MailAddress.php | 5 +++-- tests/phpunit/includes/mail/MailAddressTest.php | 17 +++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/includes/mail/MailAddress.php b/includes/mail/MailAddress.php index 1686bbb048..b9d94143d0 100644 --- a/includes/mail/MailAddress.php +++ b/includes/mail/MailAddress.php @@ -88,8 +88,9 @@ class MailAddress { global $wgEnotifUseRealName; $name = ( $wgEnotifUseRealName && $this->realName !== '' ) ? $this->realName : $this->name; $quoted = UserMailer::quotedPrintable( $name ); - if ( strpos( $quoted, '.' ) !== false || strpos( $quoted, ',' ) !== false ) { - $quoted = '"' . $quoted . '"'; + // Must only be quoted if string does not use =? encoding (T191931) + if ( $quoted === $name ) { + $quoted = '"' . addslashes( $quoted ) . '"'; } return "$quoted <{$this->address}>"; } else { diff --git a/tests/phpunit/includes/mail/MailAddressTest.php b/tests/phpunit/includes/mail/MailAddressTest.php index d0bd698084..459f5cc4f5 100644 --- a/tests/phpunit/includes/mail/MailAddressTest.php +++ b/tests/phpunit/includes/mail/MailAddressTest.php @@ -31,9 +31,9 @@ class MailAddressTest extends MediaWikiTestCase { $ma = MailAddress::newFromUser( $user ); $this->assertInstanceOf( MailAddress::class, $ma ); $this->setMwGlobals( 'wgEnotifUseRealName', true ); - $this->assertEquals( 'Real name ', $ma->toString() ); + $this->assertEquals( '"Real name" ', $ma->toString() ); $this->setMwGlobals( 'wgEnotifUseRealName', false ); - $this->assertEquals( 'UserName ', $ma->toString() ); + $this->assertEquals( '"UserName" ', $ma->toString() ); } /** @@ -51,11 +51,16 @@ class MailAddressTest extends MediaWikiTestCase { public static function provideToString() { return [ - [ true, 'foo@bar.baz', 'FooBar', 'Foo Bar', 'Foo Bar ' ], - [ true, 'foo@bar.baz', 'UserName', null, 'UserName ' ], - [ true, 'foo@bar.baz', 'AUser', 'My real name', 'My real name ' ], + [ true, 'foo@bar.baz', 'FooBar', 'Foo Bar', '"Foo Bar" ' ], + [ true, 'foo@bar.baz', 'UserName', null, '"UserName" ' ], + [ true, 'foo@bar.baz', 'AUser', 'My real name', '"My real name" ' ], + [ true, 'foo@bar.baz', 'AUser', 'My "real" name', '"My \"real\" name" ' ], + [ true, 'foo@bar.baz', 'AUser', 'My "A/B" test', '"My \"A/B\" test" ' ], + [ true, 'foo@bar.baz', 'AUser', 'E=MC2', '=?UTF-8?Q?E=3DMC2?= ' ], + // A backslash (\) should be escaped (\\). In a string literal that is \\\\ (4x). + [ true, 'foo@bar.baz', 'AUser', 'My "B\C" test', '"My \"B\\\\C\" test" ' ], [ true, 'foo@bar.baz', 'A.user.name', 'my@real.name', '"my@real.name" ' ], - [ false, 'foo@bar.baz', 'AUserName', 'Some real name', 'AUserName ' ], + [ false, 'foo@bar.baz', 'AUserName', 'Some real name', '"AUserName" ' ], [ false, 'foo@bar.baz', '', '', 'foo@bar.baz' ], [ true, 'foo@bar.baz', '', '', 'foo@bar.baz' ], [ true, '', '', '', '' ], -- 2.20.1