Skip to content

Commit

Permalink
fix(api-messages-attachment-download): is sendAsString param is set, …
Browse files Browse the repository at this point in the history
…and is set to true then decode the original file and send back as UTF-8 ZMS-134 (#655)

* add attachment charset in the indexer

* test adding a field

* test another way

* walk through mimetree to find the attachment charset and decode the message using this charset. Decoding is piped to the output stream

* test

* revert last change

* use regex for check, fix piping

* fixes
  • Loading branch information
NickOvt committed Apr 8, 2024
1 parent f55ddea commit 1f27778
Showing 1 changed file with 35 additions and 2 deletions.
37 changes: 35 additions & 2 deletions lib/api/messages.js
Expand Up @@ -23,6 +23,7 @@ const TaskHandler = require('../task-handler');
const { prepareSearchFilter, uidRangeStringToQuery } = require('../prepare-search-filter');
const { getMongoDBQuery /*, getElasticSearchQuery*/ } = require('../search-query');
//const { getClient } = require('../elasticsearch');
let iconv = require('iconv-lite');

const BimiHandler = require('../bimi-handler');
const {
Expand Down Expand Up @@ -1528,7 +1529,11 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti
summary: 'Download Attachment',
description: 'This method returns attachment file contents in binary form',
validationObjs: {
queryParams: {},
queryParams: {
sendAsString: booleanSchema
.default(false)
.description('If true then sends the original attachment back in string format with correct encoding.')
},
pathParams: {
user: userId,
mailbox: mailboxId,
Expand Down Expand Up @@ -1600,7 +1605,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti
_id: true,
user: true,
attachments: true,
'mimeTree.attachmentMap': true
mimeTree: true
}
}
);
Expand Down Expand Up @@ -1637,6 +1642,8 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti
});
}

let [attachmentCharset] = getAttachmentCharset(messageData.mimeTree, attachment);

res.writeHead(200, {
'Content-Type': attachmentData.contentType || 'application/octet-stream'
});
Expand Down Expand Up @@ -1678,6 +1685,10 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler, setti
} else if (attachmentData.transferEncoding === 'quoted-printable') {
attachmentStream.pipe(new libqp.Decoder()).pipe(res);
} else {
if (!/ascii|utf[-_]?8/i.test(attachmentCharset) && result.value.sendAsString) {
attachmentStream.pipe(iconv.decodeStream(attachmentCharset)).pipe(res);
return;
}
attachmentStream.pipe(res);
}
})
Expand Down Expand Up @@ -3901,3 +3912,25 @@ function parseAddresses(data) {
walk([].concat(data || []));
return Array.from(addresses);
}

function getAttachmentCharset(mimeTree, attachmentId) {
if (mimeTree.attachmentId && mimeTree.attachmentId === attachmentId) {
// current mimeTree (sub)object has the attachmentId field, and it is the one we search
// get the parsedHeader -> content-type -> params -> charset

return [mimeTree.parsedHeader['content-type']?.params?.charset || 'UTF-8', true];
} else if (mimeTree.childNodes) {
// current mimetree (sub)object does not have the attachmentId field and it is not equal to the one we search
// loop childNodes
let charset;
for (const childNode of Object.values(mimeTree.childNodes)) {
charset = getAttachmentCharset(childNode, attachmentId);
if (charset[1] === true) {
// actually found the charset, early return
return charset;
}
}
}

return ['UTF-8', false];
}

0 comments on commit 1f27778

Please sign in to comment.