Skip to content

Commit

Permalink
[10.x] Fix decoding issue in MailLogTransport (#49727)
Browse files Browse the repository at this point in the history
* Handle multipart messages and only decode content

* formatting

---------

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
rojtjo and taylorotwell authored Jan 18, 2024
1 parent c62d15b commit 3acc1d0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
40 changes: 36 additions & 4 deletions src/Illuminate/Mail/Transport/LogTransport.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -33,17 +34,48 @@ public function __construct(LoggerInterface $logger)
*/
public function send(RawMessage $message, Envelope $envelope = null): ?SentMessage
{
$string = $message->toString();
$string = Str::of($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);
$this->logger->debug((string) $string);

return new SentMessage($message, $envelope ?? Envelope::create($message));
}

/**
* 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;
}

[$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.
*
Expand Down
27 changes: 27 additions & 0 deletions tests/Mail/MailLogTransportTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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('[email protected]', 'no-reply')
->to('[email protected]', 'Taylor')
->html(<<<'BODY'
Hi,
<a href="https://example.com/reset-password=5e113c71a4c210aff04b3fa66f1b1299">Click here to reset your password</a>.
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');
Expand Down

0 comments on commit 3acc1d0

Please sign in to comment.