Page MenuHomePhabricator

D19026.id45622.diff
No OneTemporary

D19026.id45622.diff

diff --git a/src/parser/PhutilEmailAddress.php b/src/parser/PhutilEmailAddress.php
--- a/src/parser/PhutilEmailAddress.php
+++ b/src/parser/PhutilEmailAddress.php
@@ -12,7 +12,7 @@
private $localPart;
private $domainName;
- public function __construct($email_address) {
+ public function __construct($email_address = null) {
$email_address = trim($email_address);
$matches = null;
@@ -41,8 +41,9 @@
public function __toString() {
$address = $this->getAddress();
- if ($this->displayName) {
- return $this->displayName.' <'.$address.'>';
+ if (strlen($this->displayName)) {
+ $display_name = $this->encodeDisplayName($this->displayName);
+ return $display_name.' <'.$address.'>';
} else {
return $address;
}
@@ -75,12 +76,39 @@
return $this->domainName;
}
+ public function setAddress($address) {
+ $parts = explode('@', $address, 2);
+
+ $this->localPart = $parts[0];
+ if (isset($parts[1])) {
+ $this->domainName = $parts[1];
+ }
+
+ return $this;
+ }
+
public function getAddress() {
$address = $this->localPart;
- if ($this->domainName) {
+ if (strlen($this->domainName)) {
$address .= '@'.$this->domainName;
}
return $address;
}
+ private function encodeDisplayName($name) {
+ // NOTE: This is a reasonable effort based on a cursory reading of
+ // RFC2822, but may be significantly misguided.
+
+ // Newlines are not permitted, even when escaped. Discard them.
+ $name = preg_replace("/\s*[\r\n]+\s*/", ' ', $name);
+
+ // Escape double quotes and backslashes.
+ $name = addcslashes($name, '\\"');
+
+ // Quote the string.
+ $name = '"'.$name.'"';
+
+ return $name;
+ }
+
}
diff --git a/src/parser/__tests__/PhutilEmailAddressTestCase.php b/src/parser/__tests__/PhutilEmailAddressTestCase.php
--- a/src/parser/__tests__/PhutilEmailAddressTestCase.php
+++ b/src/parser/__tests__/PhutilEmailAddressTestCase.php
@@ -91,4 +91,40 @@
$email->getAddress());
}
+ public function testEmailEncoding() {
+ $cases = array(
+ array(
+ 'Tangerine Q. Hawthorne',
+ 'thawthorne@blackspire.bunker',
+ '"Tangerine Q. Hawthorne" <thawthorne@blackspire.bunker>',
+ ),
+ array(
+ 'Hector "\\" Backslash',
+ 'hector@backslash',
+ '"Hector \\"\\\\\\" Backslash" <hector@backslash>',
+ ),
+ array(
+ 'My Middle Name "<name@domain>" Is My Email',
+ 'name@domain',
+ '"My Middle Name \\"<name@domain>\\" Is My Email" <name@domain>',
+ ),
+ array(
+ "My Legal Name\nContains A Newline",
+ 'newline@example',
+ '"My Legal Name Contains A Newline" <newline@example>',
+ ),
+ );
+
+ foreach ($cases as $case) {
+ list($name, $address, $expect) = $case;
+ $actual = (string)id(new PhutilEmailAddress())
+ ->setDisplayName($name)
+ ->setAddress($address);
+ $this->assertEqual(
+ $expect,
+ $actual,
+ pht('Email: %s + %s -> %s', $name, $address, $expect));
+ }
+ }
+
}

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 19, 4:24 AM (2 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6711267
Default Alt Text
D19026.id45622.diff (3 KB)

Event Timeline