rework mail domain stats
We can now show list count, alias count as well in the mail domains UI
This commit is contained in:
+35
-40
@@ -25,9 +25,8 @@ exports = module.exports = {
|
||||
|
||||
sendTestMail,
|
||||
|
||||
getMailboxCount,
|
||||
listMailboxesByDomain,
|
||||
listMailboxes,
|
||||
listAllMailboxes,
|
||||
getMailbox,
|
||||
addMailbox,
|
||||
updateMailbox,
|
||||
@@ -38,13 +37,14 @@ exports = module.exports = {
|
||||
setAliases,
|
||||
searchAlias,
|
||||
|
||||
getListCount,
|
||||
getLists,
|
||||
getList,
|
||||
addList,
|
||||
updateList,
|
||||
delList,
|
||||
resolveList,
|
||||
listMailingListsByDomain,
|
||||
getMailingList,
|
||||
addMailingList,
|
||||
updateMailingList,
|
||||
delMailingList,
|
||||
resolveMailingList,
|
||||
|
||||
getStats,
|
||||
|
||||
checkStatus,
|
||||
|
||||
@@ -70,7 +70,6 @@ const assert = require('node:assert'),
|
||||
eventlog = require('./eventlog.js'),
|
||||
mailer = require('./mailer.js'),
|
||||
mailServer = require('./mailserver.js'),
|
||||
mysql = require('mysql2'),
|
||||
net = require('node:net'),
|
||||
network = require('./network.js'),
|
||||
nodemailer = require('nodemailer'),
|
||||
@@ -87,7 +86,7 @@ const assert = require('node:assert'),
|
||||
const DNS_OPTIONS = { timeout: 20000, tries: 4 };
|
||||
const REMOVE_MAILBOX_CMD = path.join(__dirname, 'scripts/rmmailbox.sh');
|
||||
|
||||
// if you add a field here, listMailboxes has to be updated
|
||||
// if you add a field here, listMailboxes* has to be updated
|
||||
const MAILBOX_FIELDS = [ 'name', 'type', 'ownerId', 'ownerType', 'aliasName', 'aliasDomain', 'creationTime', 'membersJson', 'membersOnly', 'domain', 'active', 'enablePop3', 'storageQuota', 'messagesQuota' ].join(',');
|
||||
const MAILDB_FIELDS = [ 'domain', 'enabled', 'mailFromValidation', 'catchAllJson', 'relayJson', 'dkimKeyJson', 'dkimSelector', 'bannerJson' ].join(',');
|
||||
|
||||
@@ -837,14 +836,13 @@ async function sendTestMail(domain, to) {
|
||||
await mailer.sendTestMail(result.domain, to);
|
||||
}
|
||||
|
||||
async function listMailboxes(domain, search, page, perPage) {
|
||||
async function listMailboxesByDomain(domain, page, perPage) {
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
assert(typeof search === 'string' || search === null);
|
||||
assert.strictEqual(typeof page, 'number');
|
||||
assert.strictEqual(typeof perPage, 'number');
|
||||
|
||||
const escapedSearch = mysql.escape('%' + search + '%'); // this also quotes the string
|
||||
const searchQuery = search ? ` HAVING (name LIKE ${escapedSearch} OR aliasNames LIKE ${escapedSearch} OR aliasDomains LIKE ${escapedSearch})` : ''; // having instead of where because of aggregated columns use
|
||||
// const escapedSearch = mysql.escape('%' + search + '%'); // this also quotes the string
|
||||
// const searchQuery = search ? ` HAVING (name LIKE ${escapedSearch} OR aliasNames LIKE ${escapedSearch} OR aliasDomains LIKE ${escapedSearch})` : ''; // having instead of where because of aggregated columns use
|
||||
|
||||
const query = 'SELECT m1.name AS name, m1.domain AS domain, m1.ownerId AS ownerId, m1.ownerType as ownerType, m1.active as active, JSON_ARRAYAGG(m2.name) AS aliasNames, JSON_ARRAYAGG(m2.domain) AS aliasDomains, m1.enablePop3 AS enablePop3, m1.storageQuota AS storageQuota, m1.messagesQuota AS messagesQuota '
|
||||
+ ` FROM (SELECT * FROM mailboxes WHERE type='${exports.TYPE_MAILBOX}') AS m1`
|
||||
@@ -852,7 +850,7 @@ async function listMailboxes(domain, search, page, perPage) {
|
||||
+ ' ON m1.name=m2.aliasName AND m1.domain=m2.aliasDomain AND m1.ownerId=m2.ownerId'
|
||||
+ ' WHERE m1.domain = ?'
|
||||
+ ' GROUP BY m1.name, m1.domain, m1.ownerId'
|
||||
+ searchQuery
|
||||
// + searchQuery
|
||||
+ ' ORDER BY name LIMIT ?,?';
|
||||
|
||||
const results = await database.query(query, [ domain, (page-1)*perPage, perPage ]);
|
||||
@@ -863,7 +861,7 @@ async function listMailboxes(domain, search, page, perPage) {
|
||||
return results;
|
||||
}
|
||||
|
||||
async function listAllMailboxes(page, perPage) {
|
||||
async function listMailboxes(page, perPage) {
|
||||
assert.strictEqual(typeof page, 'number');
|
||||
assert.strictEqual(typeof perPage, 'number');
|
||||
|
||||
@@ -882,12 +880,18 @@ async function listAllMailboxes(page, perPage) {
|
||||
return results;
|
||||
}
|
||||
|
||||
async function getMailboxCount(domain) {
|
||||
async function getStats(domain) {
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
|
||||
const results = await database.query('SELECT COUNT(*) AS total FROM mailboxes WHERE type = ? AND domain = ?', [ exports.TYPE_MAILBOX, domain ]);
|
||||
const mailboxes = await listMailboxesByDomain(domain, 1, 10000);
|
||||
const mailingLists = await listMailingListsByDomain(domain, 1, 10000);
|
||||
|
||||
return results[0].total;
|
||||
return {
|
||||
mailboxCount: mailboxes.length,
|
||||
pop3Count: mailboxes.filter(mb => mb.enablePop3).length,
|
||||
aliasCount: mailboxes.map(mb => mb.aliases.length).reduce((a, b) => a + b, 0),
|
||||
mailingListCount: mailingLists.length
|
||||
};
|
||||
}
|
||||
|
||||
async function delByDomain(domain) {
|
||||
@@ -900,7 +904,7 @@ async function get(name, domain) {
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
|
||||
const results = await database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE name = ? AND domain = ?', [ name, domain ]);
|
||||
const results = await database.query(`SELECT ${MAILBOX_FIELDS} FROM mailboxes WHERE name = ? AND domain = ?`, [ name, domain ]);
|
||||
if (results.length === 0) return null;
|
||||
|
||||
return postProcessMailbox(results[0]);
|
||||
@@ -910,7 +914,7 @@ async function getMailbox(name, domain) {
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
|
||||
const results = await database.query('SELECT ' + MAILBOX_FIELDS + ' FROM mailboxes WHERE name = ? AND type = ? AND domain = ?', [ name, exports.TYPE_MAILBOX, domain ]);
|
||||
const results = await database.query(`SELECT ${MAILBOX_FIELDS} FROM mailboxes WHERE name = ? AND type = ? AND domain = ?`, [ name, exports.TYPE_MAILBOX, domain ]);
|
||||
if (results.length === 0) return null;
|
||||
return postProcessMailbox(results[0]);
|
||||
}
|
||||
@@ -1089,22 +1093,13 @@ async function setAliases(name, domain, aliases, auditSource) {
|
||||
await eventlog.add(eventlog.ACTION_MAIL_MAILBOX_UPDATE, auditSource, { name, domain, aliases });
|
||||
}
|
||||
|
||||
async function getListCount(domain) {
|
||||
async function listMailingListsByDomain(domain, page, perPage) {
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
|
||||
const results = await database.query('SELECT COUNT(*) AS total FROM mailboxes WHERE type = ? AND domain = ?', [ exports.TYPE_LIST, domain ]);
|
||||
|
||||
return results[0].total;
|
||||
}
|
||||
|
||||
async function getLists(domain, search, page, perPage) {
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
assert(typeof search === 'string' || search === null);
|
||||
assert.strictEqual(typeof page, 'number');
|
||||
assert.strictEqual(typeof perPage, 'number');
|
||||
|
||||
let query = `SELECT ${MAILBOX_FIELDS} FROM mailboxes WHERE type = ? AND domain = ?`;
|
||||
if (search) query += ' AND (name LIKE ' + mysql.escape('%' + search + '%') + ' OR membersJson LIKE ' + mysql.escape('%' + search + '%') + ')';
|
||||
// if (search) query += ' AND (name LIKE ' + mysql.escape('%' + search + '%') + ' OR membersJson LIKE ' + mysql.escape('%' + search + '%') + ')';
|
||||
|
||||
query += 'ORDER BY name LIMIT ?,?';
|
||||
|
||||
@@ -1115,7 +1110,7 @@ async function getLists(domain, search, page, perPage) {
|
||||
return results;
|
||||
}
|
||||
|
||||
async function getList(name, domain) {
|
||||
async function getMailingList(name, domain) {
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
|
||||
@@ -1125,7 +1120,7 @@ async function getList(name, domain) {
|
||||
return postProcessMailbox(results[0]);
|
||||
}
|
||||
|
||||
async function addList(name, domain, data, auditSource) {
|
||||
async function addMailingList(name, domain, data, auditSource) {
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
assert.strictEqual(typeof data, 'object');
|
||||
@@ -1152,7 +1147,7 @@ async function addList(name, domain, data, auditSource) {
|
||||
await eventlog.add(eventlog.ACTION_MAIL_LIST_ADD, auditSource, { name, domain, members, membersOnly, active });
|
||||
}
|
||||
|
||||
async function updateList(name, domain, data, auditSource) {
|
||||
async function updateMailingList(name, domain, data, auditSource) {
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
assert.strictEqual(typeof data, 'object');
|
||||
@@ -1179,7 +1174,7 @@ async function updateList(name, domain, data, auditSource) {
|
||||
await eventlog.add(eventlog.ACTION_MAIL_LIST_UPDATE, auditSource, { name, domain, oldMembers: result.members, members, membersOnly, active });
|
||||
}
|
||||
|
||||
async function delList(name, domain, auditSource) {
|
||||
async function delMailingList(name, domain, auditSource) {
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
assert.strictEqual(typeof auditSource, 'object');
|
||||
@@ -1192,14 +1187,14 @@ async function delList(name, domain, auditSource) {
|
||||
}
|
||||
|
||||
// resolves the members of a list. i.e the lists and aliases
|
||||
async function resolveList(listName, listDomain) {
|
||||
async function resolveMailingList(listName, listDomain) {
|
||||
assert.strictEqual(typeof listName, 'string');
|
||||
assert.strictEqual(typeof listDomain, 'string');
|
||||
|
||||
const mailDomains = await listDomains();
|
||||
const mailInDomains = mailDomains.filter(function (d) { return d.enabled; }).map(function (d) { return d.domain; }).join(',');
|
||||
|
||||
const list = await getList(listName, listDomain);
|
||||
const list = await getMailingList(listName, listDomain);
|
||||
if (!list) throw new BoxError(BoxError.NOT_FOUND, 'List not found');
|
||||
|
||||
const resolvedMembers = [], visited = []; // slice creates a copy of array
|
||||
@@ -1217,7 +1212,7 @@ async function resolveList(listName, listDomain) {
|
||||
|
||||
const member =`${memberName}@${memberDomain}`; // cleaned up without any '+' subaddress
|
||||
if (visited.includes(member)) {
|
||||
debug(`resolveList: list ${listName}@${listDomain} has a recursion at member ${member}`);
|
||||
debug(`resolveMailingList: list ${listName}@${listDomain} has a recursion at member ${member}`);
|
||||
continue;
|
||||
}
|
||||
visited.push(member);
|
||||
|
||||
Reference in New Issue
Block a user