diff --git a/composer.json b/composer.json index 334275fa..f70fe0dd 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,8 @@ "ext-fileinfo": "*", "nesbot/carbon": "^2.62.1|^3.2.4", "symfony/http-foundation": ">=2.8.0", - "illuminate/pagination": ">=5.0.0" + "illuminate/pagination": ">=5.0.0", + "qualityunit/tnef-decoder": "^1.2" }, "require-dev": { "phpunit/phpunit": "^9.5.10" diff --git a/src/Decoder/TNEFPartDecoder.php b/src/Decoder/TNEFPartDecoder.php new file mode 100644 index 00000000..022a59ba --- /dev/null +++ b/src/Decoder/TNEFPartDecoder.php @@ -0,0 +1,57 @@ +getEncoding() === 'base64') { + $content = base64_decode($payload); + } + $attachment = new TNEFAttachment(); + $attachment->decodeTnef($content); + $files = $attachment->getFiles(); + $parts = []; + foreach ($files as $file) { + $parts[] = new Part(base64_encode($file->content), $this->config, $this->createFakeHeaders($file), $part_number++); + } + return $parts; + } + + public function getEncoding(): string + { + return $this->headers->get('content_transfer_encoding')(); + } + + public static function isTNEFEncoded($headers): bool + { + return $headers->get("content_type")->contains("application/ms-tnef"); + } + + private function createFakeHeaders($file) + { + $fileName = $file->name ?? 'winmail.dat'; + $fileType = $file->type ?? 'application/ms-tnef'; + $fakeHeaders = [ + 'Content-Type' => "$fileType; name=\"$fileName \"", + 'Content-Description' => $fileName, + 'Content-Disposition' => 'attachment; filename=\"' . $fileName . '\"', + 'content_transfer_encoding' => 'base64', + ]; + $headers = implode( + "", + array_map(function ($key, $value) { + return $key . ": " . $value . "\r\n"; + }, array_keys($fakeHeaders), $fakeHeaders) + ); + + + return new Header($headers, $this->config); + } +} diff --git a/src/Structure.php b/src/Structure.php index cd296c49..e8f67e14 100644 --- a/src/Structure.php +++ b/src/Structure.php @@ -15,6 +15,7 @@ use Webklex\PHPIMAP\Exceptions\InvalidMessageDateException; use Webklex\PHPIMAP\Exceptions\MessageContentFetchingException; +use Webklex\PHPIMAP\Decoder\TNEFPartDecoder; /** * Class Structure @@ -120,6 +121,11 @@ private function parsePart(string $context, int $part_number = 0): array { } } + if (TNEFPartDecoder::isTNEFEncoded($headers)) { + $decoder = new TNEFPartDecoder($headers, $this->header->getConfig()); + return $decoder->decode($body, $part_number); + } + return [new Part($body, $this->header->getConfig(), $headers, $part_number)]; }