Skip to content

Commit 1d04819

Browse files
committed
fix: decoding preview texts
Respect the content type charset when decoding bodies to use when generating preview texts. Signed-off-by: Richard Steinmetz <[email protected]>
1 parent 6aaf571 commit 1d04819

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed

lib/IMAP/MessageMapper.php

+37-11
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@
3535
use Horde_Imap_Client_Socket;
3636
use Horde_Mime_Exception;
3737
use Horde_Mime_Headers;
38+
use Horde_Mime_Headers_ContentParam_ContentType;
39+
use Horde_Mime_Headers_ContentTransferEncoding;
3840
use Horde_Mime_Part;
3941
use Html2Text\Html2Text;
4042
use OCA\Mail\Attachment;
4143
use OCA\Mail\Db\Mailbox;
4244
use OCA\Mail\Exception\ServiceException;
45+
use OCA\Mail\IMAP\Charset\Converter;
4346
use OCA\Mail\Model\IMAPMessage;
4447
use OCA\Mail\Service\SmimeService;
4548
use OCA\Mail\Support\PerformanceLoggerTask;
@@ -64,13 +67,16 @@ class MessageMapper {
6467

6568
private SMimeService $smimeService;
6669
private ImapMessageFetcherFactory $imapMessageFactory;
70+
private Converter $converter;
6771

6872
public function __construct(LoggerInterface $logger,
6973
SmimeService $smimeService,
70-
ImapMessageFetcherFactory $imapMessageFactory) {
74+
ImapMessageFetcherFactory $imapMessageFactory,
75+
Converter $converter) {
7176
$this->logger = $logger;
7277
$this->smimeService = $smimeService;
7378
$this->imapMessageFactory = $imapMessageFactory;
79+
$this->converter = $converter;
7480
}
7581

7682
/**
@@ -943,15 +949,39 @@ public function getBodyStructureData(Horde_Imap_Client_Socket $client,
943949
return new MessageStructureData($hasAttachments, $text, $isImipMessage, $isEncrypted);
944950
}
945951

952+
// Convert a given binary body to utf-8 according to the transfer encoding and content
953+
// type headers of the underlying MIME part
954+
$convertBody = function (string $body, Horde_Mime_Headers $mimeHeaders) use ($structure): string {
955+
/** @var Horde_Mime_Headers_ContentParam_ContentType $contentType */
956+
$contentType = $mimeHeaders->getHeader('content-type');
957+
/** @var Horde_Mime_Headers_ContentTransferEncoding $transferEncoding */
958+
$transferEncoding = $mimeHeaders->getHeader('content-transfer-encoding');
959+
960+
if (!$contentType && !$transferEncoding) {
961+
// Nothing to convert here ...
962+
return $body;
963+
}
964+
965+
if ($transferEncoding) {
966+
$structure->setTransferEncoding($transferEncoding->value_single);
967+
}
968+
969+
if ($contentType) {
970+
$structure->setType($contentType->value_single);
971+
if (isset($contentType['charset'])) {
972+
$structure->setCharset($contentType['charset']);
973+
}
974+
}
975+
976+
$structure->setContents($body);
977+
return $this->converter->convert($structure);
978+
};
979+
946980

947981
$htmlBody = ($htmlBodyId !== null) ? $part->getBodyPart($htmlBodyId) : null;
948982
if (!empty($htmlBody)) {
949983
$mimeHeaders = $part->getMimeHeader($htmlBodyId, Horde_Imap_Client_Data_Fetch::HEADER_PARSE);
950-
if ($enc = $mimeHeaders->getValue('content-transfer-encoding')) {
951-
$structure->setTransferEncoding($enc);
952-
$structure->setContents($htmlBody);
953-
$htmlBody = $structure->getContents();
954-
}
984+
$htmlBody = $convertBody($htmlBody, $mimeHeaders);
955985
$html = new Html2Text($htmlBody, ['do_links' => 'none','alt_image' => 'hide']);
956986
return new MessageStructureData(
957987
$hasAttachments,
@@ -964,11 +994,7 @@ public function getBodyStructureData(Horde_Imap_Client_Socket $client,
964994

965995
if (!empty($textBody)) {
966996
$mimeHeaders = $part->getMimeHeader($textBodyId, Horde_Imap_Client_Data_Fetch::HEADER_PARSE);
967-
if ($enc = $mimeHeaders->getValue('content-transfer-encoding')) {
968-
$structure->setTransferEncoding($enc);
969-
$structure->setContents($textBody);
970-
$textBody = $structure->getContents();
971-
}
997+
$textBody = $convertBody($textBody, $mimeHeaders);
972998
return new MessageStructureData(
973999
$hasAttachments,
9741000
$textBody,

tests/Unit/IMAP/MessageMapperTest.php

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
use Horde_Imap_Client_Ids;
3333
use Horde_Imap_Client_Socket;
3434
use OCA\Mail\Db\Mailbox;
35+
use OCA\Mail\IMAP\Charset\Converter;
3536
use OCA\Mail\IMAP\ImapMessageFetcher;
3637
use OCA\Mail\IMAP\ImapMessageFetcherFactory;
3738
use OCA\Mail\IMAP\MessageMapper;
@@ -55,17 +56,22 @@ class MessageMapperTest extends TestCase {
5556
/** @var ImapMessageFetcherFactory|MockObject */
5657
private $imapMessageFactory;
5758

59+
/** @var Converter|MockObject */
60+
private $converter;
61+
5862
protected function setUp(): void {
5963
parent::setUp();
6064

6165
$this->logger = $this->createMock(LoggerInterface::class);
6266
$this->sMimeService = $this->createMock(SmimeService::class);
6367
$this->imapMessageFactory = $this->createMock(ImapMessageFetcherFactory::class);
68+
$this->converter = $this->createMock(Converter::class);
6469

6570
$this->mapper = new MessageMapper(
6671
$this->logger,
6772
$this->sMimeService,
6873
$this->imapMessageFactory,
74+
$this->converter,
6975
);
7076
}
7177

0 commit comments

Comments
 (0)