From 6d57118b3d536b887145abce1ae3ac3158dd80d6 Mon Sep 17 00:00:00 2001 From: Roj Vroemen Date: Wed, 17 Jan 2024 18:47:26 +0100 Subject: [PATCH 1/2] Handle multipart messages and only decode content --- .../Mail/Transport/LogTransport.php | 31 +++++++++++++++++-- tests/Mail/MailLogTransportTest.php | 27 ++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Mail/Transport/LogTransport.php b/src/Illuminate/Mail/Transport/LogTransport.php index 291251200a48..7d803feef33a 100644 --- a/src/Illuminate/Mail/Transport/LogTransport.php +++ b/src/Illuminate/Mail/Transport/LogTransport.php @@ -33,10 +33,21 @@ public function __construct(LoggerInterface $logger) */ public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage { - $string = $message->toString(); + $string = str($message->toString()); - if (str_contains($string, 'Content-Transfer-Encoding: quoted-printable')) { - $string = quoted_printable_decode($string); + if ($string->contains('Content-Type: multipart/')) { + $boundary = $string + ->after('boundary=') + ->before("\r\n") + ->prepend('--') + ->append("\r\n"); + + $string = $string + ->explode($boundary) + ->map($this->decodeQuotedPrintableContent(...)) + ->implode($boundary); + } elseif ($string->contains('Content-Transfer-Encoding: quoted-printable')) { + $string = $this->decodeQuotedPrintableContent($string); } $this->logger->debug($string); @@ -44,6 +55,20 @@ public function send(RawMessage $message, Envelope $envelope = null): ?SentMessa return new SentMessage($message, $envelope ?? Envelope::create($message)); } + protected function decodeQuotedPrintableContent(string $part): string + { + if (! str_contains($part, 'Content-Transfer-Encoding: quoted-printable')) { + return $part; + } + + [$headers, $content] = explode("\r\n\r\n", $part, 2); + + return implode("\r\n\r\n", [ + $headers, + quoted_printable_decode($content), + ]); + } + /** * Get the logger for the LogTransport instance. * diff --git a/tests/Mail/MailLogTransportTest.php b/tests/Mail/MailLogTransportTest.php index 3bb0c69a44df..33367d52610c 100644 --- a/tests/Mail/MailLogTransportTest.php +++ b/tests/Mail/MailLogTransportTest.php @@ -2,6 +2,7 @@ namespace Illuminate\Tests\Mail; +use Illuminate\Mail\Attachment; use Illuminate\Mail\Message; use Illuminate\Mail\Transport\LogTransport; use Monolog\Handler\StreamHandler; @@ -59,6 +60,32 @@ public function testItDecodesTheMessageBeforeLogging() $this->assertStringContainsString('https://example.com/reset-password=5e113c71a4c210aff04b3fa66f1b1299', $actualLoggedValue); } + public function testItOnlyDecodesQuotedPrintablePartsOfTheMessageBeforeLogging() + { + $message = (new Message(new Email)) + ->from('noreply@example.com', 'no-reply') + ->to('taylor@example.com', 'Taylor') + ->html(<<<'BODY' + Hi, + + Click here to reset your password. + + All the best, + + Burt & Irving + BODY) + ->text('A text part') + ->attach(Attachment::fromData(fn () => 'My attachment', 'attachment.txt')); + + $actualLoggedValue = $this->getLoggedEmailMessage($message); + + $this->assertStringContainsString('href=', $actualLoggedValue); + $this->assertStringContainsString('Burt & Irving', $actualLoggedValue); + $this->assertStringContainsString('https://example.com/reset-password=5e113c71a4c210aff04b3fa66f1b1299', $actualLoggedValue); + $this->assertStringContainsString('name=attachment.txt', $actualLoggedValue); + $this->assertStringContainsString('filename=attachment.txt', $actualLoggedValue); + } + public function testGetLogTransportWithPsrLogger() { $this->app['config']->set('mail.driver', 'log'); From 79652bbb40e089675742e2aad35af5df3262a47e Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Thu, 18 Jan 2024 09:38:26 -0600 Subject: [PATCH 2/2] formatting --- src/Illuminate/Mail/Transport/LogTransport.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Mail/Transport/LogTransport.php b/src/Illuminate/Mail/Transport/LogTransport.php index 7d803feef33a..682169e3eaa7 100644 --- a/src/Illuminate/Mail/Transport/LogTransport.php +++ b/src/Illuminate/Mail/Transport/LogTransport.php @@ -2,6 +2,7 @@ namespace Illuminate\Mail\Transport; +use Illuminate\Support\Str; use Psr\Log\LoggerInterface; use Symfony\Component\Mailer\Envelope; use Symfony\Component\Mailer\SentMessage; @@ -33,7 +34,7 @@ public function __construct(LoggerInterface $logger) */ public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage { - $string = str($message->toString()); + $string = Str::of($message->toString()); if ($string->contains('Content-Type: multipart/')) { $boundary = $string @@ -50,12 +51,18 @@ public function send(RawMessage $message, Envelope $envelope = null): ?SentMessa $string = $this->decodeQuotedPrintableContent($string); } - $this->logger->debug($string); + $this->logger->debug((string) $string); return new SentMessage($message, $envelope ?? Envelope::create($message)); } - protected function decodeQuotedPrintableContent(string $part): string + /** + * Decode the given quoted printable content. + * + * @param string $part + * @return string + */ + protected function decodeQuotedPrintableContent(string $part) { if (! str_contains($part, 'Content-Transfer-Encoding: quoted-printable')) { return $part;