mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-09-20 07:16:05 +08:00
fix(mime-parsing): ensure that text content for multipart nodes always ends with a newline. Fixes #571
This commit is contained in:
parent
e553523df3
commit
6f4994d3a0
|
@ -58,4 +58,5 @@ module.exports = function (grunt) {
|
|||
// Tasks
|
||||
grunt.registerTask('default', ['eslint', 'shell:server', 'wait:server', 'mochaTest', 'shell:server:kill']);
|
||||
grunt.registerTask('testonly', ['shell:server', 'wait:server', 'mochaTest', 'shell:server:kill']);
|
||||
grunt.registerTask('proto', ['mochaTest:imap']);
|
||||
};
|
||||
|
|
|
@ -125,6 +125,23 @@ class MIMEParser {
|
|||
node.message = parse(node.body.join(''));
|
||||
}
|
||||
|
||||
if (node.body && node.body.length && node.multipart) {
|
||||
// find last character from an array of strings
|
||||
let lastChar;
|
||||
let lastIndex = 0;
|
||||
for (let i = node.body.length - 1; i >= 0; i--) {
|
||||
if (typeof node.body[i] === 'string' && node.body[i].length) {
|
||||
lastChar = node.body[i].at(-1);
|
||||
lastIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastChar && lastChar !== '\n') {
|
||||
// ensure that non-multipart body text always ends with a newline
|
||||
node.body[lastIndex] += '\n';
|
||||
}
|
||||
}
|
||||
|
||||
node.lineCount = node.body.length ? node.body.length - 1 : 0;
|
||||
node.body = Buffer.from(
|
||||
node.body
|
||||
|
|
22
imap-core/test/fixtures/no_empty_line_between_text_boundary.eml
vendored
Normal file
22
imap-core/test/fixtures/no_empty_line_between_text_boundary.eml
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Content-Type: multipart/mixed; boundary="------------cWFvDSey27tFG0hVYLqp9hs9"
|
||||
MIME-Version: 1.0
|
||||
Message-ID: <beep-boop@example-1.com>
|
||||
To: foo-1@example-1.com
|
||||
From: foo-1@example-1.com
|
||||
Subject: test
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------cWFvDSey27tFG0hVYLqp9hs9
|
||||
Content-Type: text/plain; charset=UTF-8; format=flowed
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
test
|
||||
|
||||
--------------cWFvDSey27tFG0hVYLqp9hs9
|
||||
Content-Type: text/plain; charset=UTF-8; name="example.txt"
|
||||
Content-Disposition: attachment; filename="example.txt"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
ZXhhbXBsZQo=
|
||||
|
||||
--------------cWFvDSey27tFG0hVYLqp9hs9--
|
22
imap-core/test/fixtures/no_empty_line_between_text_boundary.eml.2
vendored
Normal file
22
imap-core/test/fixtures/no_empty_line_between_text_boundary.eml.2
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Content-Type: multipart/mixed; boundary="------------cWFvDSey27tFG0hVYLqp9hs9"
|
||||
MIME-Version: 1.0
|
||||
Message-ID: <beep-boop@example-1.com>
|
||||
To: foo-1@example-1.com
|
||||
From: foo-1@example-1.com
|
||||
Subject: test
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
--------------cWFvDSey27tFG0hVYLqp9hs9
|
||||
Content-Type: text/plain; charset=UTF-8; format=flowed
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
test
|
||||
|
||||
--------------cWFvDSey27tFG0hVYLqp9hs9
|
||||
Content-Type: text/plain; charset=UTF-8; name="example.txt"
|
||||
Content-Disposition: attachment; filename="example.txt"
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
ZXhhbXBsZQo=
|
||||
|
||||
--------------cWFvDSey27tFG0hVYLqp9hs9--
|
|
@ -3,11 +3,20 @@
|
|||
'use strict';
|
||||
|
||||
const MIMEParser = require('../lib/indexer/parse-mime-tree').MIMEParser;
|
||||
const Indexer = require('../lib/indexer/indexer');
|
||||
const indexer = new Indexer();
|
||||
|
||||
const fs = require('fs');
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
chai.config.includeStack = true;
|
||||
|
||||
const fixtures = {
|
||||
no_empty_line_between_text_boundary: {
|
||||
eml: fs.readFileSync(__dirname + '/fixtures/no_empty_line_between_text_boundary.eml')
|
||||
}
|
||||
};
|
||||
|
||||
describe('#parseValueParams', function () {
|
||||
it('should return continuation value as mime-word', function () {
|
||||
let parser = new MIMEParser();
|
||||
|
@ -44,4 +53,23 @@ describe('#parseValueParams', function () {
|
|||
hasParams: true
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse a file with no empty line between text and boundary', function (done) {
|
||||
// parse a file and then make sure that boundary is correct
|
||||
|
||||
let source = Buffer.concat([fixtures.no_empty_line_between_text_boundary.eml]);
|
||||
|
||||
let parser = new MIMEParser(source);
|
||||
|
||||
parser.parse();
|
||||
parser.finalizeTree();
|
||||
|
||||
let parsed = parser.tree.childNodes[0];
|
||||
|
||||
indexer.bodyQuery(parsed, '', (err, data) => {
|
||||
expect(err).to.not.exist;
|
||||
expect(data.toString().indexOf('This is a multi-part message in MIME format.\r\n--------------cWFvDSey27tFG0hVYLqp9hs9')).to.gt(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"main": "server.js",
|
||||
"scripts": {
|
||||
"test": "mongo --eval 'db.dropDatabase()' wildduck-test && redis-cli -n 13 flushdb && npm run runtest",
|
||||
"test:proto": "NODE_ENV=test grunt proto",
|
||||
"printconf": "NODE_CONFIG_ONLY=true npm start",
|
||||
"runtest": "NODE_ENV=test grunt",
|
||||
"runci": "npm run printconf && npm run runtest",
|
||||
|
|
Loading…
Reference in a new issue