Move mail related settings to new mail route

there is quite a bit of circular dep between settings, platform and
mail code. this will be removed in future commits.
This commit is contained in:
Girish Ramakrishnan
2018-01-20 18:56:17 -08:00
parent e724913b6c
commit a7de17a160
15 changed files with 655 additions and 601 deletions
+199 -3
View File
@@ -5,6 +5,25 @@ exports = module.exports = {
getStatus: getStatus,
checkRblStatus: checkRblStatus,
getMailFromValidation: getMailFromValidation,
setMailFromValidation: setMailFromValidation,
setCatchAllAddress: setCatchAllAddress,
getCatchAllAddress: getCatchAllAddress,
getMailRelay: getMailRelay,
setMailRelay: setMailRelay,
getMailConfig: getMailConfig,
setMailConfig: setMailConfig,
createMailConfig: createMailConfig,
MAIL_FROM_VALIDATION_KEY: 'mail_from_validation',
CATCH_ALL_ADDRESS_KEY: 'catch_all_address',
MAIL_RELAY_KEY: 'mail_relay',
MAIL_CONFIG_KEY: 'mail_config',
MailError: MailError
};
@@ -12,18 +31,33 @@ var assert = require('assert'),
async = require('async'),
cloudron = require('./cloudron.js'),
config = require('./config.js'),
debug = require('debug')('box:email'),
DatabaseError = require('./databaseerror.js'),
debug = require('debug')('box:mail'),
dig = require('./dig.js'),
net = require('net'),
nodemailer = require('nodemailer'),
paths = require('./paths.js'),
platform = require('./platform.js'),
safe = require('safetydance'),
settings = require('./settings.js'),
settingsdb = require('./settingsdb.js'),
smtpTransport = require('nodemailer-smtp-transport'),
sysinfo = require('./sysinfo.js'),
user = require('./user.js'),
util = require('util'),
_ = require('underscore');
const digOptions = { server: '127.0.0.1', port: 53, timeout: 5000 };
var NOOP_CALLBACK = function (error) { if (error) debug(error); };
var gDefaults = (function () {
var result = { };
result[exports.MAIL_FROM_VALIDATION_KEY] = true;
result[exports.CATCH_ALL_ADDRESS_KEY] = [ ];
result[exports.MAIL_RELAY_KEY] = { provider: 'cloudron-smtp' };
result[exports.MAIL_CONFIG_KEY] = { enabled: false };
return result;
})();
function MailError(reason, errorOrMessage) {
assert.strictEqual(typeof reason, 'string');
@@ -370,7 +404,7 @@ function getStatus(callback) {
};
}
settings.getMailRelay(function (error, relay) {
getMailRelay(function (error, relay) {
if (error) return callback(error);
var checks = [
@@ -396,3 +430,165 @@ function getStatus(callback) {
});
});
}
// FIXME: temporary function till we move to domain API
function getAll(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.getAll(function (error, settings) {
if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error));
var result = _.extend({ }, gDefaults);
settings.forEach(function (setting) { result[setting.name] = setting.value; });
// convert JSON objects
[ exports.CATCH_ALL_ADDRESS_KEY, exports.MAIL_RELAY_KEY, exports.MAIL_CONFIG_KEY ].forEach(function (key) {
result[key] = typeof result[key] === 'object' ? result[key] : safe.JSON.parse(result[key]);
});
callback(null, result);
});
}
function createMailConfig(callback) {
assert.strictEqual(typeof callback, 'function');
const fqdn = config.fqdn();
const mailFqdn = config.mailFqdn();
const alertsFrom = 'no-reply@' + config.fqdn();
debug('createMailConfig: generating mail config');
user.getOwner(function (error, owner) {
var alertsTo = config.provider() === 'caas' ? [ 'support@cloudron.io' ] : [ ];
alertsTo.concat(error ? [] : owner.email).join(','); // owner may not exist yet
getAll(function (error, result) {
if (error) return callback(error);
var catchAll = result[exports.CATCH_ALL_ADDRESS_KEY].map(function (c) { return `${c}@${fqdn}`; }).join(',');
var mailFromValidation = result[exports.MAIL_FROM_VALIDATION_KEY];
if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/mail.ini',
`mail_domains=${fqdn}\nmail_default_domain=${fqdn}\nmail_server_name=${mailFqdn}\nalerts_from=${alertsFrom}\nalerts_to=${alertsTo}\ncatch_all=${catchAll}\nmail_from_validation=${mailFromValidation}\n`, 'utf8')) {
return callback(new Error('Could not create mail var file:' + safe.error.message));
}
var relay = result[exports.MAIL_RELAY_KEY];
const enabled = relay.provider !== 'cloudron-smtp' ? true : false,
host = relay.host || '',
port = relay.port || 25,
username = relay.username || '',
password = relay.password || '';
if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/smtp_forward.ini',
`enable_outbound=${enabled}\nhost=${host}\nport=${port}\nenable_tls=true\nauth_type=plain\nauth_user=${username}\nauth_pass=${password}`, 'utf8')) {
return callback(new Error('Could not create mail var file:' + safe.error.message));
}
callback();
});
});
}
function getMailFromValidation(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.MAIL_FROM_VALIDATION_KEY, function (error, enabled) {
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.MAIL_FROM_VALIDATION_KEY]);
if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error));
callback(null, !!enabled); // settingsdb holds string values only
});
}
function setMailFromValidation(enabled, callback) {
assert.strictEqual(typeof enabled, 'boolean');
assert.strictEqual(typeof callback, 'function');
settingsdb.set(exports.MAIL_FROM_VALIDATION_KEY, enabled ? 'enabled' : '', function (error) {
if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error));
createMailConfig(NOOP_CALLBACK);
callback(null);
});
}
function getCatchAllAddress(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.CATCH_ALL_ADDRESS_KEY, function (error, value) {
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.CATCH_ALL_ADDRESS_KEY]);
if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error));
callback(null, JSON.parse(value));
});
}
function setCatchAllAddress(address, callback) {
assert(Array.isArray(address));
assert.strictEqual(typeof callback, 'function');
settingsdb.set(exports.CATCH_ALL_ADDRESS_KEY, JSON.stringify(address), function (error) {
if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error));
createMailConfig(NOOP_CALLBACK);
callback(null);
});
}
function getMailRelay(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.MAIL_RELAY_KEY, function (error, value) {
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.MAIL_RELAY_KEY]);
if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error));
callback(null, JSON.parse(value));
});
}
function setMailRelay(relay, callback) {
assert.strictEqual(typeof relay, 'object');
assert.strictEqual(typeof callback, 'function');
verifyRelay(relay, function (error) {
if (error) return callback(error);
settingsdb.set(exports.MAIL_RELAY_KEY, JSON.stringify(relay), function (error) {
if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error));
platform.restartMail(NOOP_CALLBACK);
callback(null);
});
});
}
function getMailConfig(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.MAIL_CONFIG_KEY, function (error, value) {
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.MAIL_CONFIG_KEY]);
if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error));
callback(null, JSON.parse(value));
});
}
function setMailConfig(mailConfig, callback) {
assert.strictEqual(typeof mailConfig, 'object');
assert.strictEqual(typeof callback, 'function');
settingsdb.set(exports.MAIL_CONFIG_KEY, JSON.stringify(mailConfig), function (error) {
if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error));
platform.restartMail(NOOP_CALLBACK);
callback(null);
});
}
+4 -51
View File
@@ -4,7 +4,7 @@ exports = module.exports = {
start: start,
stop: stop,
createMailConfig: createMailConfig
restartMail: startMail
};
var apps = require('./apps.js'),
@@ -18,15 +18,14 @@ var apps = require('./apps.js'),
hat = require('hat'),
infra = require('./infra_version.js'),
locker = require('./locker.js'),
mail = require('./mail.js'),
nginx = require('./nginx.js'),
os = require('os'),
paths = require('./paths.js'),
safe = require('safetydance'),
semver = require('semver'),
settings = require('./settings.js'),
shell = require('./shell.js'),
taskmanager = require('./taskmanager.js'),
user = require('./user.js'),
util = require('util'),
_ = require('underscore');
@@ -41,10 +40,6 @@ function start(callback) {
debug('initializing addon infrastructure');
// restart mail container if any of these keys change
settings.events.on(settings.MAIL_CONFIG_KEY, function () { startMail(NOOP_CALLBACK); });
settings.events.on(settings.MAIL_RELAY_KEY, function () { startMail(NOOP_CALLBACK); });
certificates.events.on(certificates.EVENT_CERT_CHANGED, function (domain) {
if (domain === '*.' + config.fqdn() || domain === config.adminFqdn()) startMail(NOOP_CALLBACK);
});
@@ -240,48 +235,6 @@ function startMongodb(callback) {
setTimeout(callback, 5000);
}
function createMailConfig(callback) {
assert.strictEqual(typeof callback, 'function');
const fqdn = config.fqdn();
const mailFqdn = config.mailFqdn();
const alertsFrom = 'no-reply@' + config.fqdn();
debug('createMailConfig: generating mail config');
user.getOwner(function (error, owner) {
var alertsTo = config.provider() === 'caas' ? [ 'support@cloudron.io' ] : [ ];
alertsTo.concat(error ? [] : owner.email).join(','); // owner may not exist yet
settings.getAll(function (error, result) {
if (error) return callback(error);
var catchAll = result[settings.CATCH_ALL_ADDRESS_KEY].map(function (c) { return `${c}@${fqdn}`; }).join(',');
var mailFromValidation = result[settings.MAIL_FROM_VALIDATION_KEY];
if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/mail.ini',
`mail_domains=${fqdn}\nmail_default_domain=${fqdn}\nmail_server_name=${mailFqdn}\nalerts_from=${alertsFrom}\nalerts_to=${alertsTo}\ncatch_all=${catchAll}\nmail_from_validation=${mailFromValidation}\n`, 'utf8')) {
return callback(new Error('Could not create mail var file:' + safe.error.message));
}
var relay = result[settings.MAIL_RELAY_KEY];
const enabled = relay.provider !== 'cloudron-smtp' ? true : false,
host = relay.host || '',
port = relay.port || 25,
username = relay.username || '',
password = relay.password || '';
if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/smtp_forward.ini',
`enable_outbound=${enabled}\nhost=${host}\nport=${port}\nenable_tls=true\nauth_type=plain\nauth_user=${username}\nauth_pass=${password}`, 'utf8')) {
return callback(new Error('Could not create mail var file:' + safe.error.message));
}
callback();
});
});
}
function startMail(callback) {
// mail (note: 2525 is hardcoded in mail container and app use this port)
// MAIL_SERVER_NAME is the hostname of the mailserver i.e server uses these certs
@@ -299,12 +252,12 @@ function startMail(callback) {
if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/tls_cert.pem', cert)) return callback(new Error('Could not create cert file:' + safe.error.message));
if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/tls_key.pem', key)) return callback(new Error('Could not create key file:' + safe.error.message));
settings.getMailConfig(function (error, mailConfig) {
mail.getMailConfig(function (error, mailConfig) {
if (error) return callback(error);
shell.execSync('startMail', 'docker rm -f mail || true');
createMailConfig(function (error) {
mail.createMailConfig(function (error) {
if (error) return callback(error);
var ports = mailConfig.enabled ? '-p 587:2525 -p 993:9993 -p 4190:4190 -p 25:2525' : '';
+108 -2
View File
@@ -1,10 +1,24 @@
'use strict';
exports = module.exports = {
getStatus: getStatus
getStatus: getStatus,
getMailFromValidation: getMailFromValidation,
setMailFromValidation: setMailFromValidation,
getCatchAllAddress: getCatchAllAddress,
setCatchAllAddress: setCatchAllAddress,
getMailRelay: getMailRelay,
setMailRelay: setMailRelay,
getMailConfig: getMailConfig,
setMailConfig: setMailConfig,
};
var mail = require('../mail.js'),
var assert = require('assert'),
mail = require('../mail.js'),
MailError = mail.MailError,
HttpError = require('connect-lastmile').HttpError,
HttpSuccess = require('connect-lastmile').HttpSuccess;
@@ -15,3 +29,95 @@ function getStatus(req, res, next) {
next(new HttpSuccess(200, records));
});
}
function getMailFromValidation(req, res, next) {
mail.getMailFromValidation(function (error, enabled) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, { enabled: enabled }));
});
}
function setMailFromValidation(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (typeof req.body.enabled !== 'boolean') return next(new HttpError(400, 'enabled is required'));
mail.setMailFromValidation(req.body.enabled, function (error) {
if (error && error.reason === MailError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(202));
});
}
function getCatchAllAddress(req, res, next) {
mail.getCatchAllAddress(function (error, address) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, { address: address }));
});
}
function setCatchAllAddress(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (!req.body.address || !Array.isArray(req.body.address)) return next(new HttpError(400, 'address array is required'));
for (var i = 0; i < req.body.address.length; i++) {
if (typeof req.body.address[i] !== 'string') return next(new HttpError(400, 'address must be an array of string'));
}
mail.setCatchAllAddress(req.body.address, function (error) {
if (error && error.reason === MailError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(202));
});
}
function getMailRelay(req, res, next) {
mail.getMailRelay(function (error, mail) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, mail));
});
}
function setMailRelay(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (typeof req.body.provider !== 'string') return next(new HttpError(400, 'provider is required'));
if ('host' in req.body && typeof req.body.host !== 'string') return next(new HttpError(400, 'host must be a string'));
if ('port' in req.body && typeof req.body.port !== 'number') return next(new HttpError(400, 'port must be a string'));
if ('username' in req.body && typeof req.body.username !== 'string') return next(new HttpError(400, 'username must be a string'));
if ('password' in req.body && typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be a string'));
mail.setMailRelay(req.body, function (error) {
if (error && error.reason === MailError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(202));
});
}
function getMailConfig(req, res, next) {
mail.getMailConfig(function (error, mail) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, mail));
});
}
function setMailConfig(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (typeof req.body.enabled !== 'boolean') return next(new HttpError(400, 'enabled is required'));
mail.setMailConfig({ enabled: req.body.enabled }, function (error) {
if (error && error.reason === MailError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(202));
});
}
-104
View File
@@ -16,18 +16,6 @@ exports = module.exports = {
getTimeZone: getTimeZone,
setTimeZone: setTimeZone,
getMailConfig: getMailConfig,
setMailConfig: setMailConfig,
getMailRelay: getMailRelay,
setMailRelay: setMailRelay,
getCatchAllAddress: getCatchAllAddress,
setCatchAllAddress: setCatchAllAddress,
getMailFromValidation: getMailFromValidation,
setMailFromValidation: setMailFromValidation,
getAppstoreConfig: getAppstoreConfig,
setAppstoreConfig: setAppstoreConfig,
@@ -106,98 +94,6 @@ function setTimeZone(req, res, next) {
});
}
function getMailConfig(req, res, next) {
settings.getMailConfig(function (error, mail) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, mail));
});
}
function setMailConfig(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (typeof req.body.enabled !== 'boolean') return next(new HttpError(400, 'enabled is required'));
settings.setMailConfig({ enabled: req.body.enabled }, function (error) {
if (error && error.reason === SettingsError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(202));
});
}
function getMailFromValidation(req, res, next) {
settings.getMailFromValidation(function (error, enabled) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, { enabled: enabled }));
});
}
function setMailFromValidation(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (typeof req.body.enabled !== 'boolean') return next(new HttpError(400, 'enabled is required'));
settings.setMailFromValidation(req.body.enabled, function (error) {
if (error && error.reason === SettingsError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(202));
});
}
function getMailRelay(req, res, next) {
settings.getMailRelay(function (error, mail) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, mail));
});
}
function setMailRelay(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (typeof req.body.provider !== 'string') return next(new HttpError(400, 'provider is required'));
if ('host' in req.body && typeof req.body.host !== 'string') return next(new HttpError(400, 'host must be a string'));
if ('port' in req.body && typeof req.body.port !== 'number') return next(new HttpError(400, 'port must be a string'));
if ('username' in req.body && typeof req.body.username !== 'string') return next(new HttpError(400, 'username must be a string'));
if ('password' in req.body && typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be a string'));
settings.setMailRelay(req.body, function (error) {
if (error && error.reason === SettingsError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(202));
});
}
function getCatchAllAddress(req, res, next) {
settings.getCatchAllAddress(function (error, address) {
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(200, { address: address }));
});
}
function setCatchAllAddress(req, res, next) {
assert.strictEqual(typeof req.body, 'object');
if (!req.body.address || !Array.isArray(req.body.address)) return next(new HttpError(400, 'address array is required'));
for (var i = 0; i < req.body.address.length; i++) {
if (typeof req.body.address[i] !== 'string') return next(new HttpError(400, 'address must be an array of string'));
}
settings.setCatchAllAddress(req.body.address, function (error) {
if (error && error.reason === SettingsError.BAD_FIELD) return next(new HttpError(400, error.message));
if (error) return next(new HttpError(500, error));
next(new HttpSuccess(202));
});
}
function setCloudronAvatar(req, res, next) {
assert.strictEqual(typeof req.files, 'object');
+184
View File
@@ -10,7 +10,9 @@ var async = require('async'),
config = require('../../config.js'),
database = require('../../database.js'),
expect = require('expect.js'),
mail = require('../../mail.js'),
server = require('../../server.js'),
settingsdb = require('../../settingsdb.js'),
superagent = require('superagent');
var SERVER_URL = 'http://localhost:' + config.get('port');
@@ -302,4 +304,186 @@ describe('Mail API', function () {
});
});
});
describe('mail from validation', function () {
it('get mail from validation succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/mail/mail_from_validation')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ enabled: true });
done();
});
});
it('cannot set without enabled field', function (done) {
superagent.post(SERVER_URL + '/api/v1/mail/mail_from_validation')
.query({ access_token: token })
.send({ })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('can set with enabled field', function (done) {
superagent.post(SERVER_URL + '/api/v1/mail/mail_from_validation')
.query({ access_token: token })
.send({ enabled: false })
.end(function (err, res) {
expect(res.statusCode).to.equal(202);
done();
});
});
});
describe('catch_all', function () {
it('get catch_all succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/mail/catch_all_address')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ address: [ ] });
done();
});
});
it('cannot set without address field', function (done) {
superagent.put(SERVER_URL + '/api/v1/mail/catch_all_address')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('cannot set with bad address field', function (done) {
superagent.put(SERVER_URL + '/api/v1/mail/catch_all_address')
.query({ access_token: token })
.send({ address: [ 'user1', 123 ] })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('set succeeds', function (done) {
superagent.put(SERVER_URL + '/api/v1/mail/catch_all_address')
.query({ access_token: token })
.send({ address: [ 'user1' ] })
.end(function (err, res) {
expect(res.statusCode).to.equal(202);
done();
});
});
it('get succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/mail/catch_all_address')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ address: [ 'user1' ] });
done();
});
});
});
describe('mail relay', function () {
it('get mail relay succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/mail/mail_relay')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ provider: 'cloudron-smtp' });
done();
});
});
it('cannot set without provider field', function (done) {
superagent.post(SERVER_URL + '/api/v1/mail/mail_relay')
.query({ access_token: token })
.send({ })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('cannot set with bad host', function (done) {
superagent.post(SERVER_URL + '/api/v1/mail/mail_relay')
.query({ access_token: token })
.send({ provider: 'external-smtp', host: true })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('set fails because mail server is unreachable', function (done) {
superagent.post(SERVER_URL + '/api/v1/mail/mail_relay')
.query({ access_token: token })
.send({ provider: 'external-smtp', host: 'host', port: 25, username: 'u', password: 'p', tls: true })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('get succeeds', function (done) {
var relay = { provider: 'external-smtp', host: 'host', port: 25, username: 'u', password: 'p', tls: true };
settingsdb.set(mail.MAIL_RELAY_KEY, JSON.stringify(relay), function (error) { // skip the mail server verify()
expect(error).to.not.be.ok();
superagent.get(SERVER_URL + '/api/v1/mail/mail_relay')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql(relay);
done();
});
});
});
});
describe('mail_config', function () {
it('get mail_config succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/mail/mail_config')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ enabled: false });
done();
});
});
it('cannot set without enabled field', function (done) {
superagent.post(SERVER_URL + '/api/v1/mail/mail_config')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('set succeeds', function (done) {
superagent.post(SERVER_URL + '/api/v1/mail/mail_config')
.query({ access_token: token })
.send({ enabled: true })
.end(function (err, res) {
expect(res.statusCode).to.equal(202);
done();
});
});
it('get succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/mail/mail_config')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ enabled: true });
done();
});
});
});
});
-184
View File
@@ -8,7 +8,6 @@
var async = require('async'),
child_process = require('child_process'),
cloudron = require('../../cloudron.js'),
config = require('../../config.js'),
constants = require('../../constants.js'),
database = require('../../database.js'),
@@ -19,7 +18,6 @@ var async = require('async'),
paths = require('../../paths.js'),
server = require('../../server.js'),
settings = require('../../settings.js'),
settingsdb = require('../../settingsdb.js'),
superagent = require('superagent');
var SERVER_URL = 'http://localhost:' + config.get('port');
@@ -222,98 +220,6 @@ describe('Settings API', function () {
});
});
describe('mail_config', function () {
it('get mail_config succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/settings/mail_config')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ enabled: false });
done();
});
});
it('cannot set without enabled field', function (done) {
superagent.post(SERVER_URL + '/api/v1/settings/mail_config')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('set succeeds', function (done) {
superagent.post(SERVER_URL + '/api/v1/settings/mail_config')
.query({ access_token: token })
.send({ enabled: true })
.end(function (err, res) {
expect(res.statusCode).to.equal(202);
done();
});
});
it('get succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/settings/mail_config')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ enabled: true });
done();
});
});
});
describe('catch_all', function () {
it('get catch_all succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/settings/catch_all_address')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ address: [ ] });
done();
});
});
it('cannot set without address field', function (done) {
superagent.put(SERVER_URL + '/api/v1/settings/catch_all_address')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('cannot set with bad address field', function (done) {
superagent.put(SERVER_URL + '/api/v1/settings/catch_all_address')
.query({ access_token: token })
.send({ address: [ 'user1', 123 ] })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('set succeeds', function (done) {
superagent.put(SERVER_URL + '/api/v1/settings/catch_all_address')
.query({ access_token: token })
.send({ address: [ 'user1' ] })
.end(function (err, res) {
expect(res.statusCode).to.equal(202);
done();
});
});
it('get succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/settings/catch_all_address')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ address: [ 'user1' ] });
done();
});
});
});
xdescribe('Certificates API', function () {
var validCert0, validKey0, // example.com
validCert1, validKey1; // *.example.com
@@ -526,94 +432,4 @@ describe('Settings API', function () {
});
});
});
describe('mail relay', function () {
it('get mail relay succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/settings/mail_relay')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ provider: 'cloudron-smtp' });
done();
});
});
it('cannot set without provider field', function (done) {
superagent.post(SERVER_URL + '/api/v1/settings/mail_relay')
.query({ access_token: token })
.send({ })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('cannot set with bad host', function (done) {
superagent.post(SERVER_URL + '/api/v1/settings/mail_relay')
.query({ access_token: token })
.send({ provider: 'external-smtp', host: true })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('set fails because mail server is unreachable', function (done) {
superagent.post(SERVER_URL + '/api/v1/settings/mail_relay')
.query({ access_token: token })
.send({ provider: 'external-smtp', host: 'host', port: 25, username: 'u', password: 'p', tls: true })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('get succeeds', function (done) {
var relay = { provider: 'external-smtp', host: 'host', port: 25, username: 'u', password: 'p', tls: true };
settingsdb.set(settings.MAIL_RELAY_KEY, JSON.stringify(relay), function (error) { // skip the mail server verify()
expect(error).to.not.be.ok();
superagent.get(SERVER_URL + '/api/v1/settings/mail_relay')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql(relay);
done();
});
});
});
});
describe('mail from validation', function () {
it('get mail from validation succeeds', function (done) {
superagent.get(SERVER_URL + '/api/v1/settings/mail_from_validation')
.query({ access_token: token })
.end(function (err, res) {
expect(res.statusCode).to.equal(200);
expect(res.body).to.eql({ enabled: true });
done();
});
});
it('cannot set without enabled field', function (done) {
superagent.post(SERVER_URL + '/api/v1/settings/mail_from_validation')
.query({ access_token: token })
.send({ })
.end(function (err, res) {
expect(res.statusCode).to.equal(400);
done();
});
});
it('can set with enabled field', function (done) {
superagent.post(SERVER_URL + '/api/v1/settings/mail_from_validation')
.query({ access_token: token })
.send({ enabled: false })
.end(function (err, res) {
expect(res.statusCode).to.equal(202);
done();
});
});
});
});
+8 -9
View File
@@ -214,15 +214,14 @@ function initializeExpressSync() {
// email routes
router.get ('/api/v1/mail/status', settingsScope, routes.user.requireAdmin, routes.mail.getStatus);
router.get ('/api/v1/settings/mail_config', settingsScope, routes.user.requireAdmin, routes.settings.getMailConfig);
router.post('/api/v1/settings/mail_config', settingsScope, routes.user.requireAdmin, routes.settings.setMailConfig);
router.get ('/api/v1/settings/mail_relay', settingsScope, routes.user.requireAdmin, routes.settings.getMailRelay);
router.post('/api/v1/settings/mail_relay', settingsScope, routes.user.requireAdmin, routes.settings.setMailRelay);
router.get ('/api/v1/settings/catch_all_address', settingsScope, routes.user.requireAdmin, routes.settings.getCatchAllAddress);
router.put ('/api/v1/settings/catch_all_address', settingsScope, routes.user.requireAdmin, routes.settings.setCatchAllAddress);
router.get ('/api/v1/settings/mail_from_validation', settingsScope, routes.user.requireAdmin, routes.settings.getMailFromValidation);
router.post('/api/v1/settings/mail_from_validation', settingsScope, routes.user.requireAdmin, routes.settings.setMailFromValidation);
router.get ('/api/v1/mail/mail_from_validation', settingsScope, routes.user.requireAdmin, routes.mail.getMailFromValidation);
router.post('/api/v1/mail/mail_from_validation', settingsScope, routes.user.requireAdmin, routes.mail.setMailFromValidation);
router.get ('/api/v1/mail/catch_all_address', settingsScope, routes.user.requireAdmin, routes.mail.getCatchAllAddress);
router.put ('/api/v1/mail/catch_all_address', settingsScope, routes.user.requireAdmin, routes.mail.setCatchAllAddress);
router.get ('/api/v1/mail/mail_relay', settingsScope, routes.user.requireAdmin, routes.mail.getMailRelay);
router.post('/api/v1/mail/mail_relay', settingsScope, routes.user.requireAdmin, routes.mail.setMailRelay);
router.get ('/api/v1/mail/mail_config', settingsScope, routes.user.requireAdmin, routes.mail.getMailConfig);
router.post('/api/v1/mail/mail_config', settingsScope, routes.user.requireAdmin, routes.mail.setMailConfig);
// feedback
router.post('/api/v1/feedback', usersScope, routes.cloudron.feedback);
+1 -134
View File
@@ -32,18 +32,6 @@ exports = module.exports = {
getAppstoreConfig: getAppstoreConfig,
setAppstoreConfig: setAppstoreConfig,
getMailConfig: getMailConfig,
setMailConfig: setMailConfig,
getMailFromValidation: getMailFromValidation,
setMailFromValidation: setMailFromValidation,
getMailRelay: getMailRelay,
setMailRelay: setMailRelay,
setCatchAllAddress: setCatchAllAddress,
getCatchAllAddress: getCatchAllAddress,
getEmailDigest: getEmailDigest,
setEmailDigest: setEmailDigest,
@@ -51,7 +39,6 @@ exports = module.exports = {
// booleans. if you add an entry here, be sure to fix getAll
DYNAMIC_DNS_KEY: 'dynamic_dns',
MAIL_FROM_VALIDATION_KEY: 'mail_from_validation',
EMAIL_DIGEST: 'email_digest',
// json. if you add an entry here, be sure to fix getAll
@@ -60,9 +47,6 @@ exports = module.exports = {
UPDATE_CONFIG_KEY: 'update_config',
APPSTORE_CONFIG_KEY: 'appstore_config',
CAAS_CONFIG_KEY: 'caas_config',
MAIL_CONFIG_KEY: 'mail_config',
MAIL_RELAY_KEY: 'mail_relay',
CATCH_ALL_ADDRESS_KEY: 'catch_all_address',
// strings
AUTOUPDATE_PATTERN_KEY: 'autoupdate_pattern',
@@ -79,12 +63,8 @@ var assert = require('assert'),
constants = require('./constants.js'),
CronJob = require('cron').CronJob,
DatabaseError = require('./databaseerror.js'),
debug = require('debug')('box:settings'),
mail = require('./mail.js'),
MailError = mail.MailError,
moment = require('moment-timezone'),
paths = require('./paths.js'),
platform = require('./platform.js'),
safe = require('safetydance'),
settingsdb = require('./settingsdb.js'),
superagent = require('superagent'),
@@ -106,17 +86,11 @@ var gDefaults = (function () {
result[exports.TLS_CONFIG_KEY] = { provider: 'letsencrypt-prod' };
result[exports.UPDATE_CONFIG_KEY] = { prerelease: false };
result[exports.APPSTORE_CONFIG_KEY] = {};
result[exports.MAIL_CONFIG_KEY] = { enabled: false };
result[exports.MAIL_RELAY_KEY] = { provider: 'cloudron-smtp' };
result[exports.CATCH_ALL_ADDRESS_KEY] = [ ];
result[exports.MAIL_FROM_VALIDATION_KEY] = true;
result[exports.EMAIL_DIGEST] = true;
return result;
})();
var NOOP_CALLBACK = function (error) { if (error) debug(error); };
function SettingsError(reason, errorOrMessage) {
assert.strictEqual(typeof reason, 'string');
assert(errorOrMessage instanceof Error || typeof errorOrMessage === 'string' || typeof errorOrMessage === 'undefined');
@@ -349,56 +323,6 @@ function setBackupConfig(backupConfig, callback) {
});
}
function getMailConfig(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.MAIL_CONFIG_KEY, function (error, value) {
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.MAIL_CONFIG_KEY]);
if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error));
callback(null, JSON.parse(value));
});
}
function setMailConfig(mailConfig, callback) {
assert.strictEqual(typeof mailConfig, 'object');
assert.strictEqual(typeof callback, 'function');
settingsdb.set(exports.MAIL_CONFIG_KEY, JSON.stringify(mailConfig), function (error) {
if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error));
exports.events.emit(exports.MAIL_CONFIG_KEY, mailConfig);
callback(null);
});
}
function getMailFromValidation(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.MAIL_FROM_VALIDATION_KEY, function (error, enabled) {
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.MAIL_FROM_VALIDATION_KEY]);
if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error));
callback(null, !!enabled); // settingsdb holds string values only
});
}
function setMailFromValidation(enabled, callback) {
assert.strictEqual(typeof enabled, 'boolean');
assert.strictEqual(typeof callback, 'function');
settingsdb.set(exports.MAIL_FROM_VALIDATION_KEY, enabled ? 'enabled' : '', function (error) {
if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error));
exports.events.emit(exports.MAIL_FROM_VALIDATION_KEY, enabled);
platform.createMailConfig(NOOP_CALLBACK);
callback(null);
});
}
function getEmailDigest(callback) {
assert.strictEqual(typeof callback, 'function');
@@ -423,61 +347,6 @@ function setEmailDigest(enabled, callback) {
});
}
function getMailRelay(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.MAIL_RELAY_KEY, function (error, value) {
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.MAIL_RELAY_KEY]);
if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error));
callback(null, JSON.parse(value));
});
}
function setMailRelay(relay, callback) {
assert.strictEqual(typeof relay, 'object');
assert.strictEqual(typeof callback, 'function');
mail.verifyRelay(relay, function (error) {
if (error && error.reason === MailError.BAD_FIELD) return callback(new SettingsError(SettingsError.BAD_FIELD, error.message));
if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error));
settingsdb.set(exports.MAIL_RELAY_KEY, JSON.stringify(relay), function (error) {
if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error));
exports.events.emit(exports.MAIL_RELAY_KEY, relay);
callback(null);
});
});
}
function getCatchAllAddress(callback) {
assert.strictEqual(typeof callback, 'function');
settingsdb.get(exports.CATCH_ALL_ADDRESS_KEY, function (error, value) {
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.CATCH_ALL_ADDRESS_KEY]);
if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error));
callback(null, JSON.parse(value));
});
}
function setCatchAllAddress(address, callback) {
assert(Array.isArray(address));
assert.strictEqual(typeof callback, 'function');
settingsdb.set(exports.CATCH_ALL_ADDRESS_KEY, JSON.stringify(address), function (error) {
if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error));
exports.events.emit(exports.CATCH_ALL_ADDRESS_KEY, address);
platform.createMailConfig(NOOP_CALLBACK);
callback(null);
});
}
function getCaasConfig(callback) {
assert.strictEqual(typeof callback, 'function');
@@ -570,11 +439,9 @@ function getAll(callback) {
// convert booleans
result[exports.DYNAMIC_DNS_KEY] = !!result[exports.DYNAMIC_DNS_KEY];
result[exports.MAIL_FROM_VALIDATION_KEY] = !!result[exports.MAIL_FROM_VALIDATION_KEY];
// convert JSON objects
[exports.TLS_CONFIG_KEY, exports.BACKUP_CONFIG_KEY, exports.MAIL_CONFIG_KEY,
exports.UPDATE_CONFIG_KEY, exports.APPSTORE_CONFIG_KEY, exports.MAIL_RELAY_KEY, exports.CATCH_ALL_ADDRESS_KEY].forEach(function (key) {
[exports.TLS_CONFIG_KEY, exports.BACKUP_CONFIG_KEY, exports.UPDATE_CONFIG_KEY, exports.APPSTORE_CONFIG_KEY ].forEach(function (key) {
result[key] = typeof result[key] === 'object' ? result[key] : safe.JSON.parse(result[key]);
});
+3 -3
View File
@@ -9,9 +9,9 @@ var async = require('async'),
config = require('../config.js'),
database = require('../database.js'),
digest = require('../digest.js'),
domaindb = require('../domaindb.js'),
eventlog = require('../eventlog.js'),
expect = require('expect.js'),
mail = require('../mail.js'),
mailer = require('../mailer.js'),
paths = require('../paths.js'),
safe = require('safetydance'),
@@ -67,7 +67,7 @@ describe('digest', function () {
settings.initialize,
user.createOwner.bind(null, USER_0.username, USER_0.password, USER_0.email, USER_0.displayName, AUDIT_SOURCE),
eventlog.add.bind(null, eventlog.ACTION_UPDATE, AUDIT_SOURCE, { boxUpdateInfo: { sourceTarballUrl: 'xx', version: '1.2.3', changelog: [ 'good stuff' ] } }),
settingsdb.set.bind(null, settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true })),
settingsdb.set.bind(null, mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true })),
mailer._clearMailQueue
], done);
});
@@ -123,7 +123,7 @@ describe('digest', function () {
it('sends mail for pending update to owner account email', function (done) {
updatechecker._setUpdateInfo({ box: null, apps: { 'appid': { manifest: { version: '1.2.5', changelog: 'noop\nreally' } } } });
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
if (error) return done(error);
digest.maybeSend(function (error) {
+16 -16
View File
@@ -1,6 +1,6 @@
/* jslint node:true */
/* global it:false */
/* global xdescribe:false */
/* global describe:false */
/* global before:false */
/* global after:false */
@@ -16,8 +16,8 @@ var appdb = require('../appdb.js'),
groups = require('../groups.js'),
http = require('http'),
ldapServer = require('../ldap.js'),
mail = require('../mail.js'),
mailboxdb = require('../mailboxdb.js'),
settings = require('../settings.js'),
settingsdb = require('../settingsdb.js'),
ldap = require('ldapjs'),
user = require('../user.js');
@@ -246,7 +246,7 @@ describe('Ldap', function () {
it('succeeds without accessRestriction when email is enabled', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
@@ -256,7 +256,7 @@ describe('Ldap', function () {
client.unbind();
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
@@ -378,7 +378,7 @@ describe('Ldap', function () {
it ('succeeds with basic filter and email enabled', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
@@ -409,7 +409,7 @@ describe('Ldap', function () {
client.unbind();
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
@@ -739,7 +739,7 @@ describe('Ldap', function () {
});
it('cannot get mailbox with just name', function (done) {
ldapSearch('cn=' + USER_0.username + ',ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error, entries) {
ldapSearch('cn=' + USER_0.username + ',ou=mailboxes,dc=cloudron', 'objectclass=mailbox', function (error) {
expect(error).to.be.a(ldap.NoSuchObjectError);
done();
});
@@ -845,7 +845,7 @@ describe('Ldap', function () {
it('email enabled - allows with valid email', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
@@ -855,14 +855,14 @@ describe('Ldap', function () {
client.unbind();
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
it('email enabled - does not allow with invalid password', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
@@ -872,7 +872,7 @@ describe('Ldap', function () {
client.unbind();
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
@@ -881,7 +881,7 @@ describe('Ldap', function () {
describe('app sendmail bind', function () {
// these tests should work even when email is disabled
before(function (done) {
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
it('does not allow with invalid app', function (done) {
@@ -933,7 +933,7 @@ describe('Ldap', function () {
it('email enabled - allows with valid email', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
@@ -943,14 +943,14 @@ describe('Ldap', function () {
client.unbind();
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
it('email enabled - does not allow with invalid password', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
var client = ldap.createClient({ url: 'ldap://127.0.0.1:' + config.get('ldapPort') });
@@ -960,7 +960,7 @@ describe('Ldap', function () {
client.unbind();
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
+108
View File
@@ -0,0 +1,108 @@
/* global it:false */
/* global describe:false */
/* global before:false */
/* global after:false */
'use strict';
var async = require('async'),
config = require('../config.js'),
database = require('../database.js'),
expect = require('expect.js'),
mail = require('../mail.js'),
settingsdb = require('../settingsdb.js');
function setup(done) {
config._reset();
config.set('fqdn', 'example.com');
config.set('provider', 'caas');
async.series([
database.initialize,
], done);
}
function cleanup(done) {
async.series([
database._clear,
database.uninitialize
], done);
}
describe('Settings', function () {
describe('values', function () {
before(setup);
after(cleanup);
it('can set mail from validation', function (done) {
mail.setMailFromValidation(true, function (error) {
expect(error).to.be(null);
done();
});
});
it('can get mail from validation', function (done) {
mail.getMailFromValidation(function (error, enabled) {
expect(error).to.be(null);
expect(enabled).to.be(true);
done();
});
});
it('can get catch all address', function (done) {
mail.getCatchAllAddress(function (error, address) {
expect(error).to.be(null);
expect(address).to.eql([ ]);
done();
});
});
it('can set catch all address', function (done) {
mail.setCatchAllAddress([ 'user1', 'user2' ], function (error) {
expect(error).to.be(null);
mail.getCatchAllAddress(function (error, address) {
expect(error).to.be(null);
expect(address).to.eql([ 'user1', 'user2' ]);
done();
});
});
});
it('can get mail relay', function (done) {
mail.getMailRelay(function (error, address) {
expect(error).to.be(null);
expect(address).to.eql({ provider: 'cloudron-smtp' });
done();
});
});
it('can set mail relay', function (done) {
var relay = { provider: 'external-smtp', host: 'mx.foo.com', port: 25 };
settingsdb.set(mail.MAIL_RELAY_KEY, JSON.stringify(relay), function (error) { // skip the mail server verify()
expect(error).to.be(null);
mail.getMailRelay(function (error, address) {
expect(error).to.be(null);
expect(address).to.eql(relay);
done();
});
});
});
it('can set mail config', function (done) {
mail.setMailConfig({ enabled: true }, function (error) {
expect(error).to.be(null);
done();
});
});
it('can get mail config', function (done) {
mail.getMailConfig(function (error, mailConfig) {
expect(error).to.be(null);
expect(mailConfig.enabled).to.be(true);
done();
});
});
});
});
+1 -72
View File
@@ -105,7 +105,7 @@ describe('Settings', function () {
});
it('can set backup config', function (done) {
var scope2 = nock(config.apiServerOrigin())
nock(config.apiServerOrigin())
.post('/api/v1/boxes/' + config.fqdn() + '/awscredentials?token=TOKEN')
.reply(201, { credentials: { AccessKeyId: 'accessKeyId', SecretAccessKey: 'secretAccessKey', SessionToken: 'sessionToken' } });
@@ -124,36 +124,6 @@ describe('Settings', function () {
});
});
it('can set mail config', function (done) {
settings.setMailConfig({ enabled: true }, function (error) {
expect(error).to.be(null);
done();
});
});
it('can get mail config', function (done) {
settings.getMailConfig(function (error, mailConfig) {
expect(error).to.be(null);
expect(mailConfig.enabled).to.be(true);
done();
});
});
it('can set mail from validation', function (done) {
settings.setMailFromValidation(true, function (error) {
expect(error).to.be(null);
done();
});
});
it('can get mail from validation', function (done) {
settings.getMailFromValidation(function (error, enabled) {
expect(error).to.be(null);
expect(enabled).to.be(true);
done();
});
});
it('can enable mail digest', function (done) {
settings.setEmailDigest(true, function (error) {
expect(error).to.be(null);
@@ -169,47 +139,6 @@ describe('Settings', function () {
});
});
it('can get mail relay', function (done) {
settings.getMailRelay(function (error, address) {
expect(error).to.be(null);
expect(address).to.eql({ provider: 'cloudron-smtp' });
done();
});
});
it('can set mail relay', function (done) {
var relay = { provider: 'external-smtp', host: 'mx.foo.com', port: 25 };
+ settingsdb.set(settings.MAIL_RELAY_KEY, JSON.stringify(relay), function (error) { // skip the mail server verify()
expect(error).to.be(null);
settings.getMailRelay(function (error, address) {
expect(error).to.be(null);
expect(address).to.eql(relay);
done();
});
});
});
it('can get catch all address', function (done) {
settings.getCatchAllAddress(function (error, address) {
expect(error).to.be(null);
expect(address).to.eql([ ]);
done();
});
});
it('can set catch all address', function (done) {
settings.setCatchAllAddress([ "user1", "user2" ], function (error) {
expect(error).to.be(null);
settings.getCatchAllAddress(function (error, address) {
expect(error).to.be(null);
expect(address).to.eql([ "user1", "user2" ]);
done();
});
});
});
it('can get all values', function (done) {
settings.getAll(function (error, allSettings) {
expect(error).to.be(null);
+10 -10
View File
@@ -14,11 +14,11 @@ var async = require('async'),
fs = require('fs'),
groupdb = require('../groupdb.js'),
groups = require('../groups.js'),
mail = require('../mail.js'),
mailboxdb = require('../mailboxdb.js'),
mailer = require('../mailer.js'),
user = require('../user.js'),
userdb = require('../userdb.js'),
settings = require('../settings.js'),
settingsdb = require('../settingsdb.js'),
UserError = user.UserError;
@@ -269,7 +269,7 @@ describe('User', function () {
it('succeeds and attempts to send invite to alternateEmail', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
user.create(USERNAME_1, PASSWORD_1, EMAIL_1, DISPLAY_NAME_1, AUDIT_SOURCE, { sendInvite: true }, function (error, result) {
@@ -283,7 +283,7 @@ describe('User', function () {
checkMails(2, { sentTo: EMAIL_1.toLowerCase() }, function (error) {
expect(error).not.to.be.ok();
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
@@ -589,28 +589,28 @@ describe('User', function () {
it('succeeds with cloudron mail enabled', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
user.verifyWithEmail(USERNAME + '@' + config.fqdn(), PASSWORD, function (error, result) {
expect(error).to.not.be.ok();
expect(result).to.be.ok();
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
it('fails with cloudron mail enabled and invite email', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
user.verifyWithEmail(EMAIL, PASSWORD, function (error) {
expect(error).to.be.a(UserError);
expect(error.reason).to.equal(UserError.NOT_FOUND);
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
@@ -645,7 +645,7 @@ describe('User', function () {
it('succeeds with email enabled', function (done) {
// user settingsdb instead of settings, to not trigger further events
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: true }), function (error) {
expect(error).not.to.be.ok();
user.get(userObject.id, function (error, result) {
@@ -657,7 +657,7 @@ describe('User', function () {
expect(result.username).to.equal(USERNAME.toLowerCase());
expect(result.displayName).to.equal(DISPLAY_NAME);
settingsdb.set(settings.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
settingsdb.set(mail.MAIL_CONFIG_KEY, JSON.stringify({ enabled: false }), done);
});
});
});
@@ -1026,7 +1026,7 @@ describe('User', function () {
});
it('did delete mailbox and aliases', function (done) {
mailboxdb.getMailbox(userObject.username.toLowerCase(), DOMAIN_0.domain, function (error, mailbox) {
mailboxdb.getMailbox(userObject.username.toLowerCase(), DOMAIN_0.domain, function (error) {
expect(error.reason).to.be(DatabaseError.NOT_FOUND);
mailboxdb.getAliasesForName(USERNAME.toLowerCase(), DOMAIN_0.domain, function (error, results) {
+7 -7
View File
@@ -36,10 +36,10 @@ var assert = require('assert'),
groups = require('./groups.js'),
GroupError = groups.GroupError,
hat = require('hat'),
mail = require('./mail.js'),
mailer = require('./mailer.js'),
mailboxdb = require('./mailboxdb.js'),
safe = require('safetydance'),
settings = require('./settings.js'),
tokendb = require('./tokendb.js'),
userdb = require('./userdb.js'),
util = require('util'),
@@ -178,7 +178,7 @@ function createUser(username, password, email, displayName, auditSource, options
if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(new UserError(UserError.ALREADY_EXISTS, error.message));
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
settings.getMailConfig(function (error, mailConfig) {
mail.getMailConfig(function (error, mailConfig) {
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
if (mailConfig.enabled) {
@@ -259,7 +259,7 @@ function verifyWithEmail(email, password, callback) {
email = email.toLowerCase();
settings.getMailConfig(function (error, mailConfig) {
mail.getMailConfig(function (error, mailConfig) {
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
if (mailConfig.enabled) return verifyWithUsername(email.split('@')[0], password, callback);
@@ -302,7 +302,7 @@ function listUsers(callback) {
userdb.getAllWithGroupIds(function (error, results) {
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
settings.getMailConfig(function (error, mailConfig) {
mail.getMailConfig(function (error, mailConfig) {
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
results.forEach(function (result) {
@@ -345,7 +345,7 @@ function getUser(userId, callback) {
result.groupIds = groupIds;
result.admin = groupIds.indexOf(constants.ADMIN_GROUP_ID) !== -1;
settings.getMailConfig(function (error, mailConfig) {
mail.getMailConfig(function (error, mailConfig) {
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
if (mailConfig.enabled) {
@@ -451,7 +451,7 @@ function getAllAdmins(callback) {
userdb.getAllAdmins(function (error, admins) {
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
settings.getMailConfig(function (error, mailConfig) {
mail.getMailConfig(function (error, mailConfig) {
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
admins.forEach(function (admin) {
@@ -575,7 +575,7 @@ function getOwner(callback) {
if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new UserError(UserError.NOT_FOUND));
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
settings.getMailConfig(function (error, mailConfig) {
mail.getMailConfig(function (error, mailConfig) {
if (error) return callback(new UserError(UserError.INTERNAL_ERROR, error));
if (mailConfig.enabled) {