mirror of
https://github.com/nodemailer/wildduck.git
synced 2025-03-01 10:24:40 +08:00
v1.10.10
This commit is contained in:
parent
0b7588b960
commit
b8f9c8882d
13 changed files with 99 additions and 33 deletions
26
api.js
26
api.js
|
@ -14,6 +14,7 @@ const tools = require('./lib/tools');
|
|||
const crypto = require('crypto');
|
||||
const Gelf = require('gelf');
|
||||
const os = require('os');
|
||||
const util = require('util');
|
||||
|
||||
const usersRoutes = require('./lib/api/users');
|
||||
const addressesRoutes = require('./lib/api/addresses');
|
||||
|
@ -72,15 +73,22 @@ const serverOptions = {
|
|||
};
|
||||
|
||||
Object.keys(req.params || {}).forEach(key => {
|
||||
let value = (req.params[key] || '').toString().trim();
|
||||
let value =
|
||||
typeof req.params[key] === 'string'
|
||||
? req.params[key]
|
||||
: util
|
||||
.inspect(req.params[key], false, 3)
|
||||
.toString()
|
||||
.trim();
|
||||
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (['password'].includes(key)) {
|
||||
value = '***';
|
||||
} else if (value.length > 64) {
|
||||
value = value.substr(0, 63) + '…';
|
||||
} else if (value.length > 128) {
|
||||
value = value.substr(0, 128) + '…';
|
||||
}
|
||||
|
||||
if (key.length > 30) {
|
||||
|
@ -95,10 +103,16 @@ const serverOptions = {
|
|||
if (!body || !['id'].includes(key)) {
|
||||
return;
|
||||
}
|
||||
value = (value || '').toString().trim();
|
||||
value =
|
||||
typeof value === 'string'
|
||||
? value
|
||||
: util
|
||||
.inspect(value, false, 3)
|
||||
.toString()
|
||||
.trim();
|
||||
|
||||
if (value.length > 64) {
|
||||
value = value.substr(0, 63) + '…';
|
||||
if (value.length > 128) {
|
||||
value = value.substr(0, 128) + '…';
|
||||
}
|
||||
|
||||
if (key.length > 30) {
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
define({
"name": "wildduck",
"version": "1.0.0",
"description": "WildDuck API docs",
"title": "WildDuck API",
"url": "https://api.wildduck.email",
"sampleUrl": false,
"defaultVersion": "0.0.0",
"apidoc": "0.3.0",
"generator": {
"name": "apidoc",
"time": "2018-11-12T11:44:06.203Z",
"url": "http://apidocjs.com",
"version": "0.17.6"
}
});
|
||||
define({
"name": "wildduck",
"version": "1.0.0",
"description": "WildDuck API docs",
"title": "WildDuck API",
"url": "https://api.wildduck.email",
"sampleUrl": false,
"defaultVersion": "0.0.0",
"apidoc": "0.3.0",
"generator": {
"name": "apidoc",
"time": "2018-11-14T11:21:41.763Z",
"url": "http://apidocjs.com",
"version": "0.17.6"
}
});
|
||||
|
|
|
@ -1 +1 @@
|
|||
{
"name": "wildduck",
"version": "1.0.0",
"description": "WildDuck API docs",
"title": "WildDuck API",
"url": "https://api.wildduck.email",
"sampleUrl": false,
"defaultVersion": "0.0.0",
"apidoc": "0.3.0",
"generator": {
"name": "apidoc",
"time": "2018-11-12T11:44:06.203Z",
"url": "http://apidocjs.com",
"version": "0.17.6"
}
}
|
||||
{
"name": "wildduck",
"version": "1.0.0",
"description": "WildDuck API docs",
"title": "WildDuck API",
"url": "https://api.wildduck.email",
"sampleUrl": false,
"defaultVersion": "0.0.0",
"apidoc": "0.3.0",
"generator": {
"name": "apidoc",
"time": "2018-11-14T11:21:41.763Z",
"url": "http://apidocjs.com",
"version": "0.17.6"
}
}
|
||||
|
|
|
@ -343,6 +343,7 @@ class IMAPConnection extends EventEmitter {
|
|||
if (err && /SSL[23]*_GET_CLIENT_HELLO|ssl[23]*_read_bytes|ssl_bytes_to_cipher_list/i.test(err.message)) {
|
||||
let message = err.message;
|
||||
err.message = 'Failed to establish TLS session';
|
||||
err.code = err.code || 'TLSError';
|
||||
err.meta = {
|
||||
protocol: 'imap',
|
||||
stage: 'starttls',
|
||||
|
@ -353,6 +354,7 @@ class IMAPConnection extends EventEmitter {
|
|||
|
||||
if (!err || !err.message) {
|
||||
err = new Error('Socket closed unexpectedly');
|
||||
err.code = 'SocketError';
|
||||
err.meta = {
|
||||
remoteAddress: this.remoteAddress
|
||||
};
|
||||
|
|
|
@ -309,6 +309,7 @@ class IMAPServer extends EventEmitter {
|
|||
if (err && /SSL[23]*_GET_CLIENT_HELLO|ssl[23]*_read_bytes|ssl_bytes_to_cipher_list/i.test(err.message)) {
|
||||
let message = err.message;
|
||||
err.message = 'Failed to establish TLS session';
|
||||
err.code = err.code || 'TLSError';
|
||||
err.meta = {
|
||||
protocol: 'imap',
|
||||
stage: 'connect',
|
||||
|
@ -318,6 +319,7 @@ class IMAPServer extends EventEmitter {
|
|||
}
|
||||
if (!err || !err.message) {
|
||||
err = new Error('Socket closed while initiating TLS');
|
||||
err.code = 'SocketError';
|
||||
err.report = false;
|
||||
err.meta = {
|
||||
protocol: 'imap',
|
||||
|
|
|
@ -113,6 +113,15 @@ indexes:
|
|||
key:
|
||||
user: 1
|
||||
|
||||
- collection: asps
|
||||
type: users # index applies to users database
|
||||
index:
|
||||
name: entry_autoexpire
|
||||
# autoremove log entries after expire seconds
|
||||
expireAfterSeconds: 0
|
||||
key:
|
||||
expires: 1
|
||||
|
||||
# Indexes for the authentication log collection
|
||||
- collection: authlog
|
||||
type: users # index applies to users database
|
||||
|
|
|
@ -27,6 +27,7 @@ module.exports = (db, server, userHandler) => {
|
|||
* }
|
||||
*
|
||||
* @apiParam {String} user ID of the User
|
||||
* @apiParam {Boolean} [showAll=false] If not true then skips entries with a TTL set
|
||||
*
|
||||
* @apiSuccess {Boolean} success Indicates successful response
|
||||
* @apiSuccess {Object[]} results Event listing
|
||||
|
@ -81,6 +82,10 @@ module.exports = (db, server, userHandler) => {
|
|||
.lowercase()
|
||||
.length(24)
|
||||
.required(),
|
||||
showAll: Joi.boolean()
|
||||
.truthy(['Y', 'true', 'yes', 'on', '1', 1])
|
||||
.falsy(['N', 'false', 'no', 'off', '0', 0, ''])
|
||||
.default(false),
|
||||
sess: Joi.string().max(255),
|
||||
ip: Joi.string().ip({
|
||||
version: ['ipv4', 'ipv6'],
|
||||
|
@ -88,6 +93,10 @@ module.exports = (db, server, userHandler) => {
|
|||
})
|
||||
});
|
||||
|
||||
if (req.query.showAll) {
|
||||
req.params.showAll = req.query.showAll;
|
||||
}
|
||||
|
||||
const result = Joi.validate(req.params, schema, {
|
||||
abortEarly: false,
|
||||
convert: true
|
||||
|
@ -109,6 +118,7 @@ module.exports = (db, server, userHandler) => {
|
|||
}
|
||||
|
||||
let user = new ObjectID(result.value.user);
|
||||
let showAll = result.value.showAll;
|
||||
|
||||
let userData;
|
||||
|
||||
|
@ -163,16 +173,27 @@ module.exports = (db, server, userHandler) => {
|
|||
res.json({
|
||||
success: true,
|
||||
|
||||
results: asps.map(asp => ({
|
||||
id: asp._id,
|
||||
description: asp.description,
|
||||
scopes: asp.scopes.includes('*') ? [...consts.SCOPES] : asp.scopes,
|
||||
lastUse: {
|
||||
time: asp.used || false,
|
||||
event: asp.authEvent || false
|
||||
},
|
||||
created: asp.created
|
||||
}))
|
||||
results: asps
|
||||
.filter(asp => {
|
||||
if (showAll) {
|
||||
return true;
|
||||
}
|
||||
if (asp.ttl) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map(asp => ({
|
||||
id: asp._id,
|
||||
description: asp.description,
|
||||
scopes: asp.scopes.includes('*') ? [...consts.SCOPES] : asp.scopes,
|
||||
lastUse: {
|
||||
time: asp.used || false,
|
||||
event: asp.authEvent || false
|
||||
},
|
||||
expires: asp.expires,
|
||||
created: asp.created
|
||||
}))
|
||||
});
|
||||
|
||||
return next();
|
||||
|
@ -307,6 +328,7 @@ module.exports = (db, server, userHandler) => {
|
|||
time: aspData.used || false,
|
||||
event: aspData.authEvent || false
|
||||
},
|
||||
expires: asp.expires,
|
||||
created: aspData.created
|
||||
});
|
||||
|
||||
|
@ -329,6 +351,7 @@ module.exports = (db, server, userHandler) => {
|
|||
* @apiParam {String[]} scopes List of scopes this Password applies to. Special scope "*" indicates that this password can be used for any scope except "master"
|
||||
* @apiParam {Boolean} [generateMobileconfig] If true then result contains a mobileconfig formatted file with account config
|
||||
* @apiParam {String} [address] E-mail address to be used as the account address in mobileconfig file. Must be one of the listed identity addresses of the user. Defaults to the main address of the user
|
||||
* @apiParam {Number} [ttl] TTL in seconds for this password. Every time password is used, TTL is reset to this value
|
||||
* @apiParam {String} [sess] Session identifier for the logs
|
||||
* @apiParam {String} [ip] IP address for the logs
|
||||
*
|
||||
|
@ -392,6 +415,7 @@ module.exports = (db, server, userHandler) => {
|
|||
.truthy(['Y', 'true', 'yes', 'on', '1', 1])
|
||||
.falsy(['N', 'false', 'no', 'off', '0', 0, ''])
|
||||
.default(false),
|
||||
ttl: Joi.number().empty([0, '']),
|
||||
sess: Joi.string().max(255),
|
||||
ip: Joi.string().ip({
|
||||
version: ['ipv4', 'ipv6'],
|
||||
|
|
|
@ -397,7 +397,7 @@ module.exports = (db, server, userHandler) => {
|
|||
nextCursor: listing.hasNext ? listing.next : false,
|
||||
results: (listing.results || []).map(resultData => {
|
||||
let response = {
|
||||
id: resultData._id
|
||||
id: (resultData._id || '').toString()
|
||||
};
|
||||
Object.keys(resultData).forEach(key => {
|
||||
if (!['_id', 'user'].includes(key)) {
|
||||
|
|
|
@ -102,6 +102,7 @@ class POP3Server extends EventEmitter {
|
|||
if (err && /SSL[23]*_GET_CLIENT_HELLO|ssl[23]*_read_bytes|ssl_bytes_to_cipher_list/i.test(err.message)) {
|
||||
let message = err.message;
|
||||
err.message = 'Failed to establish TLS session';
|
||||
err.code = err.code || 'TLSError';
|
||||
err.meta = {
|
||||
protocol: 'pop3',
|
||||
stage: 'connect',
|
||||
|
@ -112,6 +113,7 @@ class POP3Server extends EventEmitter {
|
|||
|
||||
if (!err || !err.message) {
|
||||
err = new Error('Socket closed while initiating TLS');
|
||||
err.code = 'SocketError';
|
||||
err.meta = {
|
||||
protocol: 'pop3',
|
||||
stage: 'connect',
|
||||
|
|
|
@ -835,16 +835,23 @@ class UserHandler {
|
|||
if (err) {
|
||||
// don't really care
|
||||
}
|
||||
let aspUpdates = {
|
||||
used: new Date(),
|
||||
authEvent,
|
||||
authIp: meta.ip
|
||||
};
|
||||
|
||||
if (asp.ttl) {
|
||||
// extend temporary password ttl every time it is used
|
||||
aspUpdates.expires = new Date(Date.now() + asp.ttl * 1000);
|
||||
}
|
||||
|
||||
this.users.collection('asps').findOneAndUpdate(
|
||||
{
|
||||
_id: asp._id
|
||||
},
|
||||
{
|
||||
$set: {
|
||||
used: new Date(),
|
||||
authEvent,
|
||||
authIp: meta.ip
|
||||
}
|
||||
$set: aspUpdates
|
||||
},
|
||||
() => {
|
||||
authSuccess(
|
||||
|
@ -1063,6 +1070,11 @@ class UserHandler {
|
|||
created: new Date()
|
||||
};
|
||||
|
||||
if (data.ttl) {
|
||||
passwordData.ttl = data.ttl;
|
||||
passwordData.expires = new Date(Date.now() + data.ttl * 1000);
|
||||
}
|
||||
|
||||
// register this address as the default address for that user
|
||||
return this.users.collection('users').findOne(
|
||||
{
|
||||
|
@ -1095,6 +1107,7 @@ class UserHandler {
|
|||
action: 'create asp',
|
||||
asp: passwordData._id,
|
||||
aname: passwordData.description,
|
||||
temporary: passwordData.ttl ? true : false,
|
||||
result: 'success',
|
||||
sess: data.sess,
|
||||
ip: data.ip
|
||||
|
|
14
package.json
14
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "wildduck",
|
||||
"version": "1.10.9",
|
||||
"version": "1.10.10",
|
||||
"description": "IMAP/POP3 server built with Node.js and MongoDB",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
@ -17,12 +17,12 @@
|
|||
"license": "EUPL-1.1+",
|
||||
"devDependencies": {
|
||||
"ajv": "6.5.5",
|
||||
"apidoc": "0.17.6",
|
||||
"apidoc": "0.17.7",
|
||||
"browserbox": "0.9.1",
|
||||
"chai": "4.2.0",
|
||||
"eslint": "5.8.0",
|
||||
"eslint": "5.9.0",
|
||||
"eslint-config-nodemailer": "1.2.0",
|
||||
"eslint-config-prettier": "3.1.0",
|
||||
"eslint-config-prettier": "3.3.0",
|
||||
"grunt": "1.0.3",
|
||||
"grunt-cli": "1.3.2",
|
||||
"grunt-eslint": "21.0.0",
|
||||
|
@ -30,7 +30,7 @@
|
|||
"grunt-shell-spawn": "0.3.10",
|
||||
"grunt-wait": "0.3.0",
|
||||
"icedfrisby": "1.5.0",
|
||||
"mailparser": "2.4.0",
|
||||
"mailparser": "2.4.2",
|
||||
"markdown-toc": "1.2.0",
|
||||
"mocha": "5.2.0",
|
||||
"request": "2.88.0"
|
||||
|
@ -50,13 +50,13 @@
|
|||
"ioredfour": "1.0.2-ioredis-02",
|
||||
"ioredis": "4.2.0",
|
||||
"isemail": "3.2.0",
|
||||
"joi": "14.0.4",
|
||||
"joi": "14.0.6",
|
||||
"js-yaml": "3.12.0",
|
||||
"key-fingerprint": "1.1.0",
|
||||
"libbase64": "1.0.3",
|
||||
"libmime": "4.0.1",
|
||||
"libqp": "1.1.0",
|
||||
"mailsplit": "4.2.3",
|
||||
"mailsplit": "4.2.4",
|
||||
"mobileconfig": "2.1.0",
|
||||
"mongo-cursor-pagination": "7.1.0",
|
||||
"mongodb": "3.1.9",
|
||||
|
|
Loading…
Reference in a new issue