Merge branch 'master' of github.com:nodemailer/wildduck

This commit is contained in:
Andris Reinman 2019-01-17 11:48:35 +02:00
commit eb70966db1
4 changed files with 228 additions and 32 deletions

View file

@ -144,11 +144,9 @@ module.exports = (db, server, userHandler) => {
user = auth.user;
} catch (err) {
let response = {
error: err.message
error: err.message,
code: 'AuthFailed' || err.code
};
if (err.code) {
response.code = err.code;
}
if (user) {
response.id = user.toString();
}

View file

@ -3209,44 +3209,95 @@ class UserHandler {
checkAddress(username, callback) {
if (username.indexOf('@') < 0) {
// assume regular username
// not formatted as an address, assume regular username
return callback(null, {
unameview: tools.uview(username)
});
}
// try to find existing email address
// we do not use resolveAddress because it is too lax
let address = tools.normalizeAddress(username, { removeLabel: true });
this.users.collection('addresses').findOne(
{
addrview: tools.normalizeAddress(address, false, { removeDots: true })
},
{
projection: {
user: true
}
},
(err, addressData) => {
if (err) {
err.code = 'InternalDatabaseError';
return callback(err);
}
let address = tools.normalizeAddress(username, false, {
removeLabel: true,
removeDots: true
});
let domain = address.substr(address.indexOf('@') + 1);
username = address.substr(0, address.indexOf('@'));
if (!addressData || !addressData.user) {
// fall back to username formatted as an address
return callback(null, {
unameview: tools.normalizeAddress(address, false, {
removeDots: true
})
let aliasDomain;
let findAddressData = done => {
this.users.collection('addresses').findOne(
{
addrview: address
},
{
projection: {
user: true
}
},
(err, addressData) => {
if (err) {
err.code = 'InternalDatabaseError';
return callback(err);
}
if (addressData) {
return done(null, addressData);
}
// check if the address uses an alias domain
this.users.collection('domainaliases').findOne({ alias: domain }, (err, aliasData) => {
if (err) {
return done(err);
}
if (!aliasData) {
// not an alias domain, nothing to check for
return done();
}
aliasDomain = aliasData.domain;
this.users.collection('addresses').findOne(
{
addrview: username + '@' + aliasDomain
},
{
projection: {
user: true
}
},
(err, addressData) => {
if (err) {
err.code = 'InternalDatabaseError';
return done(err);
}
return done(null, addressData);
}
);
});
}
);
};
callback(null, {
_id: addressData.user
findAddressData((err, addressData) => {
if (err) {
return callback(err);
}
if (addressData && !addressData.user) {
// found a non-user address
return callback(null, false);
}
if (!addressData) {
// fall back to username formatted as an address
return callback(null, {
unameview: address
});
}
);
callback(null, {
_id: addressData.user
});
});
}
}

View file

@ -1,6 +1,6 @@
{
"name": "wildduck",
"version": "1.12.3",
"version": "1.12.4",
"description": "IMAP/POP3 server built with Node.js and MongoDB",
"main": "server.js",
"scripts": {

View file

@ -15,6 +15,23 @@ let userId = false;
describe('API tests', function() {
this.timeout(10000); // eslint-disable-line no-invalid-this
frisby
.create('POST domainaliases')
.post(
URL + '/domainaliases',
{
alias: 'jõgeva.öö',
domain: 'example.com'
},
{ json: true }
)
.expectStatus(200)
.afterJSON(response => {
expect(response).to.exist;
expect(response.success).to.be.true;
})
.toss();
frisby
.create('POST users')
.post(
@ -61,6 +78,136 @@ describe('API tests', function() {
})
.toss();
frisby
.create('POST authenticate')
.post(
URL + '/authenticate',
{
username: 'testuser@example.com',
password: 'secretpass',
scope: 'master'
},
{ json: true }
)
.expectStatus(200)
.afterJSON(response => {
expect(response).to.exist;
expect(response.success).to.be.true;
})
.toss();
frisby
.create('POST authenticate - failure')
.post(
URL + '/authenticate',
{
username: 'testuser@example.com',
password: 'invalid',
scope: 'master'
},
{ json: true }
)
.afterJSON(response => {
expect(response).to.exist;
expect(response.error).to.exist;
expect(response.success).to.not.be.true;
})
.toss();
frisby
.create('POST authenticate - using aliasdomain')
.post(
URL + '/authenticate',
{
username: 'testuser@jõgeva.öö',
password: 'secretpass',
scope: 'master'
},
{ json: true }
)
.expectStatus(200)
.afterJSON(response => {
expect(response).to.exist;
expect(response.success).to.be.true;
})
.toss();
frisby
.create('POST authenticate - failure using aliasdomain')
.post(
URL + '/authenticate',
{
username: 'testuser@jõgeva.öö',
password: 'invalid',
scope: 'master'
},
{ json: true }
)
.afterJSON(response => {
expect(response).to.exist;
expect(response.error).to.exist;
expect(response.success).to.not.be.true;
})
.toss();
frisby
.create('POST users/{id}/asps - generate ASP')
.post(
URL + '/users/' + userId + '/asps',
{
description: 'test',
scopes: ['imap', 'smtp'],
generateMobileconfig: true
},
{ json: true }
)
.afterJSON(response => {
expect(response).to.exist;
expect(response.error).to.not.exist;
expect(response.success).to.be.true;
expect(response.password).to.exist;
expect(response.mobileconfig).to.exist;
let asp = response.password;
frisby
.create('POST authenticate - success on correct scope')
.post(
URL + '/authenticate',
{
username: 'testuser@example.com',
password: asp,
scope: 'imap'
},
{ json: true }
)
.expectStatus(200)
.afterJSON(response => {
expect(response).to.exist;
expect(response.success).to.be.true;
})
.toss();
frisby
.create('POST authenticate - failure on incorrect scope')
.post(
URL + '/authenticate',
{
username: 'testuser@example.com',
password: asp,
scope: 'master'
},
{ json: true }
)
.afterJSON(response => {
expect(response).to.exist;
expect(response.error).to.exist;
expect(response.success).to.not.be.true;
})
.toss();
})
.toss();
frisby
.create('GET users/{id} updated name')
.get(URL + '/users/' + userId)