previous mailer code has no callback and thus no way to pass back errors. now with asyncification it passes back the error
330 lines
14 KiB
JavaScript
330 lines
14 KiB
JavaScript
'use strict';
|
|
|
|
exports = module.exports = {
|
|
getDomain,
|
|
|
|
getStatus,
|
|
|
|
setMailFromValidation,
|
|
setCatchAllAddress,
|
|
setMailRelay,
|
|
setMailEnabled,
|
|
setBanner,
|
|
|
|
sendTestMail,
|
|
|
|
listMailboxes,
|
|
getMailbox,
|
|
addMailbox,
|
|
updateMailbox,
|
|
delMailbox,
|
|
|
|
getAliases,
|
|
setAliases,
|
|
|
|
getLists,
|
|
getList,
|
|
addList,
|
|
updateList,
|
|
delList,
|
|
|
|
getMailboxCount
|
|
};
|
|
|
|
const assert = require('assert'),
|
|
auditSource = require('../auditsource.js'),
|
|
BoxError = require('../boxerror.js'),
|
|
mail = require('../mail.js'),
|
|
HttpError = require('connect-lastmile').HttpError,
|
|
HttpSuccess = require('connect-lastmile').HttpSuccess,
|
|
safe = require('safetydance');
|
|
|
|
async function getDomain(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
|
|
const [error, result] = await safe(mail.getDomain(req.params.domain));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
if (!result) return next(new HttpError(404, 'Mail domain not found'));
|
|
|
|
next(new HttpSuccess(200, mail.removePrivateFields(result)));
|
|
}
|
|
|
|
function getStatus(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
|
|
// can take a while to query all the DNS entries
|
|
req.clearTimeout();
|
|
|
|
mail.getStatus(req.params.domain, function (error, records) {
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(200, records));
|
|
});
|
|
}
|
|
|
|
async function setMailFromValidation(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.body, 'object');
|
|
|
|
if (typeof req.body.enabled !== 'boolean') return next(new HttpError(400, 'enabled is required'));
|
|
|
|
const [error] = await safe(mail.setMailFromValidation(req.params.domain, req.body.enabled));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(202));
|
|
}
|
|
|
|
async function setCatchAllAddress(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.body, 'object');
|
|
|
|
if (!req.body.addresses) return next(new HttpError(400, 'addresses is required'));
|
|
if (!Array.isArray(req.body.addresses)) return next(new HttpError(400, 'addresses must be an array of strings'));
|
|
|
|
for (let i = 0; i < req.body.addresses.length; i++) {
|
|
if (typeof req.body.addresses[i] !== 'string') return next(new HttpError(400, 'addresses must be an array of strings'));
|
|
}
|
|
|
|
const [error] = await safe(mail.setCatchAllAddress(req.params.domain, req.body.addresses));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(202));
|
|
}
|
|
|
|
async function setMailRelay(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
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'));
|
|
if ('acceptSelfSignedCerts' in req.body && typeof req.body.acceptSelfSignedCerts !== 'boolean') return next(new HttpError(400, 'acceptSelfSignedCerts must be a boolean'));
|
|
|
|
const [error] = await safe(mail.setMailRelay(req.params.domain, req.body, { skipVerify: false }));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(202));
|
|
}
|
|
|
|
async function setMailEnabled(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.body, 'object');
|
|
|
|
if (typeof req.body.enabled !== 'boolean') return next(new HttpError(400, 'enabled is required'));
|
|
|
|
const [error] = await safe(mail.setMailEnabled(req.params.domain, !!req.body.enabled, auditSource.fromRequest(req)));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(202));
|
|
}
|
|
|
|
async function sendTestMail(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.body, 'object');
|
|
|
|
if (!req.body.to || typeof req.body.to !== 'string') return next(new HttpError(400, 'to must be a non-empty string'));
|
|
|
|
const [error] = await safe(mail.sendTestMail(req.params.domain, req.body.to));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(202));
|
|
}
|
|
|
|
async function listMailboxes(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
|
|
const page = typeof req.query.page !== 'undefined' ? parseInt(req.query.page) : 1;
|
|
if (!page || page < 0) return next(new HttpError(400, 'page query param has to be a positive number'));
|
|
|
|
const perPage = typeof req.query.per_page !== 'undefined'? parseInt(req.query.per_page) : 25;
|
|
if (!perPage || perPage < 0) return next(new HttpError(400, 'per_page query param has to be a positive number'));
|
|
|
|
if (req.query.search && typeof req.query.search !== 'string') return next(new HttpError(400, 'search must be a string'));
|
|
|
|
const [error, mailboxes] = await safe(mail.listMailboxes(req.params.domain, req.query.search || null, page, perPage));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(200, { mailboxes }));
|
|
}
|
|
|
|
async function getMailboxCount(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
|
|
const [error, count] = await safe(mail.getMailboxCount(req.params.domain));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(200, { count }));
|
|
}
|
|
|
|
async function getMailbox(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.params.name, 'string');
|
|
|
|
const [error, result] = await safe(mail.getMailbox(req.params.name, req.params.domain));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
if (!result) return next(new HttpError(404, 'Mailbox not found'));
|
|
|
|
next(new HttpSuccess(200, { mailbox: result }));
|
|
}
|
|
|
|
async function addMailbox(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
|
|
if (typeof req.body.name !== 'string') return next(new HttpError(400, 'name must be a string'));
|
|
if (typeof req.body.ownerId !== 'string') return next(new HttpError(400, 'ownerId must be a string'));
|
|
if (typeof req.body.ownerType !== 'string') return next(new HttpError(400, 'ownerType must be a string'));
|
|
if (typeof req.body.active !== 'boolean') return next(new HttpError(400, 'active must be a boolean'));
|
|
|
|
const [error] = await safe(mail.addMailbox(req.body.name, req.params.domain, req.body, auditSource.fromRequest(req)));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(201, {}));
|
|
}
|
|
|
|
async function updateMailbox(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.params.name, 'string');
|
|
|
|
if (typeof req.body.ownerId !== 'string') return next(new HttpError(400, 'ownerId must be a string'));
|
|
if (typeof req.body.ownerType !== 'string') return next(new HttpError(400, 'ownerType must be a string'));
|
|
if (typeof req.body.active !== 'boolean') return next(new HttpError(400, 'active must be a boolean'));
|
|
|
|
const [error] = await safe(mail.updateMailbox(req.params.name, req.params.domain, req.body, auditSource.fromRequest(req)));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(204));
|
|
}
|
|
|
|
async function delMailbox(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.params.name, 'string');
|
|
|
|
if (typeof req.body.deleteMails !== 'boolean') return next(new HttpError(400, 'deleteMails must be a boolean'));
|
|
|
|
const [error] = await safe(mail.delMailbox(req.params.name, req.params.domain, req.body, auditSource.fromRequest(req)));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(201, {}));
|
|
}
|
|
|
|
async function getAliases(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.params.name, 'string');
|
|
|
|
const [error, aliases] = await safe(mail.getAliases(req.params.name, req.params.domain));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(200, { aliases }));
|
|
}
|
|
|
|
async function setAliases(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.params.name, 'string');
|
|
assert.strictEqual(typeof req.body, 'object');
|
|
|
|
if (!Array.isArray(req.body.aliases)) return next(new HttpError(400, 'aliases must be an array'));
|
|
|
|
for (let alias of req.body.aliases) {
|
|
if (!alias || typeof alias !== 'object') return next(new HttpError(400, 'each alias must have a name and domain'));
|
|
if (typeof alias.name !== 'string') return next(new HttpError(400, 'name must be a string'));
|
|
if (typeof alias.domain !== 'string') return next(new HttpError(400, 'domain must be a string'));
|
|
}
|
|
|
|
const [error] = await safe(mail.setAliases(req.params.name, req.params.domain, req.body.aliases));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(202));
|
|
}
|
|
|
|
async function setBanner(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.body, 'object');
|
|
|
|
if (typeof req.body.text !== 'string') return res.status(400).send({ message: 'text must be a string' });
|
|
if ('html' in req.body && typeof req.body.html !== 'string') return res.status(400).send({ message: 'html must be a string' });
|
|
|
|
const [error] = await safe(mail.setBanner(req.params.domain, { text: req.body.text, html: req.body.html || null }));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(202));
|
|
}
|
|
|
|
async function getLists(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
|
|
const page = typeof req.query.page !== 'undefined' ? parseInt(req.query.page) : 1;
|
|
if (!page || page < 0) return next(new HttpError(400, 'page query param has to be a positive number'));
|
|
|
|
const perPage = typeof req.query.per_page !== 'undefined'? parseInt(req.query.per_page) : 25;
|
|
if (!perPage || perPage < 0) return next(new HttpError(400, 'per_page query param has to be a positive number'));
|
|
|
|
if (req.query.search && typeof req.query.search !== 'string') return next(new HttpError(400, 'search must be a string'));
|
|
|
|
const [error, lists] = await safe(mail.getLists(req.params.domain, req.query.search || null, page, perPage));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(200, { lists }));
|
|
}
|
|
|
|
async function getList(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.params.name, 'string');
|
|
|
|
const [error, result] = await safe(mail.getList(req.params.name, req.params.domain));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
if (!result) return next(new HttpError(404, 'List not found'));
|
|
|
|
next(new HttpSuccess(200, { list: result }));
|
|
}
|
|
|
|
async function addList(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.body, 'object');
|
|
|
|
if (typeof req.body.name !== 'string') return next(new HttpError(400, 'name must be a string'));
|
|
if (!Array.isArray(req.body.members)) return next(new HttpError(400, 'members must be a string'));
|
|
if (req.body.members.length === 0) return next(new HttpError(400, 'list must have atleast one member'));
|
|
|
|
for (let i = 0; i < req.body.members.length; i++) {
|
|
if (typeof req.body.members[i] !== 'string') return next(new HttpError(400, 'member must be a string'));
|
|
}
|
|
if (typeof req.body.membersOnly !== 'boolean') return next(new HttpError(400, 'membersOnly must be a boolean'));
|
|
if (typeof req.body.active !== 'boolean') return next(new HttpError(400, 'active must be a boolean'));
|
|
|
|
const [error] = await safe(mail.addList(req.body.name, req.params.domain, req.body, auditSource.fromRequest(req)));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(201, {}));
|
|
}
|
|
|
|
async function updateList(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.params.name, 'string');
|
|
|
|
if (!Array.isArray(req.body.members)) return next(new HttpError(400, 'members must be a string'));
|
|
if (req.body.members.length === 0) return next(new HttpError(400, 'list must have atleast one member'));
|
|
|
|
for (var i = 0; i < req.body.members.length; i++) {
|
|
if (typeof req.body.members[i] !== 'string') return next(new HttpError(400, 'member must be a string'));
|
|
}
|
|
if (typeof req.body.membersOnly !== 'boolean') return next(new HttpError(400, 'membersOnly must be a boolean'));
|
|
if (typeof req.body.active !== 'boolean') return next(new HttpError(400, 'active must be a boolean'));
|
|
|
|
const [error] = await safe(mail.updateList(req.params.name, req.params.domain, req.body, auditSource.fromRequest(req)));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(204));
|
|
}
|
|
|
|
async function delList(req, res, next) {
|
|
assert.strictEqual(typeof req.params.domain, 'string');
|
|
assert.strictEqual(typeof req.params.name, 'string');
|
|
|
|
const [error] = await safe(mail.delList(req.params.name, req.params.domain, auditSource.fromRequest(req)));
|
|
if (error) return next(BoxError.toHttpError(error));
|
|
|
|
next(new HttpSuccess(204));
|
|
}
|