Skip to content

Commit

Permalink
Merge pull request #511 from qligier/fix-email-name
Browse files Browse the repository at this point in the history
Add support for commas and semicolons in email name and add test
  • Loading branch information
thinkingserious authored Mar 28, 2018
2 parents 76aa1e1 + 8820dfc commit 02b4840
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 6 deletions.
68 changes: 62 additions & 6 deletions lib/helpers/mail/Mail.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ class ReplyTo implements \JsonSerializable

public function __construct($email, $name = null)
{
$this->email = $email;
$this->setEmail($email);

if (!is_null($name)) {
$this->name = $name;
$this->setName($name);
}
}

Expand All @@ -38,7 +38,35 @@ public function getEmail()

public function setName($name)
{
$this->name = $name;
/*
Issue #368
==========
If the name is not wrapped in double quotes and contains a comma or
semicolon, the API fails to parse it correctly.
When wrapped in double quotes, commas, semicolons and unescaped single
quotes are supported.
Escaped double quotes are supported as well but will appear unescaped in
the mail (e.g. "O\'Keefe").
Double quotes will be shown in some email clients, so the name should
only be wrapped when necessary.
*/

// Only wrapp in double quote if comma or semicolon are found
if (false !== strpos($name, ',') || false !== strpos($name, ';')) {
// Unescape quotes
$name = stripslashes(html_entity_decode($name, ENT_QUOTES));

// Escape only double quotes
$name = str_replace('"', '\\"', $name);

// Wrapp in double quotes
$name = '"' . $name . '"';
}

$this->name = (!empty($name)) ? $name : null;
}

public function getName()
Expand Down Expand Up @@ -897,13 +925,41 @@ class Email implements \JsonSerializable

public function __construct($name, $email)
{
$this->name = $name;
$this->email = $email;
$this->setName($name);
$this->setEmail($email);
}

public function setName($name)
{
$this->name = $name;
/*
Issue #368
==========
If the name is not wrapped in double quotes and contains a comma or
semicolon, the API fails to parse it correctly.
When wrapped in double quotes, commas, semicolons and unescaped single
quotes are supported.
Escaped double quotes are supported as well but will appear unescaped in
the mail (e.g. "O\'Keefe").
Double quotes will be shown in some email clients, so the name should
only be wrapped when necessary.
*/

// Only wrapp in double quote if comma or semicolon are found
if (false !== strpos($name, ',') || false !== strpos($name, ';')) {
// Unescape quotes
$name = stripslashes(html_entity_decode($name, ENT_QUOTES));

// Escape only double quotes
$name = str_replace('"', '\\"', $name);

// Wrapp in double quotes
$name = '"' . $name . '"';
}

$this->name = (!empty($name)) ? $name : null;
}

public function getName()
Expand Down
31 changes: 31 additions & 0 deletions test/unit/Mail/MailHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,35 @@ public function testKitchenSinkExample()

$this->assertEquals($json, '{"from":{"name":"DX","email":"test@example.com"},"personalizations":[{"to":[{"name":"Example User","email":"test@example.com"},{"name":"Example User","email":"test@example.com"}],"cc":[{"name":"Example User","email":"test@example.com"},{"name":"Example User","email":"test@example.com"}],"bcc":[{"name":"Example User","email":"test@example.com"},{"name":"Example User","email":"test@example.com"}],"subject":"Hello World from the SendGrid PHP Library","headers":{"X-Test":"test","X-Mock":"true"},"substitutions":{"%name%":"Example User","%city%":"Denver"},"custom_args":{"user_id":"343","type":"marketing"},"send_at":1443636843},{"to":[{"name":"Example User","email":"test@example.com"},{"name":"Example User","email":"test@example.com"}],"cc":[{"name":"Example User","email":"test@example.com"},{"name":"Example User","email":"test@example.com"}],"bcc":[{"name":"Example User","email":"test@example.com"},{"name":"Example User","email":"test@example.com"}],"subject":"Hello World from the SendGrid PHP Library","headers":{"X-Test":"test","X-Mock":"true"},"substitutions":{"%name%":"Example User","%city%":"Denver"},"custom_args":{"user_id":"343","type":"marketing"},"send_at":1443636843}],"subject":"Hello World from the SendGrid PHP Library","content":[{"type":"text\/plain","value":"some text here"},{"type":"text\/html","value":"<html><body>some text here<\/body><\/html>"}],"attachments":[{"content":"TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gQ3JhcyBwdW12","type":"application\/pdf","filename":"balance_001.pdf","disposition":"attachment","content_id":"Balance Sheet"},{"content":"BwdW","type":"image\/png","filename":"banner.png","disposition":"inline","content_id":"Banner"}],"template_id":"439b6d66-4408-4ead-83de-5c83c2ee313a","sections":{"%section1%":"Substitution Text for Section 1","%section2%":"Substitution Text for Section 2"},"headers":{"X-Test1":"1","X-Test2":"2"},"categories":["May","2016"],"custom_args":{"campaign":"welcome","weekday":"morning"},"send_at":1443636842,"asm":{"group_id":99,"groups_to_display":[4,5,6,7,8]},"ip_pool_name":"23","mail_settings":{"bcc":{"enable":true,"email":"test@example.com"},"bypass_list_management":{"enable":true},"footer":{"enable":true,"text":"Footer Text","html":"<html><body>Footer Text<\/body><\/html>"},"sandbox_mode":{"enable":true},"spam_check":{"enable":true,"threshold":1,"post_to_url":"https:\/\/spamcatcher.sendgrid.com"}},"tracking_settings":{"click_tracking":{"enable":true,"enable_text":true},"open_tracking":{"enable":true,"substitution_tag":"Optional tag to replace with the open image in the body of the message"},"subscription_tracking":{"enable":true,"text":"text to insert into the text\/plain portion of the message","html":"<html><body>html to insert into the text\/html portion of the message<\/body><\/html>","substitution_tag":"Optional tag to replace with the open image in the body of the message"},"ganalytics":{"enable":true,"utm_source":"some source","utm_medium":"some medium","utm_term":"some term","utm_content":"some content","utm_campaign":"some name"}},"reply_to":{"email":"test@example.com"}}');
}

public function testEmailName()
{
$email = new Email('John Doe', 'test@example.com');
$json = json_encode($email->jsonSerialize());
$this->assertEquals($json, '{"name":"John Doe","email":"test@example.com"}');

$email->setName('');
$json = json_encode($email->jsonSerialize());
$this->assertEquals($json, '{"email":"test@example.com"}');

$email->setName(null);
$json = json_encode($email->jsonSerialize());
$this->assertEquals($json, '{"email":"test@example.com"}');

$email->setName('Doe, John');
$json = json_encode($email->jsonSerialize());
$this->assertEquals($json, '{"name":"\\"Doe, John\\"","email":"test@example.com"}');

$email->setName('Doe; John');
$json = json_encode($email->jsonSerialize());
$this->assertEquals($json, '{"name":"\\"Doe; John\\"","email":"test@example.com"}');

$email->setName('John "Billy" O\'Keeffe');
$json = json_encode($email->jsonSerialize());
$this->assertEquals($json, '{"name":"John \\"Billy\\" O\'Keeffe","email":"test@example.com"}');

$email->setName('O\'Keeffe, John "Billy"');
$json = json_encode($email->jsonSerialize());
$this->assertEquals($json, '{"name":"\\"O\'Keeffe, John \\\\\\"Billy\\\\\\"\\"","email":"test@example.com"}');
}
}

0 comments on commit 02b4840

Please sign in to comment.