mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-09-20 15:26:03 +08:00
updated autiding
This commit is contained in:
parent
7abe3215a4
commit
4a194b6502
14
indexes.yaml
14
indexes.yaml
|
@ -561,6 +561,20 @@ indexes:
|
||||||
locked: 1
|
locked: 1
|
||||||
lockedUntil: 1
|
lockedUntil: 1
|
||||||
|
|
||||||
|
- collection: audits
|
||||||
|
index:
|
||||||
|
name: user_expire_time
|
||||||
|
key:
|
||||||
|
user: 1
|
||||||
|
expires: 1
|
||||||
|
|
||||||
|
- collection: audits
|
||||||
|
index:
|
||||||
|
name: expire_time
|
||||||
|
key:
|
||||||
|
expires: 1
|
||||||
|
deleted: 1
|
||||||
|
|
||||||
- collection: audit.files
|
- collection: audit.files
|
||||||
type: gridfs # index applies to gridfs database
|
type: gridfs # index applies to gridfs database
|
||||||
index:
|
index:
|
||||||
|
|
|
@ -36,12 +36,18 @@ class AuditHandler {
|
||||||
start: options.start, // Date or null
|
start: options.start, // Date or null
|
||||||
end: options.end, // Date or null
|
end: options.end, // Date or null
|
||||||
expires: options.expires, // Date
|
expires: options.expires, // Date
|
||||||
|
deleted: false, // Boolean
|
||||||
|
notes: options.nodes, // String
|
||||||
|
meta: options.meta || {}, // Object
|
||||||
|
|
||||||
import: {
|
import: {
|
||||||
status: 'queued',
|
status: 'queued',
|
||||||
failed: 0,
|
failed: 0,
|
||||||
copied: 0
|
copied: 0
|
||||||
}
|
},
|
||||||
|
|
||||||
|
audited: 0,
|
||||||
|
lastAuditedMessage: null
|
||||||
};
|
};
|
||||||
|
|
||||||
let r;
|
let r;
|
||||||
|
@ -96,7 +102,7 @@ class AuditHandler {
|
||||||
* @param {Mixed} message Either a Buffer, an Array of Buffers or a Stream
|
* @param {Mixed} message Either a Buffer, an Array of Buffers or a Stream
|
||||||
* @param {Object} metadata Metadata for the stored message
|
* @param {Object} metadata Metadata for the stored message
|
||||||
*/
|
*/
|
||||||
async store(audit, message, metadata) {
|
async store(audit, message, metadata, skipCounters) {
|
||||||
if (!message) {
|
if (!message) {
|
||||||
throw new Error('Missing message content');
|
throw new Error('Missing message content');
|
||||||
}
|
}
|
||||||
|
@ -111,7 +117,7 @@ class AuditHandler {
|
||||||
metadata.audit = metadata.audit || audit;
|
metadata.audit = metadata.audit || audit;
|
||||||
metadata.date = metadata.date || new Date();
|
metadata.date = metadata.date || new Date();
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
let result = await new Promise((resolve, reject) => {
|
||||||
let stream = this.gridstore.openUploadStreamWithId(id, null, {
|
let stream = this.gridstore.openUploadStreamWithId(id, null, {
|
||||||
contentType: 'message/rfc822',
|
contentType: 'message/rfc822',
|
||||||
metadata
|
metadata
|
||||||
|
@ -145,6 +151,12 @@ class AuditHandler {
|
||||||
|
|
||||||
message.pipe(stream);
|
message.pipe(stream);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (result && !skipCounters) {
|
||||||
|
await this.database.collection('audits').updateOne({ _id: metadata.audit }, { $inc: { audited: 1 }, $set: { lastAuditedMessage: new Date() } });
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -207,15 +219,19 @@ class AuditHandler {
|
||||||
}
|
}
|
||||||
await cursor.close();
|
await cursor.close();
|
||||||
|
|
||||||
await this.database.collection('audits').deleteOne({ _id: auditData._id });
|
await this.database.collection('audits').updateOne({ _id: auditData._id }, { $set: { deleted: true, deletedTime: new Date() } });
|
||||||
log.info('Audit', 'Deleted expired audit %s (%s messages)', auditData._id, messages);
|
log.info('Audit', 'Deleted audit %s (%s messages)', auditData._id, messages);
|
||||||
|
return {
|
||||||
|
audit: auditData._id,
|
||||||
|
messages
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async cleanExpired() {
|
async cleanExpired() {
|
||||||
let expiredAudits = await this.database
|
let expiredAudits = await this.database
|
||||||
.collection('audits')
|
.collection('audits')
|
||||||
.find({
|
.find({
|
||||||
expires: { $lt: new Date() }
|
expires: { $lt: new Date(), deleted: false }
|
||||||
})
|
})
|
||||||
.toArray();
|
.toArray();
|
||||||
|
|
||||||
|
|
|
@ -482,6 +482,29 @@ class FilterHandler {
|
||||||
|
|
||||||
filterResults.push({ delete: true });
|
filterResults.push({ delete: true });
|
||||||
|
|
||||||
|
try {
|
||||||
|
let audits = await this.database
|
||||||
|
.collection('audits')
|
||||||
|
.find({ user: userData._id, expires: { $gt: new Date() } })
|
||||||
|
.toArray();
|
||||||
|
|
||||||
|
let now = new Date();
|
||||||
|
for (let auditData of audits) {
|
||||||
|
if ((auditData.start && auditData.start > now) || (auditData.end && auditData.end < now)) {
|
||||||
|
// audit not active
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
await this.auditHandler.store(auditData._id, rawchunks, {
|
||||||
|
date: prepared.idate || new Date(),
|
||||||
|
msgid: prepared.msgid,
|
||||||
|
header: prepared.mimeTree && prepared.mimeTree.parsedHeader,
|
||||||
|
ha: prepared.ha,
|
||||||
|
info: Object.assign({ notStored: true }, meta || {})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
log.error('Filter', '%s AUDITFAIL from=%s to=%s error=%s', prepared.id.toString(), '<>', sender, err.message);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
response: {
|
response: {
|
||||||
userData,
|
userData,
|
||||||
|
|
|
@ -473,7 +473,10 @@ class MessageHandler {
|
||||||
|
|
||||||
let raw = options.rawchunks || options.raw;
|
let raw = options.rawchunks || options.raw;
|
||||||
let processAudits = async () => {
|
let processAudits = async () => {
|
||||||
let audits = await this.database.collection('audits').find({ user: mailboxData.user }).toArray();
|
let audits = await this.database
|
||||||
|
.collection('audits')
|
||||||
|
.find({ user: mailboxData.user, expires: { $gt: new Date() } })
|
||||||
|
.toArray();
|
||||||
|
|
||||||
let now = new Date();
|
let now = new Date();
|
||||||
for (let auditData of audits) {
|
for (let auditData of audits) {
|
||||||
|
|
|
@ -30,12 +30,7 @@ let run = async (taskData, options) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mailboxes = new Map(
|
let mailboxes = new Map(
|
||||||
(
|
(await db.database.collection('mailboxes').find({ user: taskData.user }).toArray()).map(mailboxData => [mailboxData._id.toString(), mailboxData])
|
||||||
await db.database
|
|
||||||
.collection('mailboxes')
|
|
||||||
.find({ user: taskData.user })
|
|
||||||
.toArray()
|
|
||||||
).map(mailboxData => [mailboxData._id.toString(), mailboxData])
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let processMessage = async messageData => {
|
let processMessage = async messageData => {
|
||||||
|
@ -44,16 +39,22 @@ let run = async (taskData, options) => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let mailboxData = messageData.mailbox ? mailboxes.get(messageData.mailbox.toString()) : false;
|
let mailboxData = messageData.mailbox ? mailboxes.get(messageData.mailbox.toString()) : false;
|
||||||
let auditMessage = await auditHandler.store(taskData.audit, builder.value, {
|
let auditMessage = await auditHandler.store(
|
||||||
date: messageData.idate,
|
taskData.audit,
|
||||||
msgid: messageData.msgid,
|
builder.value,
|
||||||
header: messageData.mimeTree && messageData.mimeTree.parsedHeader,
|
{
|
||||||
ha: messageData.ha,
|
date: messageData.idate,
|
||||||
mailbox: messageData.mailbox,
|
msgid: messageData.msgid,
|
||||||
mailboxPath: mailboxData ? mailboxData.path : false,
|
header: messageData.mimeTree && messageData.mimeTree.parsedHeader,
|
||||||
info: messageData.meta,
|
ha: messageData.ha,
|
||||||
draft: messageData.draft
|
mailbox: messageData.mailbox,
|
||||||
});
|
mailboxPath: mailboxData ? mailboxData.path : false,
|
||||||
|
info: messageData.meta,
|
||||||
|
draft: messageData.draft,
|
||||||
|
imported: true
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
return auditMessage;
|
return auditMessage;
|
||||||
};
|
};
|
||||||
|
@ -98,7 +99,11 @@ let run = async (taskData, options) => {
|
||||||
{ _id: taskData.audit },
|
{ _id: taskData.audit },
|
||||||
{
|
{
|
||||||
$inc: {
|
$inc: {
|
||||||
'import.copied': 1
|
'import.copied': 1,
|
||||||
|
audited: 1
|
||||||
|
},
|
||||||
|
$set: {
|
||||||
|
lastAuditedMessage: new Date()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "wildduck",
|
"name": "wildduck",
|
||||||
"version": "1.26.3",
|
"version": "1.26.4",
|
||||||
"description": "IMAP/POP3 server built with Node.js and MongoDB",
|
"description": "IMAP/POP3 server built with Node.js and MongoDB",
|
||||||
"main": "server.js",
|
"main": "server.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
"he": "1.2.0",
|
"he": "1.2.0",
|
||||||
"html-to-text": "5.1.1",
|
"html-to-text": "5.1.1",
|
||||||
"humanname": "0.2.2",
|
"humanname": "0.2.2",
|
||||||
"iconv-lite": "0.6.0",
|
"iconv-lite": "0.6.1",
|
||||||
"ioredfour": "1.0.2-ioredis-03",
|
"ioredfour": "1.0.2-ioredis-03",
|
||||||
"ioredis": "4.17.3",
|
"ioredis": "4.17.3",
|
||||||
"isemail": "3.2.0",
|
"isemail": "3.2.0",
|
||||||
|
|
|
@ -261,7 +261,7 @@ SERVICE_NAME=$1
|
||||||
# Ensure required files and permissions
|
# Ensure required files and permissions
|
||||||
echo "d /var/log/${SERVICE_NAME} 0750 syslog adm" > /etc/tmpfiles.d/${SERVICE_NAME}-log.conf
|
echo "d /var/log/${SERVICE_NAME} 0750 syslog adm" > /etc/tmpfiles.d/${SERVICE_NAME}-log.conf
|
||||||
|
|
||||||
# Redirect MongoDB log output from syslog to mongodb log file
|
# Redirect MongoDB log output from syslog to service specific log file
|
||||||
echo "if ( \$programname startswith \"$SERVICE_NAME\" ) then {
|
echo "if ( \$programname startswith \"$SERVICE_NAME\" ) then {
|
||||||
action(type=\"omfile\" file=\"/var/log/${SERVICE_NAME}/${SERVICE_NAME}.log\")
|
action(type=\"omfile\" file=\"/var/log/${SERVICE_NAME}/${SERVICE_NAME}.log\")
|
||||||
stop
|
stop
|
||||||
|
|
|
@ -27,8 +27,15 @@ echo "deb https://deb.nodesource.com/$NODEREPO $CODENAME main" > /etc/apt/source
|
||||||
echo "deb-src https://deb.nodesource.com/$NODEREPO $CODENAME main" >> /etc/apt/sources.list.d/nodesource.list
|
echo "deb-src https://deb.nodesource.com/$NODEREPO $CODENAME main" >> /etc/apt/sources.list.d/nodesource.list
|
||||||
|
|
||||||
# mongo keys
|
# mongo keys
|
||||||
|
|
||||||
|
MONGORELEASE=$CODENAME
|
||||||
|
if [ "$MONGORELEASE" = "focal" ]; then
|
||||||
|
# Ubuntu 20 is not yet supported (as of 2020-07-01), fallback to 18
|
||||||
|
MONGORELEASE="bionic"
|
||||||
|
fi
|
||||||
|
|
||||||
wget -qO- https://www.mongodb.org/static/pgp/server-${MONGODB}.asc | apt-key add
|
wget -qO- https://www.mongodb.org/static/pgp/server-${MONGODB}.asc | apt-key add
|
||||||
echo "deb [ arch=amd64 ] http://repo.mongodb.org/apt/ubuntu $CODENAME/mongodb-org/$MONGODB multiverse" > /etc/apt/sources.list.d/mongodb-org.list
|
echo "deb [ arch=amd64 ] http://repo.mongodb.org/apt/ubuntu $MONGORELEASE/mongodb-org/$MONGODB multiverse" > /etc/apt/sources.list.d/mongodb-org.list
|
||||||
|
|
||||||
# rspamd
|
# rspamd
|
||||||
wget -O- https://rspamd.com/apt-stable/gpg.key | apt-key add -
|
wget -O- https://rspamd.com/apt-stable/gpg.key | apt-key add -
|
||||||
|
|
Loading…
Reference in a new issue