mirror of
https://github.com/nodemailer/wildduck.git
synced 2024-12-27 02:10:52 +08:00
v1.25.0
This commit is contained in:
parent
faa713d12e
commit
4f0c25aa4c
7 changed files with 50 additions and 61 deletions
|
@ -8,7 +8,7 @@ secure=false
|
|||
|
||||
# If set requires all API calls to have accessToken query argument with that value
|
||||
# http://localhost:8080/users?accessToken=somesecretvalue
|
||||
#accessToken="somesecretvalue"
|
||||
accessToken="somesecretvalue"
|
||||
|
||||
[accessControl]
|
||||
# If true then require a valid access token to perform API calls
|
||||
|
|
|
@ -278,6 +278,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler) => {
|
|||
* @apiSuccess {String} results.bcc.address Address of the recipient
|
||||
* @apiSuccess {String} results.subject Message subject
|
||||
* @apiSuccess {String} results.date Datestring
|
||||
* @apiSuccess {Number} results.size Message size in bytes
|
||||
* @apiSuccess {String} results.intro First 128 bytes of the message
|
||||
* @apiSuccess {Boolean} results.attachments Does the message have attachments
|
||||
* @apiSuccess {Boolean} results.seen Is this message alread seen or not
|
||||
|
@ -317,6 +318,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler) => {
|
|||
* "date": "2003-10-24T06:28:34.000Z",
|
||||
* "intro": "Welcome to Ryan Finnie's MIME torture test. This message was designed to introduce a couple of the newer features of MIME-aware…",
|
||||
* "attachments": true,
|
||||
* "size": 1234,
|
||||
* "seen": true,
|
||||
* "deleted": false,
|
||||
* "flagged": true,
|
||||
|
@ -460,6 +462,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler) => {
|
|||
'mimeTree.parsedHeader.content-type': true,
|
||||
'mimeTree.parsedHeader.references': true,
|
||||
ha: true,
|
||||
size: true,
|
||||
intro: true,
|
||||
unseen: true,
|
||||
undeleted: true,
|
||||
|
@ -985,6 +988,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler) => {
|
|||
'mimeTree.parsedHeader.references': true,
|
||||
ha: true,
|
||||
intro: true,
|
||||
size: true,
|
||||
unseen: true,
|
||||
undeleted: true,
|
||||
flagged: true,
|
||||
|
@ -2465,7 +2469,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler) => {
|
|||
let envelopeFrom = envelope.from;
|
||||
envelope.from = data.from.address = await validateFromAddress(userData, envelopeFrom);
|
||||
|
||||
if (!envelope.to.length && referencedMessage && ['reply', 'replyAll'].includes(result.value.reference.action)) {
|
||||
if (!result.value.to && !envelope.to.length && referencedMessage && ['reply', 'replyAll'].includes(result.value.reference.action)) {
|
||||
envelope.to = envelope.to.concat(parseAddresses(referencedMessage.replyTo || [])).concat(parseAddresses(referencedMessage.replyCc || []));
|
||||
data.to = [].concat(referencedMessage.replyTo || []);
|
||||
data.cc = [].concat(referencedMessage.replyCc || []);
|
||||
|
@ -3246,6 +3250,7 @@ module.exports = (db, server, messageHandler, userHandler, storageHandler) => {
|
|||
'mimeTree.parsedHeader.references': true,
|
||||
ha: true,
|
||||
intro: true,
|
||||
size: true,
|
||||
unseen: true,
|
||||
undeleted: true,
|
||||
flagged: true,
|
||||
|
@ -3935,6 +3940,7 @@ function formatMessageListing(messageData) {
|
|||
date: messageData.hdate.toISOString(),
|
||||
intro: messageData.intro,
|
||||
attachments: !!messageData.ha,
|
||||
size: messageData.size,
|
||||
seen: !messageData.unseen,
|
||||
deleted: !messageData.undeleted,
|
||||
flagged: messageData.flagged,
|
||||
|
|
|
@ -483,9 +483,11 @@ class FilterHandler {
|
|||
filterResults.push({ delete: true });
|
||||
|
||||
return {
|
||||
userData,
|
||||
response: 'Message dropped by policy as ' + prepared.id.toString(),
|
||||
error: err
|
||||
response: {
|
||||
userData,
|
||||
response: 'Message dropped by policy as ' + prepared.id.toString(),
|
||||
error: err
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -700,13 +702,7 @@ async function checkFilter(filterData, prepared, maildata) {
|
|||
}
|
||||
}
|
||||
|
||||
if (
|
||||
query.text &&
|
||||
maildata.text
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, ' ')
|
||||
.indexOf(query.text.toLowerCase()) < 0
|
||||
) {
|
||||
if (query.text && maildata.text.toLowerCase().replace(/\s+/g, ' ').indexOf(query.text.toLowerCase()) < 0) {
|
||||
// message plaintext does not match the text field value
|
||||
return false;
|
||||
}
|
||||
|
@ -733,10 +729,7 @@ function parseReceived(str) {
|
|||
}
|
||||
});
|
||||
|
||||
let date = str
|
||||
.split(';')
|
||||
.pop()
|
||||
.trim();
|
||||
let date = str.split(';').pop().trim();
|
||||
if (date) {
|
||||
date = new Date(date);
|
||||
if (date.getTime()) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
const crypto = require('crypto');
|
||||
const uuidV1 = require('uuid/v1');
|
||||
const { v1: uuidV1 } = require('uuid');
|
||||
const ObjectID = require('mongodb').ObjectID;
|
||||
const Indexer = require('../imap-core/lib/indexer/indexer');
|
||||
const ImapNotifier = require('./imap-notifier');
|
||||
|
@ -470,10 +470,7 @@ class MessageHandler {
|
|||
|
||||
let raw = options.rawchunks || options.raw;
|
||||
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 }).toArray();
|
||||
|
||||
let now = new Date();
|
||||
for (let auditData of audits) {
|
||||
|
@ -505,9 +502,7 @@ class MessageHandler {
|
|||
};
|
||||
|
||||
// do not use more suitable .finally() as it is not supported in Node v8
|
||||
return processAudits()
|
||||
.then(next)
|
||||
.catch(next);
|
||||
return processAudits().then(next).catch(next);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
@ -600,7 +595,7 @@ class MessageHandler {
|
|||
_user: messageData.user,
|
||||
_mailbox: messageData.mailbox,
|
||||
_uid: messageData.uid,
|
||||
_message_id: messageData._id,
|
||||
_stored_id: messageData._id,
|
||||
_expires: messageData.rdate,
|
||||
_sess: options.session && options.session.id,
|
||||
_size: messageData.size
|
||||
|
@ -1142,10 +1137,7 @@ class MessageHandler {
|
|||
.map(line => {
|
||||
line = Buffer.from(line, 'binary').toString();
|
||||
|
||||
let key = line
|
||||
.substr(0, line.indexOf(':'))
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
let key = line.substr(0, line.indexOf(':')).trim().toLowerCase();
|
||||
|
||||
if (!INDEXED_HEADERS.includes(key)) {
|
||||
// do not index this header
|
||||
|
@ -1180,17 +1172,13 @@ class MessageHandler {
|
|||
|
||||
// trim long values as mongodb indexed fields can not be too long
|
||||
if (Buffer.byteLength(key, 'utf-8') >= 255) {
|
||||
key = Buffer.from(key)
|
||||
.slice(0, 255)
|
||||
.toString();
|
||||
key = Buffer.from(key).slice(0, 255).toString();
|
||||
key = key.substr(0, key.length - 4);
|
||||
}
|
||||
|
||||
if (Buffer.byteLength(value, 'utf-8') >= 880) {
|
||||
// value exceeds MongoDB max indexed value length
|
||||
value = Buffer.from(value)
|
||||
.slice(0, 880)
|
||||
.toString();
|
||||
value = Buffer.from(value).slice(0, 880).toString();
|
||||
// remove last 4 chars to be sure we do not have any incomplete unicode sequences
|
||||
value = value.substr(0, value.length - 4);
|
||||
}
|
||||
|
@ -1270,13 +1258,7 @@ class MessageHandler {
|
|||
.split(/\s+/)
|
||||
.map(id => id.replace(/[<>]/g, '').trim())
|
||||
.filter(id => id)
|
||||
.map(id =>
|
||||
crypto
|
||||
.createHash('sha1')
|
||||
.update(id)
|
||||
.digest('base64')
|
||||
.replace(/[=]+$/g, '')
|
||||
)
|
||||
.map(id => crypto.createHash('sha1').update(id).digest('base64').replace(/[=]+$/g, ''))
|
||||
);
|
||||
|
||||
subject = this.normalizeSubject(subject, {
|
||||
|
@ -1617,13 +1599,7 @@ class MessageHandler {
|
|||
if (/^content-type:/i.test(line)) {
|
||||
let parts = line.split(':');
|
||||
let value = parts.slice(1).join(':');
|
||||
if (
|
||||
value
|
||||
.split(';')
|
||||
.shift()
|
||||
.trim()
|
||||
.toLowerCase() === 'multipart/encrypted'
|
||||
) {
|
||||
if (value.split(';').shift().trim().toLowerCase() === 'multipart/encrypted') {
|
||||
// message is already encrypted, do nothing
|
||||
return callback(null, false);
|
||||
}
|
||||
|
|
|
@ -470,7 +470,22 @@ class POP3Connection extends EventEmitter {
|
|||
|
||||
// https://tools.ietf.org/html/rfc1939#section-6
|
||||
command_QUIT() {
|
||||
let finish = () => {
|
||||
let deleted = this.session.listing.messages.filter(message => message.popped);
|
||||
|
||||
let finish = err => {
|
||||
if (!err) {
|
||||
deleted.forEach(message => {
|
||||
this._server.loggelf({
|
||||
short_message: '[POP3DELETE]',
|
||||
_mail_action: 'pop3_delete',
|
||||
_message_id: message.id,
|
||||
_username: this.session.user && this.session.user.username,
|
||||
_sess: this.id,
|
||||
_ip: this.remoteAddress
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.session = false;
|
||||
this.send('+OK Bye');
|
||||
this.close();
|
||||
|
@ -481,7 +496,6 @@ class POP3Connection extends EventEmitter {
|
|||
}
|
||||
this.session.state = 'UPDATE';
|
||||
|
||||
let deleted = this.session.listing.messages.filter(message => message.popped);
|
||||
let seen = this.session.listing.messages.filter(message => !message.seen && message.fetched && !message.popped);
|
||||
|
||||
if (!deleted.length && !seen.length) {
|
||||
|
@ -813,9 +827,7 @@ class POP3Connection extends EventEmitter {
|
|||
return next();
|
||||
}
|
||||
|
||||
let credentials = Buffer.from(plain, 'base64')
|
||||
.toString()
|
||||
.split('\x00');
|
||||
let credentials = Buffer.from(plain, 'base64').toString().split('\x00');
|
||||
if (credentials.length !== 3) {
|
||||
this.send('-ERR malformed command');
|
||||
return next();
|
||||
|
|
14
package.json
14
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wildduck",
|
||||
"version": "1.24.0",
|
||||
"version": "1.25.0",
|
||||
"description": "IMAP/POP3 server built with Node.js and MongoDB",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
@ -16,7 +16,7 @@
|
|||
"license": "EUPL-1.1+",
|
||||
"devDependencies": {
|
||||
"ajv": "6.12.2",
|
||||
"apidoc": "0.20.1",
|
||||
"apidoc": "0.22.1",
|
||||
"browserbox": "0.9.1",
|
||||
"chai": "4.2.0",
|
||||
"eslint": "6.8.0",
|
||||
|
@ -29,7 +29,7 @@
|
|||
"grunt-shell-spawn": "0.4.0",
|
||||
"grunt-wait": "0.3.0",
|
||||
"mailparser": "2.7.7",
|
||||
"mocha": "7.1.1",
|
||||
"mocha": "7.1.2",
|
||||
"request": "2.88.2",
|
||||
"supertest": "4.0.2"
|
||||
},
|
||||
|
@ -55,8 +55,8 @@
|
|||
"libqp": "1.1.0",
|
||||
"mailsplit": "4.6.4",
|
||||
"mobileconfig": "2.3.1",
|
||||
"mongo-cursor-pagination": "7.2.0",
|
||||
"mongodb": "3.5.6",
|
||||
"mongo-cursor-pagination": "7.3.0",
|
||||
"mongodb": "3.5.7",
|
||||
"mongodb-extended-json": "1.11.0",
|
||||
"node-forge": "0.9.1",
|
||||
"nodemailer": "6.4.6",
|
||||
|
@ -72,8 +72,8 @@
|
|||
"speakeasy": "2.0.0",
|
||||
"u2f": "0.1.3",
|
||||
"utf7": "1.0.2",
|
||||
"uuid": "7.0.3",
|
||||
"wild-config": "1.5.0",
|
||||
"uuid": "8.0.0",
|
||||
"wild-config": "1.5.1",
|
||||
"yargs": "15.3.1"
|
||||
},
|
||||
"repository": {
|
||||
|
|
2
pop3.js
2
pop3.js
|
@ -440,6 +440,8 @@ module.exports = done => {
|
|||
loggelf: message => loggelf(message)
|
||||
});
|
||||
|
||||
server.loggelf = loggelf;
|
||||
|
||||
server.on('error', err => {
|
||||
if (!started) {
|
||||
started = true;
|
||||
|
|
Loading…
Reference in a new issue