Files
cloudron-box/dashboard/public/views/emails.js

522 lines
17 KiB
JavaScript
Raw Normal View History

2020-02-11 21:06:34 +01:00
'use strict';
2020-09-01 16:31:23 +02:00
/* global $, angular, TASK_TYPES */
/* global async */
2020-02-11 21:06:34 +01:00
2020-11-12 16:38:48 +01:00
angular.module('Application').controller('EmailsController', ['$scope', '$location', '$translate', '$timeout', 'Client', function ($scope, $location, $translate, $timeout, Client) {
Client.onReady(function () { if (!Client.getUserInfo().isAtLeastMailManager) $location.path('/'); });
2020-02-11 21:06:34 +01:00
$scope.ready = false;
$scope.config = Client.getConfig();
$scope.user = Client.getUserInfo();
2020-02-11 21:06:34 +01:00
$scope.domains = [];
2020-08-20 23:06:22 -07:00
$scope.mailLocation = {
2020-08-17 22:44:01 +02:00
busy: false,
percent: 0,
message: '',
errorMessage: '',
2020-08-17 22:44:01 +02:00
currentLocation: { domain: null, subdomain: '' },
domain: null,
subdomain: '',
tasks: [],
refreshTasks: function () {
Client.getTasksByType(TASK_TYPES.TASK_CHANGE_MAIL_LOCATION, function (error, tasks) {
if (error) return console.error(error);
$scope.mailLocation.tasks = tasks.slice(0, 10);
if ($scope.mailLocation.tasks.length && $scope.mailLocation.tasks[0].active) $scope.mailLocation.updateStatus();
});
},
stop: function () {
Client.stopTask($scope.mailLocation.tasks[0].id, function (error) {
if (error) console.error(error);
$scope.mailLocation.busy = false;
$scope.mailLocation.refreshTasks();
});
},
2020-08-22 19:34:06 -07:00
refresh: function () {
Client.getMailLocation(function (error, location) {
if (error) return console.error('Failed to get max email location', error);
$scope.mailLocation.currentLocation.subdomain = $scope.mailLocation.subdomain = location.subdomain;
$scope.mailLocation.currentLocation.domain = $scope.mailLocation.domain = $scope.domains.find(function (d) { return location.domain === d.domain; });
2020-09-01 16:31:23 +02:00
$scope.mailLocation.refreshTasks();
2020-08-22 19:34:06 -07:00
});
},
2020-09-01 16:31:23 +02:00
updateStatus: function () {
var taskId = $scope.mailLocation.tasks[0].id;
Client.getTask(taskId, function (error, data) {
2020-09-01 16:31:23 +02:00
if (error) return window.setTimeout($scope.mailLocation.updateStatus, 5000);
if (!data.active) {
$scope.mailLocation.busy = false;
$scope.mailLocation.message = '';
$scope.mailLocation.percent = 100;
2020-09-01 16:31:23 +02:00
$scope.mailLocation.errorMessage = data.success ? '' : data.error.message;
$scope.mailLocation.refreshTasks(); // update the tasks list dropdown
2020-09-01 16:31:23 +02:00
return;
}
$scope.mailLocation.busy = true;
$scope.mailLocation.percent = data.percent;
$scope.mailLocation.message = data.message;
window.setTimeout($scope.mailLocation.updateStatus, 1000);
});
},
change: function () {
2020-08-20 23:06:22 -07:00
$scope.mailLocation.busy = true;
$scope.mailLocation.percent = 0;
$scope.mailLocation.message = '';
$scope.mailLocation.errorMessage = '';
2020-08-20 23:06:22 -07:00
2024-04-18 13:30:01 +02:00
Client.setMailLocation($scope.mailLocation.subdomain, $scope.mailLocation.domain.domain, function (error) {
2020-08-20 23:06:22 -07:00
if (error) {
console.error(error);
$scope.mailLocation.errorMessage = error.message;
2020-08-20 23:06:22 -07:00
$scope.mailLocation.busy = false;
} else {
$scope.mailLocation.refreshTasks();
2020-08-20 23:06:22 -07:00
}
Client.refreshConfig(); // update config.mailFqdn
2020-08-20 23:06:22 -07:00
});
2020-08-17 22:44:01 +02:00
}
};
$scope.maxEmailSize = {
busy: false,
error: null,
size: 0,
currentSize: 0,
2020-08-22 19:34:06 -07:00
refresh: function () {
Client.getMaxEmailSize(function (error, size) {
if (error) return console.error('Failed to get max email size', error);
$scope.maxEmailSize.currentSize = size;
});
},
2020-08-17 22:44:01 +02:00
show: function() {
$scope.maxEmailSize.busy = false;
$scope.maxEmailSize.error = null;
2020-08-20 22:07:20 -07:00
$scope.maxEmailSize.size = $scope.maxEmailSize.currentSize;
2020-08-17 22:44:01 +02:00
$scope.maxEmailSizeChangeForm.$setUntouched();
$scope.maxEmailSizeChangeForm.$setPristine();
$('#maxEmailSizeChangeModal').modal('show');
},
submit: function () {
2020-08-20 22:07:20 -07:00
$scope.maxEmailSize.busy = true;
Client.setMaxEmailSize(parseInt($scope.maxEmailSize.size), function (error) {
2020-08-20 22:07:20 -07:00
$scope.maxEmailSize.busy = false;
if (error) return console.error(error);
$scope.maxEmailSize.currentSize = $scope.maxEmailSize.size;
$('#maxEmailSizeChangeModal').modal('hide');
});
2020-08-17 22:44:01 +02:00
}
};
$scope.virtualAllMail = {
busy: false,
error: null,
enabled: false,
refresh: function () {
Client.getVirtualAllMail(function (error, enabled) {
if (error) return console.error('Failed to get max email size', error);
$scope.virtualAllMail.enabled = enabled;
});
},
show: function() {
$scope.virtualAllMail.busy = false;
$scope.virtualAllMail.error = null;
$('#virtualAllMailChangeModal').modal('show');
},
submit: function (enable) {
$scope.virtualAllMail.busy = true;
Client.setVirtualAllMail(enable, function (error) {
$scope.virtualAllMail.busy = false;
if (error) return console.error(error);
$scope.virtualAllMail.enabled = enable;
$('#virtualAllMailChangeModal').modal('hide');
});
}
};
$scope.mailboxSharing = {
busy: false,
error: null,
2021-12-08 11:33:36 -08:00
enabled: null, // null means we have not refreshed yet
refresh: function () {
Client.getMailboxSharing(function (error, enabled) {
if (error) return console.error('Failed to get mailbox sharing', error);
$scope.mailboxSharing.enabled = enabled;
});
},
submit: function () {
$scope.mailboxSharing.busy = true;
2021-12-08 11:33:36 -08:00
Client.setMailboxSharing(!$scope.mailboxSharing.enabled, function (error) {
// give sometime for mail server to restart
$timeout(function () {
$scope.mailboxSharing.busy = false;
if (error) return console.error(error);
$scope.mailboxSharing.enabled = !$scope.mailboxSharing.enabled;
}, 3000);
});
}
};
2024-11-30 17:42:26 +01:00
$scope.ftsConfig = {
2020-11-19 17:45:16 -08:00
busy: false,
error: {},
2020-12-02 17:33:54 -08:00
currentConfig: null, // null means not loaded yet
2020-11-19 17:45:16 -08:00
enabled: false,
2020-12-02 17:16:59 -08:00
running: false,
2020-12-02 17:33:54 -08:00
enoughMemory: false,
2020-11-19 17:45:16 -08:00
refresh: function () {
2020-12-02 17:16:59 -08:00
Client.getService('mail', function (error, result) {
if (error) return console.log('Error getting status of mail conatiner', error);
2020-11-19 17:45:16 -08:00
2024-11-30 17:42:26 +01:00
$scope.ftsConfig.enoughMemory = result.config.memoryLimit > (1024*1024*1024*2);
$scope.ftsConfig.running = result.healthcheck && result.healthcheck.solr.status && result.healthcheck.tika.status;
2020-12-02 17:33:54 -08:00
2024-11-30 17:42:26 +01:00
Client.getFtsConfig(function (error, config) {
2020-12-02 17:16:59 -08:00
if (error) return console.error('Failed to get solr config', error);
2020-11-19 17:45:16 -08:00
2024-11-30 17:42:26 +01:00
$scope.ftsConfig.currentConfig = config;
2020-12-02 17:16:59 -08:00
});
2020-11-19 17:45:16 -08:00
});
},
show: function() {
2024-11-30 17:42:26 +01:00
$scope.ftsConfig.busy = false;
$scope.ftsConfig.error = null;
$scope.ftsConfig.enabled = $scope.ftsConfig.currentConfig.enabled;
2020-11-19 17:45:16 -08:00
2024-11-30 17:42:26 +01:00
$('#ftsConfigModal').modal('show');
2020-11-19 17:45:16 -08:00
},
submit: function (newState) {
2024-11-30 17:42:26 +01:00
$scope.ftsConfig.busy = true;
2020-11-19 17:45:16 -08:00
2024-11-30 17:42:26 +01:00
Client.setFtsConfig(newState, function (error) {
2020-11-19 17:45:16 -08:00
if (error) return console.error(error);
$timeout(function () {
2024-11-30 17:42:26 +01:00
$scope.ftsConfig.busy = false;
2020-12-04 15:51:36 -08:00
// FIXME: these values are fake. but cannot get current status from mail server since it might be restarting
2024-11-30 17:42:26 +01:00
$scope.ftsConfig.currentConfig.enabled = newState;
$scope.ftsConfig.running = newState;
2020-12-04 15:51:36 -08:00
2024-11-30 17:42:26 +01:00
$timeout(function () { $scope.ftsConfig.refresh(); }, 20000); // get real values after 20 seconds
2020-12-04 15:51:36 -08:00
2024-11-30 17:42:26 +01:00
$('#ftsConfigModal').modal('hide');
}, 5000);
2020-11-19 17:45:16 -08:00
});
}
};
2020-08-22 13:01:25 -07:00
$scope.spamConfig = {
2020-08-17 22:44:01 +02:00
busy: false,
2020-08-22 13:01:25 -07:00
error: {},
2024-05-23 16:35:35 +02:00
acl: { allowlist: [], blocklist: [] },
2020-08-22 13:01:25 -07:00
customConfig: '',
config: '',
2024-05-23 16:35:35 +02:00
blocklist: '', // currently, we don't support allowlist because it requires user to understand a bit more of what he is doing
2020-08-22 13:01:25 -07:00
refresh: function () {
Client.getSpamCustomConfig(function (error, config) {
if (error) return console.error('Failed to get custom spam config', error);
$scope.spamConfig.customConfig = config;
});
Client.getSpamAcl(function (error, acl) {
if (error) return console.error('Failed to get spam acl', error);
$scope.spamConfig.acl = acl;
});
},
2020-08-17 22:44:01 +02:00
show: function() {
2020-08-22 13:01:25 -07:00
$scope.spamConfig.busy = false;
$scope.spamConfig.error = {};
2024-05-23 16:35:35 +02:00
$scope.spamConfig.blocklist = $scope.spamConfig.acl.blocklist.join('\n');
2020-08-22 13:01:25 -07:00
$scope.spamConfig.config = $scope.spamConfig.customConfig;
2020-08-17 22:44:01 +02:00
2020-08-22 13:01:25 -07:00
$scope.spamConfigChangeForm.$setUntouched();
$scope.spamConfigChangeForm.$setPristine();
2020-08-17 22:44:01 +02:00
2020-08-22 13:01:25 -07:00
$('#spamConfigChangeModal').modal('show');
2020-08-17 22:44:01 +02:00
},
submit: function () {
2020-08-22 13:01:25 -07:00
$scope.spamConfig.busy = true;
$scope.spamConfig.error = {};
2024-05-23 16:35:35 +02:00
var blocklist = $scope.spamConfig.blocklist.split('\n').filter(function (l) { return l !== ''; });
2020-08-22 13:01:25 -07:00
2024-05-23 16:35:35 +02:00
Client.setSpamAcl({ blocklist: blocklist, allowlist: [] }, function (error) {
2020-08-22 13:01:25 -07:00
if (error) {
$scope.spamConfig.busy = false;
2024-05-23 16:35:35 +02:00
$scope.spamConfig.error.blocklist = error.message;
$scope.spamConfigChangeForm.blocklist.$setPristine();
2020-08-22 13:01:25 -07:00
return;
}
Client.setSpamCustomConfig($scope.spamConfig.config, function (error) {
if (error) {
$scope.spamConfig.busy = false;
$scope.spamConfig.error.config = error.message;
$scope.spamConfigChangeForm.config.$setPristine();
return;
}
$scope.spamConfig.busy = false;
$scope.spamConfig.refresh();
$('#spamConfigChangeModal').modal('hide');
});
});
2020-08-17 22:44:01 +02:00
}
2020-08-20 23:06:22 -07:00
},
2020-08-17 22:44:01 +02:00
2021-10-13 14:22:37 -07:00
$scope.acl = {
busy: false,
error: {},
dnsblZones: '',
dnsblZonesCount: 0,
refresh: function () {
Client.getDnsblConfig(function (error, result) {
if (error) return console.error('Failed to get email acl', error);
$scope.acl.dnsblZones = result.zones.join('\n');
$scope.acl.dnsblZonesCount = result.zones.length;
});
},
show: function() {
$scope.acl.busy = false;
$scope.acl.error = {};
$scope.aclChangeForm.$setUntouched();
$scope.aclChangeForm.$setPristine();
$('#aclChangeModal').modal('show');
},
submit: function () {
$scope.acl.busy = true;
$scope.acl.error = {};
var zones = $scope.acl.dnsblZones.split('\n').filter(function (l) { return l !== ''; });
Client.setDnsblConfig(zones, function (error) {
if (error) {
$scope.acl.busy = false;
$scope.acl.error.dnsblZones = error.message;
$scope.aclChangeForm.dnsblZones.$setPristine();
return;
}
$scope.acl.busy = false;
$scope.acl.refresh();
$('#aclChangeModal').modal('hide');
});
}
},
$scope.testEmail = {
busy: false,
error: {},
mailTo: '',
domain: null,
clearForm: function () {
$scope.testEmail.mailTo = '';
},
show: function (domain) {
$scope.testEmail.error = {};
$scope.testEmail.busy = false;
$scope.testEmail.domain = domain;
$scope.testEmail.mailTo = $scope.user.email;
$('#testEmailModal').modal('show');
},
submit: function () {
$scope.testEmail.error = {};
$scope.testEmail.busy = true;
Client.sendTestMail($scope.testEmail.domain.domain, $scope.testEmail.mailTo, function (error) {
$scope.testEmail.busy = false;
if (error) {
$scope.testEmail.error.generic = error.message;
console.error(error);
$('#inputTestMailTo').focus();
return;
}
$('#testEmailModal').modal('hide');
});
}
};
function refreshMailStatus(domain, done) {
Client.getMailStatusForDomain(domain.domain, function (error, result) {
if (error) {
console.error('Failed to fetch mail status for domain', domain.domain, error);
return done();
}
domain.status = result;
domain.statusOk = Object.keys(result).every(function (k) {
if (k === 'dns') return Object.keys(result.dns).every(function (k) { return result.dns[k].status; });
2020-02-27 10:37:21 -08:00
if (!('status' in result[k])) return true; // if status is not present, the test was not run
2020-02-27 10:37:21 -08:00
return result[k].status;
});
2020-02-20 12:35:51 -08:00
done();
});
}
function refreshMailConfig(domain, done) {
Client.getMailConfigForDomain(domain.domain, function (error, mailConfig) {
if (error) {
console.error('Failed to fetch mail config for domain', domain.domain, error);
return done();
}
domain.inbound = mailConfig.enabled;
domain.outbound = mailConfig.relay.provider !== 'noop';
// do this even if no outbound since people forget to remove mailboxes
Client.getMailboxCount(domain.domain, function (error, count) {
if (error) {
console.error('Failed to fetch mailboxes for domain', domain.domain, error);
return done();
}
domain.mailboxCount = count;
2020-02-20 12:35:51 -08:00
done();
});
});
}
2020-02-20 12:35:51 -08:00
function refreshMailUsage(domain, done) {
Client.getMailUsage(domain.domain, function (error, usage) {
if (error) {
console.error('Failed to fetch usage for domain', domain.domain, error);
return done();
}
2020-02-20 12:35:51 -08:00
domain.usage = 0;
// we used to use quotaValue here but it's quite different wrt diskSize. so choose diskSize consistently
// also, quotaValue can be missing for deleted mailboxes that are on disk but removed from dovecot/ldap itself
Object.keys(usage).forEach(function (m) { domain.usage += usage[m].diskSize; });
2020-02-20 12:35:51 -08:00
done();
});
}
2020-02-20 12:35:51 -08:00
function refreshDomainStatuses() {
async.each($scope.domains, function (domain, iteratorDone) {
async.series([
refreshMailStatus.bind(null, domain),
refreshMailConfig.bind(null, domain),
], function () {
domain.loading = false;
iteratorDone();
});
}, function () {
// mail usage is loaded separately with a cancellation check. when there are a lot of domains, it runs a long time in background and slows down loading of new views
async.eachLimit($scope.domains, 5, function (domain, itemDone) {
if ($scope.$$destroyed) return itemDone(); // abort!
refreshMailUsage(domain, function () {
domain.loadingUsage = false;
itemDone();
2020-02-20 12:35:51 -08:00
});
});
});
}
2020-02-11 21:06:34 +01:00
Client.onReady(function () {
Client.getDomains(function (error, domains) {
if (error) return console.error('Unable to get domain listing.', error);
domains.forEach(function (domain) { domain.loading = true; domain.loadingUsage = true; }); // used by ui to show 'loading'
2020-02-11 21:06:34 +01:00
$scope.domains = domains;
2020-02-11 21:06:34 +01:00
$scope.ready = true;
2020-02-11 22:07:58 -08:00
if ($scope.user.isAtLeastAdmin) {
$scope.mailLocation.refresh();
$scope.maxEmailSize.refresh();
$scope.virtualAllMail.refresh();
$scope.mailboxSharing.refresh();
$scope.spamConfig.refresh();
2024-11-30 17:42:26 +01:00
$scope.ftsConfig.refresh();
$scope.acl.refresh();
}
2020-09-01 16:31:23 +02:00
refreshDomainStatuses();
2020-02-11 21:06:34 +01:00
});
});
// setup all the dialog focus handling
['testEmailModal'].forEach(function (id) {
$('#' + id).on('shown.bs.modal', function () {
$(this).find('[autofocus]:first').focus();
});
});
2020-02-11 21:06:34 +01:00
$('.modal-backdrop').remove();
}]);