Skip to content

Commit 8c2e128

Browse files
committed
feature #33091 [Mime] Add Address::fromString (gisostallenberg)
This PR was merged into the 4.4 branch. Discussion ---------- [Mime] Add Address::fromString | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #33086 | License | MIT | Doc PR | symfony/symfony-docs#12128 This will allow to create a Address from a string such as 'Name <name@example.com>' Example: ```php $address = Address::fromString("Name <name@example.com>"); ``` Commits ------- 75ea8d0 Add Address::fromString
2 parents a77e326 + 75ea8d0 commit 8c2e128

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

src/Symfony/Component/Mime/Address.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@
2323
*/
2424
final class Address
2525
{
26+
/**
27+
* A regex that matches a structure like 'Name <email@address.com>'.
28+
* It matches anything between the first < and last > as email address.
29+
* This allows to use a single string to construct an Address, which can be convenient to use in
30+
* config, and allows to have more readable config.
31+
* This does not try to cover all edge cases for address.
32+
*/
33+
private const FROM_STRING_PATTERN = '~(?<displayName>[^<]*)<(?<addrSpec>.*)>[^>]*~';
34+
2635
private static $validator;
2736
private static $encoder;
2837

@@ -100,4 +109,15 @@ public static function createArray(array $addresses): array
100109

101110
return $addrs;
102111
}
112+
113+
public static function fromString(string $string): self
114+
{
115+
if (false === strpos($string, '<')) {
116+
return new self($string, '');
117+
}
118+
if (!preg_match(self::FROM_STRING_PATTERN, $string, $matches)) {
119+
throw new InvalidArgumentException(sprintf('Could not parse "%s" to a "%s" instance.', $string, static::class));
120+
}
121+
return new self($matches['addrSpec'], trim($matches['displayName'], ' \'"'));
122+
}
103123
}

src/Symfony/Component/Mime/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* [BC BREAK] Removed `NamedAddress` (`Address` now supports a name)
88
* Added PHPUnit constraints
99
* Added `AbstractPart::asDebugString()`
10+
* Added `Address::fromString()`
1011

1112
4.3.3
1213
-----

src/Symfony/Component/Mime/Tests/AddressTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Mime\Address;
16+
use Symfony\Component\Mime\Exception\InvalidArgumentException;
1617

1718
class AddressTest extends TestCase
1819
{
@@ -77,4 +78,79 @@ public function nameEmptyDataProvider(): array
7778
{
7879
return [[''], [' '], [" \r\n "]];
7980
}
81+
82+
/**
83+
* @dataProvider fromStringProvider
84+
*/
85+
public function testFromString($string, $displayName, $addrSpec)
86+
{
87+
$address = Address::fromString($string);
88+
$this->assertEquals($displayName, $address->getName());
89+
$this->assertEquals($addrSpec, $address->getAddress());
90+
$fromToStringAddress = Address::fromString($address->toString());
91+
$this->assertEquals($displayName, $fromToStringAddress->getName());
92+
$this->assertEquals($addrSpec, $fromToStringAddress->getAddress());
93+
}
94+
95+
public function testFromStringFailure()
96+
{
97+
$this->expectException(InvalidArgumentException::class);
98+
Address::fromString('Jane Doe <example@example.com');
99+
}
100+
101+
public function fromStringProvider()
102+
{
103+
return [
104+
[
105+
'example@example.com',
106+
'',
107+
'example@example.com',
108+
],
109+
[
110+
'<example@example.com>',
111+
'',
112+
'example@example.com',
113+
],
114+
[
115+
'Jane Doe <example@example.com>',
116+
'Jane Doe',
117+
'example@example.com',
118+
],
119+
[
120+
'Jane Doe<example@example.com>',
121+
'Jane Doe',
122+
'example@example.com',
123+
],
124+
[
125+
'\'Jane Doe\' <example@example.com>',
126+
'Jane Doe',
127+
'example@example.com',
128+
],
129+
[
130+
'"Jane Doe" <example@example.com>',
131+
'Jane Doe',
132+
'example@example.com',
133+
],
134+
[
135+
'Jane Doe <"ex<ample"@example.com>',
136+
'Jane Doe',
137+
'"ex<ample"@example.com',
138+
],
139+
[
140+
'Jane Doe <"ex<amp>le"@example.com>',
141+
'Jane Doe',
142+
'"ex<amp>le"@example.com',
143+
],
144+
[
145+
'Jane Doe > <"ex<am p>le"@example.com>',
146+
'Jane Doe >',
147+
'"ex<am p>le"@example.com',
148+
],
149+
[
150+
'Jane Doe <example@example.com>discarded',
151+
'Jane Doe',
152+
'example@example.com',
153+
],
154+
];
155+
}
80156
}

0 commit comments

Comments
 (0)