mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-11-14 21:35:57 +08:00
202 lines
6 KiB
JavaScript
202 lines
6 KiB
JavaScript
'use strict';
|
|
|
|
const log = require('npmlog');
|
|
const db = require('../db');
|
|
|
|
let run = async (taskData, options) => {
|
|
const messageHandler = options.messageHandler;
|
|
const auditHandler = options.auditHandler;
|
|
|
|
let query = {
|
|
user: taskData.user
|
|
};
|
|
|
|
if (taskData.start) {
|
|
let start = taskData.start;
|
|
if (['number', 'string'].includes(typeof start)) {
|
|
start = new Date(start);
|
|
}
|
|
query.idate = query.idate || {};
|
|
query.idate.$gte = start;
|
|
}
|
|
|
|
if (taskData.end) {
|
|
let end = taskData.end;
|
|
if (['number', 'string'].includes(typeof end)) {
|
|
end = new Date(end);
|
|
}
|
|
query.idate = query.idate || {};
|
|
query.idate.$lte = end;
|
|
}
|
|
|
|
let mailboxes = new Map(
|
|
(await db.database.collection('mailboxes').find({ user: taskData.user }).toArray()).map(mailboxData => [mailboxData._id.toString(), mailboxData])
|
|
);
|
|
|
|
let processMessage = async messageData => {
|
|
let builder = messageHandler.indexer.rebuild(messageData.mimeTree);
|
|
if (!builder || builder.type !== 'stream' || !builder.value) {
|
|
return false;
|
|
}
|
|
let mailboxData = messageData.mailbox ? mailboxes.get(messageData.mailbox.toString()) : false;
|
|
let auditMessage = await auditHandler.store(
|
|
taskData.audit,
|
|
builder.value,
|
|
{
|
|
date: messageData.idate,
|
|
msgid: messageData.msgid,
|
|
header: messageData.mimeTree && messageData.mimeTree.parsedHeader,
|
|
ha: messageData.ha,
|
|
mailbox: messageData.mailbox,
|
|
mailboxPath: mailboxData ? mailboxData.path : false,
|
|
info: messageData.meta,
|
|
draft: messageData.draft,
|
|
imported: true
|
|
},
|
|
true
|
|
);
|
|
|
|
return auditMessage;
|
|
};
|
|
|
|
let copied = 0;
|
|
let failed = 0;
|
|
let status = 'imported'; //expect to complete successfully
|
|
|
|
let processMessages = async collection => {
|
|
let cursor = await db.database.collection(collection).find(query, {
|
|
noCursorTimeout: true,
|
|
projection: {
|
|
_id: true,
|
|
user: true,
|
|
mimeTree: true,
|
|
meta: true,
|
|
mailbox: true,
|
|
idate: true,
|
|
msgid: true,
|
|
ha: true,
|
|
draft: true
|
|
}
|
|
});
|
|
|
|
let messageData;
|
|
try {
|
|
while ((messageData = await cursor.next())) {
|
|
try {
|
|
let auditMessage = await processMessage(messageData);
|
|
log.verbose(
|
|
'Tasks',
|
|
'task=audit id=%s user=%s coll=%s message=%s src=%s dst=%s',
|
|
taskData._id,
|
|
taskData.user,
|
|
collection,
|
|
'Stored message to audit base',
|
|
messageData._id,
|
|
auditMessage
|
|
);
|
|
copied++;
|
|
try {
|
|
await db.database.collection('audits').updateOne(
|
|
{ _id: taskData.audit },
|
|
{
|
|
$inc: {
|
|
'import.copied': 1,
|
|
audited: 1
|
|
},
|
|
$set: {
|
|
lastAuditedMessage: new Date()
|
|
}
|
|
}
|
|
);
|
|
} catch (e) {
|
|
//ignore
|
|
}
|
|
} catch (err) {
|
|
log.error(
|
|
'Tasks',
|
|
'task=audit id=%s user=%s coll=%s message=%s error=%s',
|
|
taskData._id,
|
|
taskData.user,
|
|
collection,
|
|
'Failed to process message',
|
|
err.message
|
|
);
|
|
failed++;
|
|
try {
|
|
await db.database.collection('audits').updateOne(
|
|
{ _id: taskData.audit },
|
|
{
|
|
$inc: {
|
|
'import.failed': 1
|
|
}
|
|
}
|
|
);
|
|
} catch (e) {
|
|
//ignore
|
|
}
|
|
}
|
|
}
|
|
await cursor.close();
|
|
} catch (err) {
|
|
log.error(
|
|
'Tasks',
|
|
'task=audit id=%s user=%s coll=%s message=%s error=%s',
|
|
taskData._id,
|
|
taskData.user,
|
|
collection,
|
|
'Failed to fetch stored messages',
|
|
err.message
|
|
);
|
|
|
|
err.code = 'InternalDatabaseError';
|
|
throw err;
|
|
}
|
|
};
|
|
|
|
await db.database.collection('audits').updateOne(
|
|
{ _id: taskData.audit },
|
|
{
|
|
$set: {
|
|
'import.status': 'importing'
|
|
}
|
|
}
|
|
);
|
|
|
|
try {
|
|
await processMessages('messages');
|
|
} catch (err) {
|
|
status = 'failed';
|
|
}
|
|
|
|
try {
|
|
await processMessages('archive');
|
|
} catch (err) {
|
|
status = 'failed';
|
|
}
|
|
|
|
await db.database.collection('audits').updateOne(
|
|
{ _id: taskData.audit },
|
|
{
|
|
$set: {
|
|
'import.status': status
|
|
}
|
|
}
|
|
);
|
|
|
|
log.verbose(
|
|
'Tasks',
|
|
'task=audit id=%s user=%s message=%s copied=%s failed=%s',
|
|
taskData._id,
|
|
taskData.user,
|
|
`Copied user messages for auditing`,
|
|
copied,
|
|
failed
|
|
);
|
|
return true;
|
|
};
|
|
|
|
module.exports = (taskData, options, callback) => {
|
|
run(taskData, options)
|
|
.then(response => callback(null, response))
|
|
.catch(callback);
|
|
};
|