mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-12-25 09:21:19 +08:00
fix streams in on-copy and message-handler. message-handler optimizations, filter-handler optimizations
This commit is contained in:
parent
fa849f2fb4
commit
d1c67e6264
3 changed files with 467 additions and 401 deletions
|
@ -141,10 +141,9 @@ class FilterHandler {
|
|||
|
||||
let rawchunks = chunks;
|
||||
|
||||
let raw;
|
||||
|
||||
let prepared;
|
||||
|
||||
let raw = Buffer.concat(chunks, chunklen);
|
||||
|
||||
if (options.mimeTree) {
|
||||
if (options.mimeTree && options.mimeTree.header) {
|
||||
// remove old headers
|
||||
|
@ -159,6 +158,7 @@ class FilterHandler {
|
|||
mimeTree: options.mimeTree
|
||||
});
|
||||
} else {
|
||||
raw = Buffer.concat(chunks, chunklen);
|
||||
prepared = await this.prepareMessage({
|
||||
raw
|
||||
});
|
||||
|
@ -661,11 +661,14 @@ class FilterHandler {
|
|||
|
||||
date: false,
|
||||
flags,
|
||||
|
||||
raw,
|
||||
rawchunks
|
||||
rawchunks,
|
||||
chunklen
|
||||
};
|
||||
|
||||
if (raw) {
|
||||
messageOpts.raw = raw;
|
||||
}
|
||||
|
||||
if (options.verificationResults) {
|
||||
messageOpts.verificationResults = options.verificationResults;
|
||||
}
|
||||
|
|
|
@ -233,15 +233,27 @@ async function copyHandler(server, messageHandler, connection, mailbox, update,
|
|||
const newPrepared = await new Promise((resolve, reject) => {
|
||||
if (targetMailboxEncrypted && !isMessageEncrypted && userData.pubKey) {
|
||||
// encrypt message
|
||||
const outputStream = messageHandler.indexer.rebuild(messageData.mimeTree).value; // get raw rebuilder stream
|
||||
let raw = Buffer.from([], 'binary'); // set initial raw
|
||||
// get raw from existing mimetree
|
||||
let outputStream = messageHandler.indexer.rebuild(messageData.mimeTree); // get raw rebuilder response obj (.value is the stream)
|
||||
|
||||
if (!outputStream || outputStream.type !== 'stream' || !outputStream.value) {
|
||||
return reject(new Error('Cannot fetch message'));
|
||||
}
|
||||
outputStream = outputStream.value; // set stream to actual stream object (.value)
|
||||
|
||||
let chunks = [];
|
||||
let chunklen = 0;
|
||||
outputStream
|
||||
.on('data', data => {
|
||||
raw = Buffer.concat([raw, data]);
|
||||
.on('readable', () => {
|
||||
let chunk;
|
||||
while ((chunk = outputStream.read()) !== null) {
|
||||
chunks.push(chunk);
|
||||
chunklen += chunk.length;
|
||||
}
|
||||
})
|
||||
.on('end', () => {
|
||||
messageHandler.encryptMessages(userData.pubKey || '', raw, (err, res) => {
|
||||
const raw = Buffer.concat(chunks, chunklen);
|
||||
messageHandler.encryptMessages(userData.pubKey, raw, (err, res) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
|
|
@ -204,22 +204,39 @@ class MessageHandler {
|
|||
}
|
||||
|
||||
// get target user data
|
||||
|
||||
this.prepareMessage(options, (err, prepared) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
let prepared = options.prepared; // might be undefined
|
||||
|
||||
// check if already encrypted
|
||||
let alreadyEncrypted = false;
|
||||
|
||||
// message already prepared, check if encrypted
|
||||
if (prepared) {
|
||||
// got prepared
|
||||
const parsedHeader = (prepared.mimeTree && prepared.mimeTree?.parsedHeader) || {};
|
||||
const parsedContentType = parsedHeader['content-type'];
|
||||
|
||||
if (parsedContentType && parsedContentType.subtype === 'encrypted') {
|
||||
alreadyEncrypted = true;
|
||||
}
|
||||
} else {
|
||||
// no prepared, use raw
|
||||
if (options.rawchunks && !options.raw) {
|
||||
// got rawchunks instead of raw
|
||||
if (options.chunklen) {
|
||||
options.raw = Buffer.concat(options.rawchunks, options.chunklen);
|
||||
} else {
|
||||
options.raw = Buffer.concat(options.rawchunks);
|
||||
}
|
||||
}
|
||||
|
||||
const rawString = options.raw.toString('binary'); // get string from the raw bytes of message
|
||||
const regex = /Content-Type:\s*multipart\/encrypted/gim;
|
||||
|
||||
if (regex.test(rawString)) {
|
||||
// if there is encrypted content-type then message already encrypted, no need to re-encrypt it
|
||||
alreadyEncrypted = true;
|
||||
}
|
||||
}
|
||||
|
||||
let flags = Array.isArray(options.flags) ? options.flags : [].concat(options.flags || []);
|
||||
|
||||
|
@ -589,10 +606,7 @@ class MessageHandler {
|
|||
|
||||
let now = new Date();
|
||||
for (let auditData of audits) {
|
||||
if (
|
||||
(auditData.start && auditData.start > now) ||
|
||||
(auditData.end && auditData.end < now)
|
||||
) {
|
||||
if ((auditData.start && auditData.start > now) || (auditData.end && auditData.end < now)) {
|
||||
// audit not active
|
||||
continue;
|
||||
}
|
||||
|
@ -637,8 +651,17 @@ class MessageHandler {
|
|||
if (!alreadyEncrypted) {
|
||||
// not already encrypted, check if user has encryption on or target mailbox is encrypted
|
||||
if ((userData.encryptMessages || !!mailboxData.encryptMessages) && userData.pubKey && !flags.includes('\\Draft')) {
|
||||
if (options.rawchunks && !options.raw) {
|
||||
// got rawchunks instead of raw
|
||||
if (options.chunklen) {
|
||||
options.raw = Buffer.concat(options.rawchunks, options.chunklen);
|
||||
} else {
|
||||
options.raw = Buffer.concat(options.rawchunks);
|
||||
}
|
||||
}
|
||||
// user has encryption on or target mailbox encrypted, encrypt message and prepare again
|
||||
// do not encrypt drafts
|
||||
// may have a situation where we got prepared and no options.raw but options.rawchunks instead, concat them
|
||||
this.encryptMessage(userData.pubKey, options.raw, (err, res) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
|
@ -665,13 +688,26 @@ class MessageHandler {
|
|||
});
|
||||
} else {
|
||||
// not already encrypted and no need to
|
||||
this.prepareMessage(options, (err, newPrepared) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
prepared = newPrepared;
|
||||
addMessage();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// message already encrypted
|
||||
addMessage();
|
||||
this.prepareMessage(options, (err, newPrepared) => {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
prepared = newPrepared;
|
||||
addMessage();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -1204,17 +1240,32 @@ class MessageHandler {
|
|||
return done(err);
|
||||
}
|
||||
// get user data
|
||||
if (!res.pubKey) {
|
||||
return updateMessage();
|
||||
}
|
||||
|
||||
// get raw from existing mimetree
|
||||
const outputStream = this.indexer.rebuild(message.mimeTree).value; // get raw rebuilder stream
|
||||
let raw = Buffer.from([], 'binary'); // set initial raw
|
||||
let outputStream = this.indexer.rebuild(message.mimeTree); // get raw rebuilder response obj (.value is the stream)
|
||||
|
||||
if (!outputStream || outputStream.type !== 'stream' || !outputStream.value) {
|
||||
return done(new Error('Cannot fetch message'));
|
||||
}
|
||||
outputStream = outputStream.value; // set stream to actual stream object (.value)
|
||||
|
||||
let chunks = [];
|
||||
let chunklen = 0;
|
||||
outputStream
|
||||
.on('data', data => {
|
||||
raw = Buffer.concat([raw, data]);
|
||||
.on('readable', () => {
|
||||
let chunk;
|
||||
while ((chunk = outputStream.read()) !== null) {
|
||||
chunks.push(chunk);
|
||||
chunklen += chunk.length;
|
||||
}
|
||||
})
|
||||
.on('end', () => {
|
||||
// when done rebuilding
|
||||
this.encryptMessage(res.pubKey || '', raw, (err, res) => {
|
||||
const raw = Buffer.concat(chunks, chunklen);
|
||||
this.encryptMessage(res.pubKey, raw, (err, res) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue