From 9cfd246982642119ad9f6744b38604948d646c58 Mon Sep 17 00:00:00 2001 From: Jeff W Date: Sat, 15 Mar 2025 09:17:54 -0400 Subject: [PATCH] Add a mail() hook to NativeMailHandler. (#1948) Allows subclassing NativeMailHandler so that the call to mail() can be intercepted and replaced in cases where additional processing needs to happen. Tests are mostly updated to use this method to test sent messages, but one test is added to make sure that everything gets passed through intact. Co-authored-by: JDW --- src/Monolog/Handler/NativeMailerHandler.php | 8 +++- .../Handler/NativeMailerHandlerTest.php | 48 +++++++++++++++---- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/Monolog/Handler/NativeMailerHandler.php b/src/Monolog/Handler/NativeMailerHandler.php index c68b1ddd..a5d1a977 100644 --- a/src/Monolog/Handler/NativeMailerHandler.php +++ b/src/Monolog/Handler/NativeMailerHandler.php @@ -128,7 +128,7 @@ class NativeMailerHandler extends MailHandler $parameters = implode(' ', $this->parameters); foreach ($this->to as $to) { - mail($to, $subject, $content, $headers, $parameters); + $this->mail($to, $subject, $content, $headers, $parameters); } } @@ -170,4 +170,10 @@ class NativeMailerHandler extends MailHandler return $this; } + + + protected function mail(string $to, string $subject, string $content, string $headers, string $parameters): void + { + mail($to, $subject, $content, $headers, $parameters); + } } diff --git a/tests/Monolog/Handler/NativeMailerHandlerTest.php b/tests/Monolog/Handler/NativeMailerHandlerTest.php index 81c1c04b..03e288bc 100644 --- a/tests/Monolog/Handler/NativeMailerHandlerTest.php +++ b/tests/Monolog/Handler/NativeMailerHandlerTest.php @@ -26,6 +26,21 @@ class NativeMailerHandlerTest extends TestCase $GLOBALS['mail'] = []; } + protected function newNativeMailerHandler( ... $args ) : NativeMailerHandler + { + return new class( ... $args ) extends NativeMailerHandler { + + public $mail = []; + + protected function mail( string $to, string $subject, string $content, + string $headers, string $parameters ) : void + { + $this->mail[] = \func_get_args(); + } + + }; + } + public function testConstructorHeaderInjection() { $this->expectException(\InvalidArgumentException::class); @@ -71,19 +86,19 @@ class NativeMailerHandlerTest extends TestCase $subject = 'dear victim'; $from = 'receiver@example.org'; - $mailer = new NativeMailerHandler($to, $subject, $from); + $mailer = $this->newNativeMailerHandler($to, $subject, $from); $mailer->setFormatter(new \Monolog\Formatter\LineFormatter); $mailer->handleBatch([]); // batch is empty, nothing sent - $this->assertEmpty($GLOBALS['mail']); + $this->assertEmpty($mailer->mail); // non-empty batch $mailer->handle($this->getRecord(Level::Error, "Foo\nBar\r\n\r\nBaz")); - $this->assertNotEmpty($GLOBALS['mail']); - $this->assertIsArray($GLOBALS['mail']); - $this->assertArrayHasKey('0', $GLOBALS['mail']); - $params = $GLOBALS['mail'][0]; + $this->assertNotEmpty($mailer->mail); + $this->assertIsArray($mailer->mail); + $this->assertArrayHasKey('0', $mailer->mail); + $params = $mailer->mail[0]; $this->assertCount(5, $params); $this->assertSame($to, $params[0]); $this->assertSame($subject, $params[1]); @@ -94,13 +109,30 @@ class NativeMailerHandlerTest extends TestCase public function testMessageSubjectFormatting() { - $mailer = new NativeMailerHandler('to@example.org', 'Alert: %level_name% %message%', 'from@example.org'); + $mailer = $this->newNativeMailerHandler('to@example.org', 'Alert: %level_name% %message%', 'from@example.org'); $mailer->handle($this->getRecord(Level::Error, "Foo\nBar\r\n\r\nBaz")); + $this->assertNotEmpty($mailer->mail); + $this->assertIsArray($mailer->mail); + $this->assertArrayHasKey('0', $mailer->mail); + $params = $mailer->mail[0]; + $this->assertCount(5, $params); + $this->assertSame('Alert: ERROR Foo Bar Baz', $params[1]); + } + + public function testMail() + { + $mailer = new NativeMailerHandler('to@example.org', 'subject', 'from@example.org' ); + $mailer->addParameter( 'foo' ); + $mailer->handle($this->getRecord(Level::Error, "FooBarBaz")); $this->assertNotEmpty($GLOBALS['mail']); $this->assertIsArray($GLOBALS['mail']); $this->assertArrayHasKey('0', $GLOBALS['mail']); $params = $GLOBALS['mail'][0]; $this->assertCount(5, $params); - $this->assertSame('Alert: ERROR Foo Bar Baz', $params[1]); + $this->assertSame('to@example.org', $params[0]); + $this->assertSame('subject', $params[1]); + $this->assertStringContainsString("FooBarBaz", $params[2]); + $this->assertStringContainsString( 'From: from@example.org', $params[3] ); + $this->assertSame( 'foo', $params[4] ); } }