From b0ffd67775074a828d22df99c774e8ebd9dcc627 Mon Sep 17 00:00:00 2001 From: Frank Forte Date: Sat, 25 Nov 2023 12:34:39 -0500 Subject: [PATCH 1/2] Update replaceCustomerHeader to remove duplicates. Improve clearCustomHeader and relaceCustomHeader to handle name: value. --- src/PHPMailer.php | 48 ++++++++++++++++++++++++++--- test/PHPMailer/CustomHeaderTest.php | 27 +++++++++++++++- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/PHPMailer.php b/src/PHPMailer.php index 6c7070af..073ff489 100644 --- a/src/PHPMailer.php +++ b/src/PHPMailer.php @@ -4059,24 +4059,63 @@ class PHPMailer } /** - * Clear a specific custom header. + * Clear a specific custom header by name or name and value. + * $name value can be overloaded to contain + * both header name and value (name:value). + * + * @param string $name Custom header name + * @param string|null $value Header value + * + * @return bool True if a header was replaced successfully */ - public function clearCustomHeader($name) + public function clearCustomHeader($name, $value = null) { + if (null === $value && strpos($name, ':') !== false) { + //Value passed in as name:value + list($name, $value) = explode(':', $name, 2); + } + $name = trim($name); + $value = (null === $value) ? null : trim($value); + foreach ($this->CustomHeader as $k => $pair) { if ($pair[0] == $name) { - unset($this->CustomHeader[$k]); + // We remove the header if the value is not provided or it matches. + if (null === $value || $pair[1] == $value) { + unset($this->CustomHeader[$k]); + } } } + + return true; } /** * Replace a custom header. + * $name value can be overloaded to contain + * both header name and value (name:value). + * + * @param string $name Custom header name + * @param string|null $value Header value + * + * @return bool True if a header was replaced successfully + * @throws Exception */ - public function replaceCustomHeader($name, $value) + public function replaceCustomHeader($name, $value = null) { + if (null === $value && strpos($name, ':') !== false) { + //Value passed in as name:value + list($name, $value) = explode(':', $name, 2); + } + $name = trim($name); + $value = (null === $value) ? '' : trim($value); + + $replaced = false; foreach ($this->CustomHeader as $k => $pair) { if ($pair[0] == $name) { + if ($replaced) { + unset( $this->CustomHeader[$k]); + continue; + } if (strpbrk($name . $value, "\r\n") !== false) { if ($this->exceptions) { throw new Exception($this->lang('invalid_header')); @@ -4085,6 +4124,7 @@ class PHPMailer return false; } $this->CustomHeader[$k] = [$name, $value]; + $replaced = true; } } diff --git a/test/PHPMailer/CustomHeaderTest.php b/test/PHPMailer/CustomHeaderTest.php index 58c123a3..89c1c806 100644 --- a/test/PHPMailer/CustomHeaderTest.php +++ b/test/PHPMailer/CustomHeaderTest.php @@ -197,8 +197,10 @@ final class CustomHeaderTest extends TestCase */ public function testClearCustomHeader() { + // make sure 'foo' is cleared, even if there is more than one header set. $this->Mail->addCustomHeader('foo', 'bar'); - self::assertSame([['foo', 'bar']], $this->Mail->getCustomHeaders()); + $this->Mail->addCustomHeader('foo', 'baz'); + self::assertSame([['foo', 'bar'], ['foo', 'baz']], $this->Mail->getCustomHeaders()); $this->Mail->clearCustomHeader('foo'); @@ -207,6 +209,29 @@ final class CustomHeaderTest extends TestCase self::assertEmpty($cleared); } + /** + * Test removing previously set custom header value. + * + * @covers \PHPMailer\PHPMailer\PHPMailer::clearCustomHeader + */ + public function testClearCustomHeaderValue() + { + // Test clearing 'name', 'value' + $this->Mail->addCustomHeader('foo', 'bar'); + $this->Mail->addCustomHeader('foo', 'baz'); + self::assertSame([['foo', 'bar'], ['foo', 'baz']], $this->Mail->getCustomHeaders()); + + $this->Mail->clearCustomHeader('foo', 'bar'); + self::assertSame($this->Mail->getCustomHeaders(), [1 => ['foo', 'baz']]); + + // Test clearing 'name: value' + $this->Mail->addCustomHeader('foo', 'bar'); + self::assertSame([1 => ['foo', 'baz'], 2 => ['foo', 'bar']], $this->Mail->getCustomHeaders()); + + $this->Mail->clearCustomHeader('foo: bar'); + self::assertSame([1 => ['foo', 'baz']], $this->Mail->getCustomHeaders()); + } + /** * Test removing previously set custom headers. * From 8a91dd64f4447edd0aa7111ac859dbf2ad9f4450 Mon Sep 17 00:00:00 2001 From: Frank Forte Date: Sat, 25 Nov 2023 13:48:53 -0500 Subject: [PATCH 2/2] Code formatting for custom header methods. --- src/PHPMailer.php | 2 +- test/PHPMailer/CustomHeaderTest.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/PHPMailer.php b/src/PHPMailer.php index 073ff489..c03eee05 100644 --- a/src/PHPMailer.php +++ b/src/PHPMailer.php @@ -4113,7 +4113,7 @@ class PHPMailer foreach ($this->CustomHeader as $k => $pair) { if ($pair[0] == $name) { if ($replaced) { - unset( $this->CustomHeader[$k]); + unset($this->CustomHeader[$k]); continue; } if (strpbrk($name . $value, "\r\n") !== false) { diff --git a/test/PHPMailer/CustomHeaderTest.php b/test/PHPMailer/CustomHeaderTest.php index 89c1c806..0f416469 100644 --- a/test/PHPMailer/CustomHeaderTest.php +++ b/test/PHPMailer/CustomHeaderTest.php @@ -222,14 +222,14 @@ final class CustomHeaderTest extends TestCase self::assertSame([['foo', 'bar'], ['foo', 'baz']], $this->Mail->getCustomHeaders()); $this->Mail->clearCustomHeader('foo', 'bar'); - self::assertSame($this->Mail->getCustomHeaders(), [1 => ['foo', 'baz']]); + self::assertSame([['foo', 'baz']], array_values($this->Mail->getCustomHeaders())); // Test clearing 'name: value' $this->Mail->addCustomHeader('foo', 'bar'); - self::assertSame([1 => ['foo', 'baz'], 2 => ['foo', 'bar']], $this->Mail->getCustomHeaders()); + self::assertSame([['foo', 'baz'], ['foo', 'bar']], array_values($this->Mail->getCustomHeaders())); $this->Mail->clearCustomHeader('foo: bar'); - self::assertSame([1 => ['foo', 'baz']], $this->Mail->getCustomHeaders()); + self::assertSame([['foo', 'baz']], array_values($this->Mail->getCustomHeaders())); } /**