Files
cloudron-box/src/mailboxdb.js

358 lines
14 KiB
JavaScript
Raw Normal View History

2016-05-26 22:34:04 -07:00
'use strict';
exports = module.exports = {
addMailbox: addMailbox,
2019-08-23 15:09:06 -07:00
addList: addList,
2018-12-06 11:41:16 -08:00
updateMailboxOwner: updateMailboxOwner,
updateList: updateList,
2016-05-26 22:34:04 -07:00
del: del,
2016-09-25 23:21:55 -07:00
listAliases: listAliases,
listMailboxes: listMailboxes,
2019-08-23 15:09:06 -07:00
getLists: getLists,
2016-09-25 23:21:55 -07:00
listAllMailboxes: listAllMailboxes,
2019-11-06 16:45:44 -08:00
get: get,
2016-09-25 18:59:11 -07:00
getMailbox: getMailbox,
2019-08-23 15:09:06 -07:00
getList: getList,
2016-09-25 18:59:11 -07:00
getAlias: getAlias,
2016-09-25 23:21:55 -07:00
2016-09-26 14:02:23 -07:00
getAliasesForName: getAliasesForName,
setAliasesForName: setAliasesForName,
2016-09-25 23:21:55 -07:00
2016-09-23 17:35:48 -07:00
getByOwnerId: getByOwnerId,
delByOwnerId: delByOwnerId,
2018-02-11 01:18:29 -08:00
delByDomain: delByDomain,
2016-05-26 22:34:04 -07:00
2016-12-15 16:13:16 +01:00
updateName: updateName,
_clear: clear,
2018-04-07 19:12:07 -07:00
TYPE_MAILBOX: 'mailbox',
TYPE_LIST: 'list',
rework how app mailboxes are allocated Our current setup had a mailbox allocated for an app during app install (into the mailboxes table). This has many issues: * When set to a custom mailbox location, there was no way to access this mailbox even via IMAP. Even when using app credentials, we cannot use IMAP since the ldap logic was testing on the addon type (most of our apps only use sendmail addon and thus cannot recvmail). * The mailboxes table was being used to add hidden 'app' type entries. This made it very hard for the user to understand why a mailbox conflicts. For example, if you set an app to use custom mailbox 'blog', this is hidden from all views. The solution is to let an app send email as whatever mailbox name is allocated to it (which we now track in the apps table. the default is in the db already so that REST response contains it). When not using Cloudron email, it will just send mail as that mailbox and the auth checks the "app password" in the addons table. Any replies to that mailbox will end up in the domain's mail server (not our problem). When using cloudron email, the app can send mail like above. Any responses will not end anywhere and bounce since there is no 'mailbox'. This is the expected behavior. If user wants to access this mailbox name, he can create a concrete mailbox and set himself as owner OR set this as an alias. For apps using the recvmail addon, the workflow is to actually create a mailbox at some point. Currently, we have no UI for this 'flow'. It's fine because we have only meemo using it. Intuitive much!
2018-12-06 21:08:19 -08:00
TYPE_ALIAS: 'alias'
2016-05-26 22:34:04 -07:00
};
var assert = require('assert'),
2019-10-24 13:34:14 -07:00
BoxError = require('./boxerror.js'),
2016-05-26 22:34:04 -07:00
database = require('./database.js'),
safe = require('safetydance'),
util = require('util');
2016-05-26 22:34:04 -07:00
2020-04-17 16:55:23 -07:00
var MAILBOX_FIELDS = [ 'name', 'type', 'ownerId', 'aliasTarget', 'creationTime', 'membersJson', 'membersOnly', 'domain' ].join(',');
function postProcess(data) {
data.members = safe.JSON.parse(data.membersJson) || [ ];
delete data.membersJson;
2020-04-17 16:55:23 -07:00
data.membersOnly = !!data.membersOnly;
return data;
}
2016-05-26 22:34:04 -07:00
rework how app mailboxes are allocated Our current setup had a mailbox allocated for an app during app install (into the mailboxes table). This has many issues: * When set to a custom mailbox location, there was no way to access this mailbox even via IMAP. Even when using app credentials, we cannot use IMAP since the ldap logic was testing on the addon type (most of our apps only use sendmail addon and thus cannot recvmail). * The mailboxes table was being used to add hidden 'app' type entries. This made it very hard for the user to understand why a mailbox conflicts. For example, if you set an app to use custom mailbox 'blog', this is hidden from all views. The solution is to let an app send email as whatever mailbox name is allocated to it (which we now track in the apps table. the default is in the db already so that REST response contains it). When not using Cloudron email, it will just send mail as that mailbox and the auth checks the "app password" in the addons table. Any replies to that mailbox will end up in the domain's mail server (not our problem). When using cloudron email, the app can send mail like above. Any responses will not end anywhere and bounce since there is no 'mailbox'. This is the expected behavior. If user wants to access this mailbox name, he can create a concrete mailbox and set himself as owner OR set this as an alias. For apps using the recvmail addon, the workflow is to actually create a mailbox at some point. Currently, we have no UI for this 'flow'. It's fine because we have only meemo using it. Intuitive much!
2018-12-06 21:08:19 -08:00
function addMailbox(name, domain, ownerId, callback) {
assert.strictEqual(typeof name, 'string');
assert.strictEqual(typeof domain, 'string');
assert.strictEqual(typeof ownerId, 'string');
assert.strictEqual(typeof callback, 'function');
rework how app mailboxes are allocated Our current setup had a mailbox allocated for an app during app install (into the mailboxes table). This has many issues: * When set to a custom mailbox location, there was no way to access this mailbox even via IMAP. Even when using app credentials, we cannot use IMAP since the ldap logic was testing on the addon type (most of our apps only use sendmail addon and thus cannot recvmail). * The mailboxes table was being used to add hidden 'app' type entries. This made it very hard for the user to understand why a mailbox conflicts. For example, if you set an app to use custom mailbox 'blog', this is hidden from all views. The solution is to let an app send email as whatever mailbox name is allocated to it (which we now track in the apps table. the default is in the db already so that REST response contains it). When not using Cloudron email, it will just send mail as that mailbox and the auth checks the "app password" in the addons table. Any replies to that mailbox will end up in the domain's mail server (not our problem). When using cloudron email, the app can send mail like above. Any responses will not end anywhere and bounce since there is no 'mailbox'. This is the expected behavior. If user wants to access this mailbox name, he can create a concrete mailbox and set himself as owner OR set this as an alias. For apps using the recvmail addon, the workflow is to actually create a mailbox at some point. Currently, we have no UI for this 'flow'. It's fine because we have only meemo using it. Intuitive much!
2018-12-06 21:08:19 -08:00
database.query('INSERT INTO mailboxes (name, type, domain, ownerId) VALUES (?, ?, ?, ?)', [ name, exports.TYPE_MAILBOX, domain, ownerId ], function (error) {
2019-10-24 13:34:14 -07:00
if (error && error.code === 'ER_DUP_ENTRY') return callback(new BoxError(BoxError.ALREADY_EXISTS, 'mailbox already exists'));
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
callback(null);
});
}
rework how app mailboxes are allocated Our current setup had a mailbox allocated for an app during app install (into the mailboxes table). This has many issues: * When set to a custom mailbox location, there was no way to access this mailbox even via IMAP. Even when using app credentials, we cannot use IMAP since the ldap logic was testing on the addon type (most of our apps only use sendmail addon and thus cannot recvmail). * The mailboxes table was being used to add hidden 'app' type entries. This made it very hard for the user to understand why a mailbox conflicts. For example, if you set an app to use custom mailbox 'blog', this is hidden from all views. The solution is to let an app send email as whatever mailbox name is allocated to it (which we now track in the apps table. the default is in the db already so that REST response contains it). When not using Cloudron email, it will just send mail as that mailbox and the auth checks the "app password" in the addons table. Any replies to that mailbox will end up in the domain's mail server (not our problem). When using cloudron email, the app can send mail like above. Any responses will not end anywhere and bounce since there is no 'mailbox'. This is the expected behavior. If user wants to access this mailbox name, he can create a concrete mailbox and set himself as owner OR set this as an alias. For apps using the recvmail addon, the workflow is to actually create a mailbox at some point. Currently, we have no UI for this 'flow'. It's fine because we have only meemo using it. Intuitive much!
2018-12-06 21:08:19 -08:00
function updateMailboxOwner(name, domain, ownerId, callback) {
assert.strictEqual(typeof name, 'string');
assert.strictEqual(typeof domain, 'string');
assert.strictEqual(typeof ownerId, 'string');
assert.strictEqual(typeof callback, 'function');
rework how app mailboxes are allocated Our current setup had a mailbox allocated for an app during app install (into the mailboxes table). This has many issues: * When set to a custom mailbox location, there was no way to access this mailbox even via IMAP. Even when using app credentials, we cannot use IMAP since the ldap logic was testing on the addon type (most of our apps only use sendmail addon and thus cannot recvmail). * The mailboxes table was being used to add hidden 'app' type entries. This made it very hard for the user to understand why a mailbox conflicts. For example, if you set an app to use custom mailbox 'blog', this is hidden from all views. The solution is to let an app send email as whatever mailbox name is allocated to it (which we now track in the apps table. the default is in the db already so that REST response contains it). When not using Cloudron email, it will just send mail as that mailbox and the auth checks the "app password" in the addons table. Any replies to that mailbox will end up in the domain's mail server (not our problem). When using cloudron email, the app can send mail like above. Any responses will not end anywhere and bounce since there is no 'mailbox'. This is the expected behavior. If user wants to access this mailbox name, he can create a concrete mailbox and set himself as owner OR set this as an alias. For apps using the recvmail addon, the workflow is to actually create a mailbox at some point. Currently, we have no UI for this 'flow'. It's fine because we have only meemo using it. Intuitive much!
2018-12-06 21:08:19 -08:00
database.query('UPDATE mailboxes SET ownerId = ? WHERE name = ? AND domain = ?', [ ownerId, name, domain ], function (error, result) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-10-24 20:48:38 -07:00
if (result.affectedRows === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
callback(null);
});
}
2020-04-17 16:55:23 -07:00
function addList(name, domain, members, membersOnly, callback) {
2016-05-26 22:34:04 -07:00
assert.strictEqual(typeof name, 'string');
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof domain, 'string');
assert(Array.isArray(members));
2020-04-17 16:55:23 -07:00
assert.strictEqual(typeof membersOnly, 'boolean');
2016-05-26 22:34:04 -07:00
assert.strictEqual(typeof callback, 'function');
2020-04-17 16:55:23 -07:00
database.query('INSERT INTO mailboxes (name, type, domain, ownerId, membersJson, membersOnly) VALUES (?, ?, ?, ?, ?, ?)',
[ name, exports.TYPE_LIST, domain, 'admin', JSON.stringify(members), membersOnly ], function (error) {
2019-10-24 13:34:14 -07:00
if (error && error.code === 'ER_DUP_ENTRY') return callback(new BoxError(BoxError.ALREADY_EXISTS, 'mailbox already exists'));
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
callback(null);
});
}
2020-04-17 16:55:23 -07:00
function updateList(name, domain, members, membersOnly, callback) {
assert.strictEqual(typeof name, 'string');
assert.strictEqual(typeof domain, 'string');
assert(Array.isArray(members));
2020-04-17 16:55:23 -07:00
assert.strictEqual(typeof membersOnly, 'boolean');
assert.strictEqual(typeof callback, 'function');
2020-04-17 16:55:23 -07:00
database.query('UPDATE mailboxes SET membersJson = ?, membersOnly = ? WHERE name = ? AND domain = ?',
[ JSON.stringify(members), membersOnly, name, domain ], function (error, result) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-10-24 20:48:38 -07:00
if (result.affectedRows === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
callback(null);
});
}
2016-05-26 22:34:04 -07:00
function clear(callback) {
assert.strictEqual(typeof callback, 'function');
database.query('TRUNCATE TABLE mailboxes', [], function (error) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2016-05-26 22:34:04 -07:00
callback(null);
});
}
2017-11-09 23:45:29 +01:00
function del(name, domain, callback) {
assert.strictEqual(typeof name, 'string');
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof domain, 'string');
2016-05-26 22:34:04 -07:00
assert.strictEqual(typeof callback, 'function');
// deletes aliases as well
2017-11-09 23:45:29 +01:00
database.query('DELETE FROM mailboxes WHERE (name=? OR aliasTarget = ?) AND domain = ?', [ name, name, domain ], function (error, result) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-10-24 20:48:38 -07:00
if (result.affectedRows === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
2016-05-26 22:34:04 -07:00
callback(null);
});
}
2018-02-11 01:18:29 -08:00
function delByDomain(domain, callback) {
assert.strictEqual(typeof domain, 'string');
assert.strictEqual(typeof callback, 'function');
database.query('DELETE FROM mailboxes WHERE domain = ?', [ domain ], function (error) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2018-02-11 01:18:29 -08:00
callback(null);
});
}
function delByOwnerId(id, callback) {
assert.strictEqual(typeof id, 'string');
assert.strictEqual(typeof callback, 'function');
2016-09-25 23:21:55 -07:00
database.query('DELETE FROM mailboxes WHERE ownerId=?', [ id ], function (error) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
callback(null);
});
}
2017-11-09 23:45:29 +01:00
function updateName(oldName, oldDomain, newName, newDomain, callback) {
2016-12-15 16:13:16 +01:00
assert.strictEqual(typeof oldName, 'string');
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof oldDomain, 'string');
2016-12-15 16:13:16 +01:00
assert.strictEqual(typeof newName, 'string');
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof newDomain, 'string');
2016-12-15 16:13:16 +01:00
assert.strictEqual(typeof callback, 'function');
// skip if no changes
2017-11-09 23:45:29 +01:00
if (oldName === newName && oldDomain === newDomain) return callback(null);
2017-11-09 23:45:29 +01:00
database.query('UPDATE mailboxes SET name=?, domain=? WHERE name=? AND domain = ?', [ newName, newDomain, oldName, oldDomain ], function (error, result) {
2019-10-24 13:34:14 -07:00
if (error && error.code === 'ER_DUP_ENTRY') return callback(new BoxError(BoxError.ALREADY_EXISTS, 'mailbox already exists'));
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-10-24 20:48:38 -07:00
if (result.affectedRows !== 1) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
2016-12-15 16:13:16 +01:00
callback(null);
});
}
2019-11-06 16:45:44 -08:00
function get(name, domain, callback) {
assert.strictEqual(typeof name, 'string');
assert.strictEqual(typeof domain, 'string');
assert.strictEqual(typeof callback, 'function');
database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE name = ? AND domain = ?',
[ name, domain ], function (error, results) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
if (results.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
callback(null, postProcess(results[0]));
});
}
2017-11-09 23:45:29 +01:00
function getMailbox(name, domain, callback) {
2016-09-25 18:59:11 -07:00
assert.strictEqual(typeof name, 'string');
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof domain, 'string');
2016-09-25 18:59:11 -07:00
assert.strictEqual(typeof callback, 'function');
2018-04-07 19:12:07 -07:00
database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE name = ? AND type = ? AND domain = ?',
[ name, exports.TYPE_MAILBOX, domain ], function (error, results) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-10-24 20:48:38 -07:00
if (results.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
2016-09-25 18:59:11 -07:00
2018-04-07 19:12:07 -07:00
callback(null, postProcess(results[0]));
});
2016-09-25 18:59:11 -07:00
}
2019-10-22 10:11:35 -07:00
function listMailboxes(domain, page, perPage, callback) {
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof domain, 'string');
2019-10-22 10:11:35 -07:00
assert.strictEqual(typeof page, 'number');
assert.strictEqual(typeof perPage, 'number');
2016-09-25 18:59:11 -07:00
assert.strictEqual(typeof callback, 'function');
2019-10-22 10:11:35 -07:00
database.query(`SELECT ${MAILBOX_FIELDS} FROM mailboxes WHERE type = ? AND domain = ? ORDER BY name LIMIT ${(page-1)*perPage},${perPage}`,
2018-04-07 19:12:07 -07:00
[ exports.TYPE_MAILBOX, domain ], function (error, results) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2016-09-25 18:59:11 -07:00
2018-04-07 19:12:07 -07:00
results.forEach(function (result) { postProcess(result); });
2018-04-07 19:12:07 -07:00
callback(null, results);
});
2016-09-25 18:59:11 -07:00
}
function listAllMailboxes(page, perPage, callback) {
assert.strictEqual(typeof page, 'number');
assert.strictEqual(typeof perPage, 'number');
assert.strictEqual(typeof callback, 'function');
database.query(`SELECT ${MAILBOX_FIELDS} FROM mailboxes WHERE type = ? ORDER BY name LIMIT ${(page-1)*perPage},${perPage}`,
[ exports.TYPE_MAILBOX ], function (error, results) {
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
results.forEach(function (result) { postProcess(result); });
callback(null, results);
});
}
2019-08-23 15:09:06 -07:00
function getLists(domain, callback) {
2018-01-26 10:22:50 +01:00
assert.strictEqual(typeof domain, 'string');
assert.strictEqual(typeof callback, 'function');
2018-04-07 19:12:07 -07:00
database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE type = ? AND domain = ?',
[ exports.TYPE_LIST, domain ], function (error, results) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2018-01-26 10:22:50 +01:00
2018-04-07 19:12:07 -07:00
results.forEach(function (result) { postProcess(result); });
2018-04-07 19:12:07 -07:00
callback(null, results);
});
2018-01-26 10:22:50 +01:00
}
2019-08-23 15:09:06 -07:00
function getList(name, domain, callback) {
2016-09-25 18:59:11 -07:00
assert.strictEqual(typeof name, 'string');
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof domain, 'string');
2016-09-25 18:59:11 -07:00
assert.strictEqual(typeof callback, 'function');
2018-04-07 19:12:07 -07:00
database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE type = ? AND name = ? AND domain = ?',
[ exports.TYPE_LIST, name, domain ], function (error, results) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-10-24 20:48:38 -07:00
if (results.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
2016-09-25 18:59:11 -07:00
2018-04-07 19:12:07 -07:00
callback(null, postProcess(results[0]));
});
2016-09-25 18:59:11 -07:00
}
2016-09-23 17:35:48 -07:00
function getByOwnerId(ownerId, callback) {
assert.strictEqual(typeof ownerId, 'string');
assert.strictEqual(typeof callback, 'function');
2016-09-25 23:21:55 -07:00
database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE ownerId = ? ORDER BY name', [ ownerId ], function (error, results) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-10-24 20:48:38 -07:00
if (results.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
2016-09-23 17:35:48 -07:00
results.forEach(function (result) { postProcess(result); });
2016-09-25 23:21:55 -07:00
callback(null, results);
2016-09-23 17:35:48 -07:00
});
}
2017-11-09 23:45:29 +01:00
function setAliasesForName(name, domain, aliases, callback) {
assert.strictEqual(typeof name, 'string');
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof domain, 'string');
assert(util.isArray(aliases));
assert.strictEqual(typeof callback, 'function');
2017-11-09 23:45:29 +01:00
database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE name = ? AND domain = ?', [ name, domain ], function (error, results) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-10-24 20:48:38 -07:00
if (results.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
2016-09-25 23:21:55 -07:00
var queries = [];
2018-04-07 19:12:07 -07:00
// clear existing aliases
queries.push({ query: 'DELETE FROM mailboxes WHERE aliasTarget = ? AND domain = ? AND type = ?', args: [ name, domain, exports.TYPE_ALIAS ] });
2016-09-25 23:21:55 -07:00
aliases.forEach(function (alias) {
rework how app mailboxes are allocated Our current setup had a mailbox allocated for an app during app install (into the mailboxes table). This has many issues: * When set to a custom mailbox location, there was no way to access this mailbox even via IMAP. Even when using app credentials, we cannot use IMAP since the ldap logic was testing on the addon type (most of our apps only use sendmail addon and thus cannot recvmail). * The mailboxes table was being used to add hidden 'app' type entries. This made it very hard for the user to understand why a mailbox conflicts. For example, if you set an app to use custom mailbox 'blog', this is hidden from all views. The solution is to let an app send email as whatever mailbox name is allocated to it (which we now track in the apps table. the default is in the db already so that REST response contains it). When not using Cloudron email, it will just send mail as that mailbox and the auth checks the "app password" in the addons table. Any replies to that mailbox will end up in the domain's mail server (not our problem). When using cloudron email, the app can send mail like above. Any responses will not end anywhere and bounce since there is no 'mailbox'. This is the expected behavior. If user wants to access this mailbox name, he can create a concrete mailbox and set himself as owner OR set this as an alias. For apps using the recvmail addon, the workflow is to actually create a mailbox at some point. Currently, we have no UI for this 'flow'. It's fine because we have only meemo using it. Intuitive much!
2018-12-06 21:08:19 -08:00
queries.push({ query: 'INSERT INTO mailboxes (name, type, domain, aliasTarget, ownerId) VALUES (?, ?, ?, ?, ?)',
args: [ alias, exports.TYPE_ALIAS, domain, name, results[0].ownerId ] });
2016-09-25 23:21:55 -07:00
});
database.transaction(queries, function (error) {
2019-10-24 20:48:38 -07:00
if (error && error.code === 'ER_DUP_ENTRY' && error.message.indexOf('mailboxes_name_domain_unique_index') !== -1) {
var aliasMatch = error.message.match(new RegExp(`^ER_DUP_ENTRY: Duplicate entry '(.*)-${domain}' for key 'mailboxes_name_domain_unique_index'$`));
if (!aliasMatch) return callback(new BoxError(BoxError.ALREADY_EXISTS, error));
return callback(new BoxError(BoxError.ALREADY_EXISTS, `Mailbox, mailinglist or alias for ${aliasMatch[1]} already exists`));
}
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2016-09-25 23:21:55 -07:00
callback(null);
});
});
}
2017-11-09 23:45:29 +01:00
function getAliasesForName(name, domain, callback) {
assert.strictEqual(typeof name, 'string');
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof domain, 'string');
assert.strictEqual(typeof callback, 'function');
2018-04-07 19:12:07 -07:00
database.query('SELECT name FROM mailboxes WHERE type = ? AND aliasTarget = ? AND domain = ? ORDER BY name',
[ exports.TYPE_ALIAS, name, domain ], function (error, results) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2016-05-26 22:34:04 -07:00
2018-04-07 19:12:07 -07:00
results = results.map(function (r) { return r.name; });
callback(null, results);
});
2016-05-26 22:34:04 -07:00
}
2016-09-25 18:59:11 -07:00
2019-10-22 10:11:35 -07:00
function listAliases(domain, page, perPage, callback) {
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof domain, 'string');
2019-10-22 10:11:35 -07:00
assert.strictEqual(typeof page, 'number');
assert.strictEqual(typeof perPage, 'number');
2016-09-25 18:59:11 -07:00
assert.strictEqual(typeof callback, 'function');
2019-10-22 10:11:35 -07:00
database.query(`SELECT ${MAILBOX_FIELDS} FROM mailboxes WHERE domain = ? AND type = ? ORDER BY name LIMIT ${(page-1)*perPage},${perPage}`,
2018-04-07 19:12:07 -07:00
[ domain, exports.TYPE_ALIAS ], function (error, results) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2016-09-25 18:59:11 -07:00
2018-04-07 19:12:07 -07:00
results.forEach(function (result) { postProcess(result); });
2018-04-07 19:12:07 -07:00
callback(null, results);
});
2016-09-25 18:59:11 -07:00
}
2017-11-09 23:45:29 +01:00
function getAlias(name, domain, callback) {
2016-09-25 18:59:11 -07:00
assert.strictEqual(typeof name, 'string');
2017-11-09 23:45:29 +01:00
assert.strictEqual(typeof domain, 'string');
2016-09-25 18:59:11 -07:00
assert.strictEqual(typeof callback, 'function');
2018-04-07 19:12:07 -07:00
database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE name = ? AND type = ? AND domain = ?',
[ name, exports.TYPE_ALIAS, domain ], function (error, results) {
2019-10-24 13:34:14 -07:00
if (error) return callback(new BoxError(BoxError.DATABASE_ERROR, error));
2019-10-24 20:48:38 -07:00
if (results.length === 0) return callback(new BoxError(BoxError.NOT_FOUND, 'Mailbox not found'));
2016-09-25 18:59:11 -07:00
2018-04-07 19:12:07 -07:00
results.forEach(function (result) { postProcess(result); });
2018-04-07 19:12:07 -07:00
callback(null, results[0]);
});
2016-09-25 18:59:11 -07:00
}