2018-01-22 13:01:38 -08:00
|
|
|
'use strict';
|
|
|
|
|
|
2020-06-03 23:17:06 +02:00
|
|
|
/* global angular */
|
|
|
|
|
/* global $ */
|
|
|
|
|
/* global async */
|
2019-01-22 10:54:03 +01:00
|
|
|
|
2021-11-19 15:45:16 +01:00
|
|
|
angular.module('Application').controller('EmailController', ['$scope', '$location', '$translate', '$timeout', '$route', '$routeParams', 'Client', function ($scope, $location, $translate, $timeout, $route, $routeParams, Client) {
|
2021-12-02 09:29:33 -08:00
|
|
|
Client.onReady(function () { if (!Client.getUserInfo().isAtLeastMailManager) $location.path('/'); });
|
|
|
|
|
|
|
|
|
|
$scope.user = Client.getUserInfo();
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2021-11-19 15:45:16 +01:00
|
|
|
// Avoid full reload on path change
|
|
|
|
|
// https://stackoverflow.com/a/22614334
|
|
|
|
|
// reloadOnUrl: false in $routeProvider did not work!
|
|
|
|
|
var lastRoute = $route.current;
|
|
|
|
|
$scope.$on('$locationChangeSuccess', function (/* event */) {
|
|
|
|
|
if (lastRoute.$$route.originalPath === $route.current.$$route.originalPath) {
|
|
|
|
|
$route.current = lastRoute;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
var domainName = $routeParams.domain;
|
|
|
|
|
if (!domainName) return $location.path('/email');
|
|
|
|
|
|
2021-11-19 15:45:16 +01:00
|
|
|
$scope.setView = function (view, setAlways) {
|
|
|
|
|
if (!setAlways && !$scope.ready) return;
|
|
|
|
|
if ($scope.view === view) return;
|
|
|
|
|
|
|
|
|
|
$route.updateParams({ view: view });
|
|
|
|
|
$scope.view = view;
|
|
|
|
|
$scope.activeTab = view;
|
|
|
|
|
};
|
|
|
|
|
|
2018-01-23 12:30:35 +01:00
|
|
|
$scope.ready = false;
|
|
|
|
|
$scope.refreshBusy = true;
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.client = Client;
|
|
|
|
|
$scope.user = Client.getUserInfo();
|
|
|
|
|
$scope.config = Client.getConfig();
|
2018-12-06 10:28:42 -08:00
|
|
|
$scope.apps = Client.getInstalledApps();
|
2020-11-12 23:53:02 -08:00
|
|
|
$scope.owners = []; // users + groups
|
2020-04-19 19:44:45 -07:00
|
|
|
$scope.incomingDomains = [];
|
2020-02-11 21:06:34 +01:00
|
|
|
$scope.domain = null;
|
2019-12-31 10:33:09 -08:00
|
|
|
$scope.adminDomain = null;
|
2020-07-05 12:18:34 -07:00
|
|
|
$scope.diskUsage = {};
|
2018-01-23 12:30:35 +01:00
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.expectedDnsRecords = {
|
|
|
|
|
mx: { },
|
|
|
|
|
dkim: { },
|
|
|
|
|
spf: { },
|
|
|
|
|
dmarc: { },
|
|
|
|
|
ptr: { }
|
|
|
|
|
};
|
2020-07-16 18:51:29 +02:00
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.expectedDnsRecordsTypes = [
|
|
|
|
|
{ name: 'MX', value: 'mx' },
|
|
|
|
|
{ name: 'DKIM', value: 'dkim' },
|
|
|
|
|
{ name: 'SPF', value: 'spf' },
|
|
|
|
|
{ name: 'DMARC', value: 'dmarc' },
|
|
|
|
|
{ name: 'PTR', value: 'ptr' }
|
|
|
|
|
];
|
|
|
|
|
|
2020-07-16 18:51:29 +02:00
|
|
|
$scope.openSubscriptionSetup = function () {
|
|
|
|
|
Client.openSubscriptionSetup($scope.$parent.subscription);
|
|
|
|
|
};
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.catchall = {
|
2018-04-12 13:02:32 +02:00
|
|
|
mailboxes: [],
|
2020-12-18 16:56:09 +01:00
|
|
|
availableMailboxes: [],
|
2018-01-22 13:01:38 -08:00
|
|
|
busy: false,
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
|
$scope.catchall.busy = true;
|
|
|
|
|
|
2018-04-12 13:02:32 +02:00
|
|
|
var addresses = $scope.catchall.mailboxes.map(function (m) { return m.name; });
|
|
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
Client.setCatchallAddresses($scope.domain.domain, addresses, function (error) {
|
2018-01-22 13:01:38 -08:00
|
|
|
if (error) console.error('Unable to add catchall address.', error);
|
|
|
|
|
|
2019-01-31 12:24:27 -08:00
|
|
|
$timeout(function () { $scope.catchall.busy = false; }, 2000); // otherwise, it's too fast
|
2018-01-22 13:01:38 -08:00
|
|
|
});
|
2018-04-12 13:02:32 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
refresh: function () {
|
2021-01-12 19:22:18 -08:00
|
|
|
Client.listMailboxes($scope.domain.domain, '', 1, 1000, function (error, result) {
|
2020-07-05 12:18:34 -07:00
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
2020-12-18 16:56:09 +01:00
|
|
|
$scope.catchall.availableMailboxes = result;
|
|
|
|
|
|
2020-07-05 12:18:34 -07:00
|
|
|
$scope.catchall.mailboxes = $scope.domain.mailConfig.catchAll.map(function (name) {
|
2020-12-18 16:56:09 +01:00
|
|
|
return $scope.catchall.availableMailboxes.find(function (m) { return m.name === name; });
|
2020-07-05 12:18:34 -07:00
|
|
|
}).filter(function (m) { return !!m; });
|
|
|
|
|
});
|
2018-01-22 13:01:38 -08:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-04-01 21:58:12 +02:00
|
|
|
$scope.mailinglists = {
|
|
|
|
|
busy: false,
|
2018-04-06 16:43:43 +02:00
|
|
|
mailinglists: [],
|
2019-10-22 12:47:32 +02:00
|
|
|
search: '',
|
2020-07-05 11:55:17 -07:00
|
|
|
currentPage: 1,
|
|
|
|
|
perPage: 10,
|
2018-04-01 21:58:12 +02:00
|
|
|
|
2018-04-06 16:43:43 +02:00
|
|
|
add: {
|
|
|
|
|
busy: false,
|
2019-09-11 14:09:53 -07:00
|
|
|
error: {},
|
2018-04-06 16:43:43 +02:00
|
|
|
name: '',
|
2019-09-11 14:09:53 -07:00
|
|
|
membersTxt: '',
|
2020-04-17 17:37:19 -07:00
|
|
|
membersOnly: false,
|
2018-04-06 16:43:43 +02:00
|
|
|
|
2018-04-09 16:12:18 +02:00
|
|
|
reset: function () {
|
|
|
|
|
$scope.mailinglists.add.busy = false;
|
2019-09-11 14:09:53 -07:00
|
|
|
$scope.mailinglists.add.error = {};
|
2018-04-09 16:12:18 +02:00
|
|
|
$scope.mailinglists.add.name = '';
|
2019-09-11 14:09:53 -07:00
|
|
|
$scope.mailinglists.add.membersTxt = '';
|
2018-04-09 16:12:18 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
show: function () {
|
|
|
|
|
$scope.mailinglists.add.reset();
|
|
|
|
|
$('#mailinglistAddModal').modal('show');
|
|
|
|
|
},
|
|
|
|
|
|
2018-04-06 16:43:43 +02:00
|
|
|
submit: function () {
|
|
|
|
|
$scope.mailinglists.add.busy = true;
|
2018-04-01 21:58:12 +02:00
|
|
|
|
2019-09-11 14:09:53 -07:00
|
|
|
var members = $scope.mailinglists.add.membersTxt
|
|
|
|
|
.split(/[\n,]/)
|
|
|
|
|
.map(function (m) { return m.trim(); })
|
|
|
|
|
.filter(function (m) { return m.length !== 0; });
|
2018-04-12 11:57:15 +02:00
|
|
|
|
2020-04-17 17:37:19 -07:00
|
|
|
Client.addMailingList($scope.domain.domain, $scope.mailinglists.add.name, members, $scope.mailinglists.add.membersOnly, function (error) {
|
2019-09-11 14:09:53 -07:00
|
|
|
$scope.mailinglists.add.busy = false;
|
|
|
|
|
$scope.mailinglists.add.error = {};
|
|
|
|
|
|
2018-04-06 16:43:43 +02:00
|
|
|
if (error) {
|
2019-09-11 14:09:53 -07:00
|
|
|
if (error.statusCode === 400 && error.message.indexOf('member') !== -1) {
|
|
|
|
|
$scope.mailinglists.add.error.members = error.message;
|
|
|
|
|
} else {
|
|
|
|
|
$scope.mailinglists.add.error.name = error.message;
|
|
|
|
|
}
|
2018-04-06 16:43:43 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-09 16:12:18 +02:00
|
|
|
$scope.mailinglists.add.reset();
|
2018-04-06 16:43:43 +02:00
|
|
|
$scope.mailinglists.refresh();
|
2018-04-09 16:12:18 +02:00
|
|
|
|
|
|
|
|
$('#mailinglistAddModal').modal('hide');
|
2018-04-01 21:58:12 +02:00
|
|
|
});
|
2018-04-06 16:43:43 +02:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2018-04-09 15:01:12 +02:00
|
|
|
edit: {
|
|
|
|
|
busy: false,
|
2019-09-11 14:09:53 -07:00
|
|
|
error: {},
|
2018-04-12 12:02:20 +02:00
|
|
|
name: '',
|
2019-09-11 14:09:53 -07:00
|
|
|
membersTxt: '',
|
2020-04-17 17:37:19 -07:00
|
|
|
membersOnly: false,
|
2021-04-14 22:37:59 -07:00
|
|
|
active: true,
|
2018-04-09 15:01:12 +02:00
|
|
|
|
|
|
|
|
show: function (list) {
|
2018-04-12 12:02:20 +02:00
|
|
|
$scope.mailinglists.edit.name = list.name;
|
2019-09-11 14:09:53 -07:00
|
|
|
$scope.mailinglists.edit.membersTxt = list.members.sort().join('\n');
|
2020-04-17 17:37:19 -07:00
|
|
|
$scope.mailinglists.edit.membersOnly = list.membersOnly;
|
2021-04-14 22:37:59 -07:00
|
|
|
$scope.mailinglists.edit.active = list.active;
|
2018-04-09 15:01:12 +02:00
|
|
|
|
|
|
|
|
$('#mailinglistEditModal').modal('show');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
|
$scope.mailinglists.edit.busy = true;
|
|
|
|
|
|
2019-09-11 14:09:53 -07:00
|
|
|
var members = $scope.mailinglists.edit.membersTxt.split(/[\n,]/)
|
|
|
|
|
.map(function (m) { return m.trim(); })
|
|
|
|
|
.filter(function (m) { return m.length !== 0; });
|
2018-04-12 12:02:20 +02:00
|
|
|
|
2021-04-14 22:37:59 -07:00
|
|
|
Client.updateMailingList($scope.domain.domain, $scope.mailinglists.edit.name, members, $scope.mailinglists.edit.membersOnly, $scope.mailinglists.edit.active, function (error) {
|
2018-04-09 15:01:12 +02:00
|
|
|
$scope.mailinglists.edit.busy = false;
|
2019-09-11 14:09:53 -07:00
|
|
|
$scope.mailinglists.edit.error = {};
|
2018-04-09 15:01:12 +02:00
|
|
|
|
2019-09-11 14:09:53 -07:00
|
|
|
if (error) {
|
|
|
|
|
$scope.mailinglists.edit.error.members = error.message;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-04-09 15:01:12 +02:00
|
|
|
|
2018-04-12 12:12:22 +02:00
|
|
|
$scope.mailinglists.refresh();
|
|
|
|
|
|
2018-04-09 15:01:12 +02:00
|
|
|
$('#mailinglistEditModal').modal('hide');
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2018-04-06 16:43:43 +02:00
|
|
|
remove: {
|
|
|
|
|
busy: false,
|
|
|
|
|
list: null,
|
|
|
|
|
|
|
|
|
|
show: function (list) {
|
|
|
|
|
$scope.mailinglists.remove.list = list;
|
|
|
|
|
|
|
|
|
|
$('#mailinglistRemoveModal').modal('show');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
|
$scope.mailinglists.remove.busy = true;
|
|
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
Client.removeMailingList($scope.domain.domain, $scope.mailinglists.remove.list.name, function (error) {
|
2018-04-06 16:43:43 +02:00
|
|
|
$scope.mailinglists.remove.busy = false;
|
|
|
|
|
|
|
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
|
|
|
|
$scope.mailinglists.remove.list = null;
|
|
|
|
|
$scope.mailinglists.refresh();
|
|
|
|
|
|
|
|
|
|
$('#mailinglistRemoveModal').modal('hide');
|
2018-04-01 21:58:12 +02:00
|
|
|
});
|
2018-04-06 16:43:43 +02:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2018-04-12 13:02:32 +02:00
|
|
|
refresh: function (callback) {
|
|
|
|
|
callback = typeof callback === 'function' ? callback : function (error) { if (error) return console.error(error); };
|
|
|
|
|
|
2020-07-05 11:55:17 -07:00
|
|
|
Client.listMailingLists($scope.domain.domain, $scope.mailinglists.search, $scope.mailinglists.currentPage, $scope.mailinglists.perPage, function (error, result) {
|
2018-04-12 13:02:32 +02:00
|
|
|
if (error) return callback(error);
|
2018-04-06 16:43:43 +02:00
|
|
|
|
2018-04-12 12:15:23 +02:00
|
|
|
$scope.mailinglists.mailinglists = result;
|
2018-04-12 13:02:32 +02:00
|
|
|
|
|
|
|
|
callback();
|
2018-04-01 21:58:12 +02:00
|
|
|
});
|
2020-07-05 11:55:17 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
showNextPage: function () {
|
|
|
|
|
$scope.mailinglists.currentPage++;
|
|
|
|
|
$scope.mailinglists.refresh();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
showPrevPage: function () {
|
|
|
|
|
if ($scope.mailinglists.currentPage > 1) $scope.mailinglists.currentPage--;
|
|
|
|
|
else $scope.mailinglists.currentPage = 1;
|
|
|
|
|
$scope.mailinglists.refresh();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
updateFilter: function (fresh) {
|
|
|
|
|
if (fresh) $scope.mailinglists.currentPage = 1;
|
|
|
|
|
$scope.mailinglists.refresh();
|
2018-04-01 21:58:12 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2020-02-27 10:47:14 -08:00
|
|
|
$scope.mailFromValidation = {
|
|
|
|
|
busy: false,
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
|
$scope.mailFromValidation.busy = true;
|
|
|
|
|
|
|
|
|
|
Client.setMailFromValidation($scope.domain.domain, !$scope.domain.mailConfig.mailFromValidation, function (error) {
|
|
|
|
|
if (error) {
|
|
|
|
|
$scope.mailFromValidation.busy = false;
|
|
|
|
|
return console.error(error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// give sometime for the mail container to restart
|
|
|
|
|
$timeout(function () {
|
|
|
|
|
$scope.mailFromValidation.busy = false;
|
|
|
|
|
$scope.refreshDomain();
|
|
|
|
|
}, 5000);
|
|
|
|
|
});
|
|
|
|
|
}
|
2018-05-23 23:34:09 -07:00
|
|
|
};
|
|
|
|
|
|
2020-08-24 10:16:11 -07:00
|
|
|
$scope.banner = {
|
|
|
|
|
busy: false,
|
|
|
|
|
text: '',
|
|
|
|
|
html: '',
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
|
$scope.banner.busy = true;
|
|
|
|
|
|
|
|
|
|
Client.setMailBanner($scope.domain.domain, { text: $scope.banner.text, html: $scope.banner.html }, function (error) {
|
|
|
|
|
if (error) {
|
|
|
|
|
$scope.banner.busy = false;
|
|
|
|
|
return console.error(error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// give sometime for the mail container to restart
|
|
|
|
|
$timeout(function () {
|
|
|
|
|
$scope.banner.busy = false;
|
|
|
|
|
$scope.refreshDomain();
|
|
|
|
|
}, 5000);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-07-30 11:26:26 -07:00
|
|
|
$scope.incomingEmail = {
|
|
|
|
|
busy: false,
|
2019-05-09 15:40:48 -07:00
|
|
|
setupDns: true,
|
|
|
|
|
setupDnsBusy: false,
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-07-30 11:26:26 -07:00
|
|
|
toggleEmailEnabled: function () {
|
2020-02-11 21:06:34 +01:00
|
|
|
if ($scope.domain.mailConfig.enabled) {
|
2018-07-30 11:26:26 -07:00
|
|
|
$('#disableEmailModal').modal('show');
|
|
|
|
|
} else {
|
|
|
|
|
$('#enableEmailModal').modal('show');
|
|
|
|
|
}
|
|
|
|
|
},
|
2018-05-29 17:17:53 +02:00
|
|
|
|
2019-05-09 15:40:48 -07:00
|
|
|
setDnsRecords: function (callback) {
|
|
|
|
|
$scope.incomingEmail.setupDnsBusy = true;
|
|
|
|
|
|
2021-02-24 22:00:05 -08:00
|
|
|
Client.setDnsRecords({ domain: $scope.domain.domain, type: 'mail' }, function (error) {
|
2019-05-09 15:40:48 -07:00
|
|
|
if (error) console.error(error);
|
|
|
|
|
|
|
|
|
|
$timeout(function () { $scope.incomingEmail.setupDnsBusy = false; }, 2000); // otherwise, it's too fast
|
|
|
|
|
|
|
|
|
|
if (callback) callback();
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
2018-07-30 11:26:26 -07:00
|
|
|
enable: function () {
|
|
|
|
|
$('#enableEmailModal').modal('hide');
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-07-30 11:26:26 -07:00
|
|
|
$scope.incomingEmail.busy = true;
|
2018-07-25 10:51:58 -07:00
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
Client.enableMailForDomain($scope.domain.domain, true , function (error) {
|
2018-07-25 10:51:58 -07:00
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
2018-08-12 13:13:52 -07:00
|
|
|
$scope.reconfigureEmailApps();
|
|
|
|
|
|
2019-05-09 15:40:48 -07:00
|
|
|
let maybeSetupDns = $scope.incomingEmail.setupDns ? $scope.incomingEmail.setDnsRecords : function (next) { next(); };
|
|
|
|
|
|
|
|
|
|
maybeSetupDns(function (error) {
|
2018-07-30 11:26:26 -07:00
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
2020-05-26 17:01:38 -07:00
|
|
|
$timeout(function () {
|
|
|
|
|
$scope.refreshDomain();
|
|
|
|
|
$scope.incomingEmail.busy = false;
|
|
|
|
|
}, 5000); // wait for mail container to restart. it cannot get IP otherwise while refreshing
|
2018-07-30 11:26:26 -07:00
|
|
|
});
|
2018-07-25 10:51:58 -07:00
|
|
|
});
|
2018-07-30 11:26:26 -07:00
|
|
|
},
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-07-30 11:26:26 -07:00
|
|
|
disable: function () {
|
|
|
|
|
$('#disableEmailModal').modal('hide');
|
2018-05-06 23:36:40 -07:00
|
|
|
|
2018-07-30 11:26:26 -07:00
|
|
|
$scope.incomingEmail.busy = true;
|
|
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
Client.enableMailForDomain($scope.domain.domain, false , function (error) {
|
2018-07-30 11:26:26 -07:00
|
|
|
if (error) return console.error(error);
|
2018-08-12 13:13:52 -07:00
|
|
|
|
|
|
|
|
$scope.reconfigureEmailApps();
|
2020-05-26 17:01:38 -07:00
|
|
|
|
|
|
|
|
$timeout(function () {
|
|
|
|
|
$scope.refreshDomain();
|
|
|
|
|
$scope.incomingEmail.busy = false;
|
|
|
|
|
}, 5000); // wait for mail container to restart. it cannot get IP otherwise while refreshing
|
2018-07-30 11:26:26 -07:00
|
|
|
});
|
|
|
|
|
}
|
2018-01-22 13:01:38 -08:00
|
|
|
};
|
|
|
|
|
|
2022-01-23 22:26:23 +01:00
|
|
|
$scope.mailboxImport = {
|
|
|
|
|
busy: false,
|
|
|
|
|
done: false,
|
|
|
|
|
error: null,
|
|
|
|
|
percent: 0,
|
|
|
|
|
success: 0,
|
|
|
|
|
mailboxes: [],
|
|
|
|
|
|
|
|
|
|
reset: function () {
|
|
|
|
|
$scope.mailboxImport.busy = false;
|
|
|
|
|
$scope.mailboxImport.error = null;
|
|
|
|
|
$scope.mailboxImport.mailboxes = [];
|
|
|
|
|
$scope.mailboxImport.percent = 0;
|
|
|
|
|
$scope.mailboxImport.success = 0;
|
|
|
|
|
$scope.mailboxImport.done = false;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handleFileChanged: function () {
|
|
|
|
|
$scope.mailboxImport.reset();
|
|
|
|
|
|
|
|
|
|
var fileInput = document.getElementById('mailboxImportFileInput');
|
|
|
|
|
if (!fileInput.files || !fileInput.files[0]) return;
|
|
|
|
|
|
|
|
|
|
var file = fileInput.files[0];
|
2022-02-17 17:50:47 -08:00
|
|
|
if (file.type !== 'application/json' && file.type !== 'text/csv') return console.log('Unsupported file type.');
|
2022-01-23 22:26:23 +01:00
|
|
|
|
|
|
|
|
const reader = new FileReader();
|
|
|
|
|
reader.addEventListener('load', function () {
|
|
|
|
|
$scope.$apply(function () {
|
2022-02-17 17:50:47 -08:00
|
|
|
$scope.mailboxImport.mailboxes = [];
|
|
|
|
|
var mailboxes = [];
|
|
|
|
|
|
|
|
|
|
if (file.type === 'text/csv') {
|
|
|
|
|
var lines = reader.result.split('\n');
|
|
|
|
|
if (lines.length === 0) return $scope.mailboxImport.error = { file: 'Imported file has no lines' };
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < lines.length; i++) {
|
|
|
|
|
var line = lines[i].trim();
|
|
|
|
|
if (!line) continue;
|
|
|
|
|
var items = line.split(',');
|
|
|
|
|
if (items.length !== 4) {
|
|
|
|
|
$scope.mailboxImport.error = { file: 'Line ' + (i+1) + ' has wrong column count. Expecting 4' };
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
mailboxes.push({
|
|
|
|
|
name: items[0].trim(),
|
|
|
|
|
domain: items[1].trim(),
|
|
|
|
|
owner: items[2].trim(),
|
|
|
|
|
ownerType: items[3].trim(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
try {
|
|
|
|
|
mailboxes = JSON.parse(reader.result).map(function (mailbox) {
|
|
|
|
|
return {
|
|
|
|
|
name: mailbox.name,
|
|
|
|
|
domain: mailbox.domain,
|
|
|
|
|
owner: mailbox.owner,
|
|
|
|
|
ownerType: mailbox.ownerType
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error('Failed to parse mailboxes.', e);
|
|
|
|
|
$scope.mailboxImport.error = { file: 'Imported file is not valid JSON' };
|
|
|
|
|
}
|
2022-01-23 22:26:23 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-17 17:50:47 -08:00
|
|
|
$scope.mailboxImport.mailboxes = mailboxes;
|
2022-01-23 22:26:23 +01:00
|
|
|
});
|
|
|
|
|
}, false);
|
|
|
|
|
reader.readAsText(file);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
show: function () {
|
|
|
|
|
$scope.mailboxImport.reset();
|
|
|
|
|
|
|
|
|
|
// named so no duplactes
|
|
|
|
|
document.getElementById('mailboxImportFileInput').addEventListener('change', $scope.mailboxImport.handleFileChanged);
|
|
|
|
|
|
|
|
|
|
$('#mailboxImportModal').modal('show');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
openFileInput: function () {
|
|
|
|
|
$('#mailboxImportFileInput').click();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
import: function () {
|
|
|
|
|
$scope.mailboxImport.percent = 0;
|
|
|
|
|
$scope.mailboxImport.success = 0;
|
|
|
|
|
$scope.mailboxImport.done = false;
|
|
|
|
|
$scope.mailboxImport.error = { import: [] };
|
|
|
|
|
$scope.mailboxImport.busy = true;
|
|
|
|
|
|
|
|
|
|
var processed = 0;
|
|
|
|
|
|
|
|
|
|
async.eachSeries($scope.mailboxImport.mailboxes, function (mailbox, callback) {
|
2022-02-17 17:50:47 -08:00
|
|
|
var owner = $scope.owners.find(function (o) { return o.display === mailbox.owner && o.type === mailbox.ownerType; }); // owner may not exist
|
|
|
|
|
if (!owner) {
|
|
|
|
|
$scope.mailboxImport.error.import.push({ error: new Error('Could not detect owner'), mailbox: mailbox });
|
|
|
|
|
++processed;
|
|
|
|
|
$scope.mailboxImport.percent = 100 * processed / $scope.mailboxImport.mailboxes.length;
|
|
|
|
|
return callback();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Client.addMailbox(mailbox.domain, mailbox.name, owner.id, mailbox.ownerType, function (error) {
|
2022-01-23 22:26:23 +01:00
|
|
|
if (error) $scope.mailboxImport.error.import.push({ error: error, mailbox: mailbox });
|
|
|
|
|
else ++$scope.mailboxImport.success;
|
|
|
|
|
|
|
|
|
|
++processed;
|
|
|
|
|
$scope.mailboxImport.percent = 100 * processed / $scope.mailboxImport.mailboxes.length;
|
|
|
|
|
|
|
|
|
|
callback();
|
|
|
|
|
});
|
|
|
|
|
}, function (error) {
|
|
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
|
|
|
|
$scope.mailboxImport.busy = false;
|
|
|
|
|
$scope.mailboxImport.done = true;
|
2022-02-17 17:50:47 -08:00
|
|
|
if ($scope.mailboxImport.success) $scope.mailboxes.refresh();
|
2022-01-23 22:26:23 +01:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2022-02-17 16:37:48 -08:00
|
|
|
$scope.mailboxExport = function (type) {
|
2022-01-23 22:26:23 +01:00
|
|
|
// FIXME only does first 10k mailboxes
|
|
|
|
|
Client.listMailboxes($scope.domain.domain, '', 1, 10000, function (error, result) {
|
|
|
|
|
if (error) {
|
|
|
|
|
Client.error('Failed to list mailboxes. Full error in the webinspector.');
|
|
|
|
|
return console.error('Failed to list mailboxes.', error);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-17 16:37:48 -08:00
|
|
|
var content = '';
|
|
|
|
|
|
|
|
|
|
if (type === 'json') {
|
|
|
|
|
content = JSON.stringify(result.map(function (mailbox) {
|
|
|
|
|
var owner = $scope.owners.find(function (o) { return o.id === mailbox.ownerId; }); // owner may not exist
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
name: mailbox.name,
|
|
|
|
|
domain: mailbox.domain,
|
|
|
|
|
owner: owner ? owner.display : '', // this meta property is set when we get the user list
|
|
|
|
|
ownerType: owner ? owner.type : '',
|
|
|
|
|
active: mailbox.active,
|
|
|
|
|
aliases: mailbox.aliases
|
|
|
|
|
};
|
|
|
|
|
}), null, 2);
|
|
|
|
|
} else if (type === 'csv') {
|
|
|
|
|
content = result.map(function (mailbox) {
|
|
|
|
|
var owner = $scope.owners.find(function (o) { return o.id === mailbox.ownerId; }); // owner may not exist
|
|
|
|
|
|
|
|
|
|
var aliases = mailbox.aliases.map(function (a) { return a.name + '@' + a.domain; }).join(' ');
|
|
|
|
|
return [ mailbox.name, mailbox.domain, owner ? owner.display : '', owner ? owner.type : '', aliases, mailbox.active ].join(',');
|
|
|
|
|
}).join('\n');
|
|
|
|
|
} else {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-02-16 23:10:10 -08:00
|
|
|
|
2022-02-17 16:37:48 -08:00
|
|
|
var file = new Blob([ content ], { type: type === 'json' ? 'application/json' : 'text/csv' });
|
2022-01-23 22:26:23 +01:00
|
|
|
var a = document.createElement('a');
|
|
|
|
|
a.href = URL.createObjectURL(file);
|
2022-02-17 16:37:48 -08:00
|
|
|
a.download = $scope.domain.domain.replaceAll('.','_') + '-mailboxes.' + type;
|
2022-01-23 22:26:23 +01:00
|
|
|
document.body.appendChild(a);
|
|
|
|
|
a.click();
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2018-03-30 18:06:40 +02:00
|
|
|
$scope.mailboxes = {
|
2018-04-05 21:00:33 +02:00
|
|
|
mailboxes: [],
|
2019-10-22 12:47:32 +02:00
|
|
|
search: '',
|
2020-07-05 12:18:34 -07:00
|
|
|
currentPage: 1,
|
|
|
|
|
perPage: 10,
|
2018-04-06 16:51:57 +02:00
|
|
|
|
2018-04-05 21:00:33 +02:00
|
|
|
add: {
|
2018-04-09 15:56:20 +02:00
|
|
|
error: null,
|
2018-04-05 21:00:33 +02:00
|
|
|
busy: false,
|
|
|
|
|
name: '',
|
|
|
|
|
owner: null,
|
|
|
|
|
|
2018-04-09 15:56:20 +02:00
|
|
|
reset: function () {
|
|
|
|
|
$scope.mailboxes.add.busy = false;
|
|
|
|
|
$scope.mailboxes.add.error = null;
|
|
|
|
|
$scope.mailboxes.add.name = '';
|
|
|
|
|
$scope.mailboxes.add.owner = null;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
show: function () {
|
2020-07-16 18:51:29 +02:00
|
|
|
if ($scope.config.features.mailboxMaxCount && $scope.config.features.mailboxMaxCount <= $scope.mailboxes.mailboxes.length) {
|
|
|
|
|
$('#subscriptionRequiredModal').modal('show');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-09 15:56:20 +02:00
|
|
|
$scope.mailboxes.add.reset();
|
|
|
|
|
$('#mailboxAddModal').modal('show');
|
|
|
|
|
},
|
|
|
|
|
|
2018-04-05 21:00:33 +02:00
|
|
|
submit: function () {
|
|
|
|
|
$scope.mailboxes.add.busy = true;
|
|
|
|
|
|
2020-11-12 23:53:02 -08:00
|
|
|
Client.addMailbox($scope.domain.domain, $scope.mailboxes.add.name, $scope.mailboxes.add.owner.id, $scope.mailboxes.add.owner.type, function (error) {
|
2018-04-06 16:51:57 +02:00
|
|
|
if (error) {
|
2018-04-09 15:56:20 +02:00
|
|
|
$scope.mailboxes.add.busy = false;
|
2018-04-09 16:21:32 +02:00
|
|
|
$scope.mailboxes.add.error = error;
|
2018-04-06 16:51:57 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-28 17:48:11 -07:00
|
|
|
$scope.mailboxes.refresh();
|
|
|
|
|
$scope.catchall.refresh();
|
2018-04-12 13:02:32 +02:00
|
|
|
|
2020-03-28 17:48:11 -07:00
|
|
|
$('#mailboxAddModal').modal('hide');
|
2018-04-05 21:00:33 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2018-04-09 12:42:14 +02:00
|
|
|
edit: {
|
|
|
|
|
busy: false,
|
|
|
|
|
error: null,
|
2018-04-12 12:26:51 +02:00
|
|
|
name: '',
|
|
|
|
|
owner: null,
|
2020-04-19 19:44:45 -07:00
|
|
|
incomingDomains: [],
|
|
|
|
|
aliases: [],
|
2021-04-14 22:37:59 -07:00
|
|
|
active: true,
|
2021-10-08 10:20:17 -07:00
|
|
|
enablePop3: false,
|
2020-04-19 19:44:45 -07:00
|
|
|
|
|
|
|
|
addAlias: function (event) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
|
|
$scope.mailboxes.edit.aliases.push({
|
|
|
|
|
name: '',
|
2021-12-15 16:06:22 +01:00
|
|
|
domain: domainName,
|
|
|
|
|
reversedSortingNotation: 'z'.repeat(100) // quick and dirty to ensure newly added are on bottom
|
2020-04-19 19:44:45 -07:00
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
delAlias: function (event, index) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
$scope.mailboxes.edit.aliases.splice(index, 1);
|
|
|
|
|
},
|
2018-04-09 12:42:14 +02:00
|
|
|
|
|
|
|
|
show: function (mailbox) {
|
2018-04-12 12:26:51 +02:00
|
|
|
$scope.mailboxes.edit.name = mailbox.name;
|
2019-01-10 13:31:49 -08:00
|
|
|
$scope.mailboxes.edit.owner = mailbox.owner; // this can be null if mailbox had no owner
|
2021-12-15 16:06:22 +01:00
|
|
|
$scope.mailboxes.edit.aliases = angular.copy(mailbox.aliases, []).map(function (a) { a.reversedSortingNotation = a.domain + '@' + a.name; return a; });
|
2021-04-14 22:37:59 -07:00
|
|
|
$scope.mailboxes.edit.active = mailbox.active;
|
2021-10-08 10:20:17 -07:00
|
|
|
$scope.mailboxes.edit.enablePop3 = mailbox.enablePop3;
|
2018-04-09 12:42:14 +02:00
|
|
|
|
|
|
|
|
$('#mailboxEditModal').modal('show');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
2018-04-09 15:01:12 +02:00
|
|
|
$scope.mailboxes.edit.busy = true;
|
2018-04-09 12:42:14 +02:00
|
|
|
|
2021-10-08 10:20:17 -07:00
|
|
|
var data = {
|
|
|
|
|
ownerId: $scope.mailboxes.edit.owner.id,
|
|
|
|
|
ownerType: $scope.mailboxes.edit.owner.type,
|
|
|
|
|
active: $scope.mailboxes.edit.active,
|
|
|
|
|
enablePop3: $scope.mailboxes.edit.enablePop3
|
|
|
|
|
};
|
|
|
|
|
|
2019-01-10 13:31:49 -08:00
|
|
|
// $scope.mailboxes.edit.owner is expected to be validated by the UI
|
2021-10-08 10:20:17 -07:00
|
|
|
Client.updateMailbox($scope.domain.domain, $scope.mailboxes.edit.name, data, function (error) {
|
2018-04-09 12:42:14 +02:00
|
|
|
if (error) {
|
|
|
|
|
$scope.mailboxes.edit.error = error;
|
|
|
|
|
$scope.mailboxes.edit.busy = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-20 19:09:25 -07:00
|
|
|
Client.setAliases($scope.mailboxes.edit.name, $scope.domain.domain, $scope.mailboxes.edit.aliases, function (error) {
|
2018-04-09 12:42:14 +02:00
|
|
|
if (error) {
|
|
|
|
|
$scope.mailboxes.edit.error = error;
|
|
|
|
|
$scope.mailboxes.edit.busy = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$scope.mailboxes.edit.busy = false;
|
|
|
|
|
$scope.mailboxes.edit.error = null;
|
2018-04-12 12:26:51 +02:00
|
|
|
$scope.mailboxes.edit.name = '';
|
|
|
|
|
$scope.mailboxes.edit.owner = null;
|
2020-04-19 19:44:45 -07:00
|
|
|
$scope.mailboxes.edit.aliases = [];
|
2018-04-09 12:42:14 +02:00
|
|
|
$scope.mailboxes.refresh();
|
|
|
|
|
|
|
|
|
|
$('#mailboxEditModal').modal('hide');
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2018-04-05 21:22:07 +02:00
|
|
|
remove: {
|
|
|
|
|
busy: false,
|
|
|
|
|
mailbox: null,
|
2020-07-27 22:36:38 -07:00
|
|
|
deleteMails: true,
|
2018-04-05 21:22:07 +02:00
|
|
|
|
|
|
|
|
show: function (mailbox) {
|
|
|
|
|
$scope.mailboxes.remove.mailbox = mailbox;
|
|
|
|
|
|
|
|
|
|
$('#mailboxRemoveModal').modal('show');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
|
$scope.mailboxes.remove.busy = true;
|
|
|
|
|
|
2020-07-27 22:36:38 -07:00
|
|
|
Client.removeMailbox($scope.domain.domain, $scope.mailboxes.remove.mailbox.name, $scope.mailboxes.remove.deleteMails, function (error) {
|
2018-04-05 21:22:07 +02:00
|
|
|
$scope.mailboxes.remove.busy = false;
|
|
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
|
|
|
|
$scope.mailboxes.remove.mailbox = null;
|
2018-04-12 13:02:32 +02:00
|
|
|
$scope.mailboxes.refresh(function (error) {
|
|
|
|
|
if (error) return console.error(error);
|
|
|
|
|
|
|
|
|
|
$scope.catchall.refresh();
|
2018-04-05 21:22:07 +02:00
|
|
|
|
2018-04-12 13:02:32 +02:00
|
|
|
$('#mailboxRemoveModal').modal('hide');
|
|
|
|
|
});
|
2018-04-05 21:22:07 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2018-04-12 13:02:32 +02:00
|
|
|
refresh: function (callback) {
|
|
|
|
|
callback = typeof callback === 'function' ? callback : function (error) { if (error) return console.error(error); };
|
|
|
|
|
|
2021-01-07 21:40:51 -08:00
|
|
|
Client.listMailboxes($scope.domain.domain, $scope.mailboxes.search, $scope.mailboxes.currentPage, $scope.mailboxes.perPage, function (error, mailboxes) {
|
2018-04-12 13:02:32 +02:00
|
|
|
if (error) return callback(error);
|
2018-04-05 21:00:33 +02:00
|
|
|
|
2021-01-07 21:40:51 -08:00
|
|
|
mailboxes.forEach(function (m) {
|
|
|
|
|
m.owner = $scope.owners.find(function (o) { return o.id === m.ownerId; }); // owner may not exist
|
|
|
|
|
m.ownerDisplayName = m.owner ? m.owner.display : ''; // this meta property is set when we get the user list
|
2018-04-05 21:00:33 +02:00
|
|
|
|
2021-01-07 21:40:51 -08:00
|
|
|
var u = $scope.diskUsage[m.name + '@' + m.domain]; // this is unset when no emails have been received yet
|
|
|
|
|
m.usage = (u && u.size) || 0;
|
|
|
|
|
});
|
2018-04-12 13:02:32 +02:00
|
|
|
|
2021-01-07 21:40:51 -08:00
|
|
|
$scope.mailboxes.mailboxes = mailboxes;
|
2020-07-05 12:18:34 -07:00
|
|
|
|
2021-01-07 21:40:51 -08:00
|
|
|
callback();
|
2018-04-05 21:00:33 +02:00
|
|
|
});
|
2020-07-05 12:18:34 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
showNextPage: function () {
|
|
|
|
|
$scope.mailboxes.currentPage++;
|
|
|
|
|
$scope.mailboxes.refresh();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
showPrevPage: function () {
|
|
|
|
|
if ($scope.mailboxes.currentPage > 1) $scope.mailboxes.currentPage--;
|
|
|
|
|
else $scope.mailboxes.currentPage = 1;
|
|
|
|
|
$scope.mailboxes.refresh();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
updateFilter: function (fresh) {
|
|
|
|
|
if (fresh) $scope.mailboxes.currentPage = 1;
|
|
|
|
|
$scope.mailboxes.refresh();
|
2018-03-30 18:06:40 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.mailRelayPresets = [
|
|
|
|
|
{ provider: 'cloudron-smtp', name: 'Built-in SMTP server' },
|
|
|
|
|
{ provider: 'external-smtp', name: 'External SMTP server', host: '', port: 587 },
|
2019-04-22 16:49:59 -07:00
|
|
|
{ provider: 'external-smtp-noauth', name: 'External SMTP server (No Authentication)', host: '', port: 587 },
|
2019-08-02 12:42:10 -07:00
|
|
|
{ provider: 'ses-smtp', name: 'Amazon SES', host: 'email-smtp.us-east-1.amazonaws.com', port: 587, spfDoc: 'https://docs.aws.amazon.com/ses/latest/DeveloperGuide/spf.html' },
|
2020-11-19 11:12:46 -08:00
|
|
|
{ provider: 'elasticemail-smtp', name: 'Elastic Email', host: 'smtp.elasticemail.com', port: 587, spfDoc: 'https://elasticemail.com/blog/marketing_tips/common-spf-errors' },
|
2019-08-02 12:42:10 -07:00
|
|
|
{ provider: 'google-smtp', name: 'Google', host: 'smtp.gmail.com', port: 587, spfDoc: 'https://support.google.com/a/answer/33786?hl=en' },
|
|
|
|
|
{ provider: 'mailgun-smtp', name: 'Mailgun', host: 'smtp.mailgun.org', port: 587, spfDoc: 'https://www.mailgun.com/blog/white-labeling-dns-records-your-customers-tips-tricks' },
|
|
|
|
|
{ provider: 'mailjet-smtp', name: 'Mailjet', host: '', port: 587, spfDoc: 'https://app.mailjet.com/docs/spf-dkim-guide' },
|
|
|
|
|
{ provider: 'postmark-smtp', name: 'Postmark', host: 'smtp.postmarkapp.com', port: 587, spfDoc: 'https://postmarkapp.com/support/article/1092-how-do-i-set-up-spf-for-postmark' },
|
|
|
|
|
{ provider: 'sendgrid-smtp', name: 'SendGrid', host: 'smtp.sendgrid.net', port: 587, username: 'apikey', spfDoc: 'https://sendgrid.com/docs/ui/account-and-settings/spf-records/' },
|
|
|
|
|
{ provider: 'sparkpost-smtp', name: 'SparkPost', host: 'smtp.sparkpostmail.com', port: 587, username: 'SMTP_Injection', spfDoc: 'https://www.sparkpost.com/resources/email-explained/spf-sender-policy-framework/' },
|
2019-03-15 11:16:43 -07:00
|
|
|
{ provider: 'noop', name: 'Disable' },
|
2018-01-22 13:01:38 -08:00
|
|
|
];
|
|
|
|
|
|
2019-04-22 16:49:59 -07:00
|
|
|
$scope.usesTokenAuth = function (provider) {
|
2019-07-15 10:49:13 -07:00
|
|
|
return provider === 'postmark-smtp' || provider === 'sendgrid-smtp' || provider === 'sparkpost-smtp';
|
2019-04-22 16:49:59 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.usesExternalServer = function (provider) {
|
|
|
|
|
return provider !== 'cloudron-smtp' && provider !== 'noop';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$scope.usesPasswordAuth = function (provider) {
|
|
|
|
|
return provider === 'external-smtp'
|
|
|
|
|
|| provider === 'ses-smtp'
|
|
|
|
|
|| provider === 'google-smtp'
|
|
|
|
|
|| provider === 'mailgun-smtp'
|
2020-11-19 11:12:46 -08:00
|
|
|
|| provider === 'elasticemail-smtp'
|
2019-04-22 16:49:59 -07:00
|
|
|
|| provider === 'mailjet-smtp';
|
|
|
|
|
};
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.mailRelay = {
|
|
|
|
|
error: null,
|
|
|
|
|
success: false,
|
|
|
|
|
busy: false,
|
|
|
|
|
preset: $scope.mailRelayPresets[0],
|
|
|
|
|
|
2020-08-24 10:16:11 -07:00
|
|
|
// form data to be set on load
|
|
|
|
|
relay: {
|
|
|
|
|
provider: 'cloudron-smtp',
|
|
|
|
|
host: '',
|
|
|
|
|
port: 25,
|
|
|
|
|
username: '',
|
|
|
|
|
password: '',
|
|
|
|
|
serverApiToken: '',
|
|
|
|
|
acceptSelfSignedCerts: false
|
|
|
|
|
},
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
presetChanged: function () {
|
|
|
|
|
$scope.mailRelay.error = null;
|
|
|
|
|
|
|
|
|
|
$scope.mailRelay.relay.provider = $scope.mailRelay.preset.provider;
|
|
|
|
|
$scope.mailRelay.relay.host = $scope.mailRelay.preset.host;
|
|
|
|
|
$scope.mailRelay.relay.port = $scope.mailRelay.preset.port;
|
|
|
|
|
$scope.mailRelay.relay.username = '';
|
|
|
|
|
$scope.mailRelay.relay.password = '';
|
|
|
|
|
$scope.mailRelay.relay.serverApiToken = '';
|
2019-04-23 15:24:31 -07:00
|
|
|
$scope.mailRelay.relay.acceptSelfSignedCerts = false;
|
2018-01-22 13:01:38 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
submit: function () {
|
|
|
|
|
$scope.mailRelay.error = null;
|
|
|
|
|
$scope.mailRelay.busy = true;
|
|
|
|
|
$scope.mailRelay.success = false;
|
|
|
|
|
|
|
|
|
|
var data = {
|
|
|
|
|
provider: $scope.mailRelay.relay.provider,
|
|
|
|
|
host: $scope.mailRelay.relay.host,
|
2019-04-23 15:24:31 -07:00
|
|
|
port: $scope.mailRelay.relay.port,
|
2021-10-16 21:47:28 -07:00
|
|
|
acceptSelfSignedCerts: $scope.mailRelay.relay.acceptSelfSignedCerts,
|
|
|
|
|
forceFromAddress: false
|
2018-01-22 13:01:38 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// fill in provider specific username/password usage
|
|
|
|
|
if (data.provider === 'postmark-smtp') {
|
|
|
|
|
data.username = $scope.mailRelay.relay.serverApiToken;
|
|
|
|
|
data.password = $scope.mailRelay.relay.serverApiToken;
|
2021-10-16 21:47:28 -07:00
|
|
|
data.forceFromAddress = true; // postmark requires the "From:" in mail to be a Sender Signature
|
2018-01-22 13:01:38 -08:00
|
|
|
} else if (data.provider === 'sendgrid-smtp') {
|
|
|
|
|
data.username = 'apikey';
|
|
|
|
|
data.password = $scope.mailRelay.relay.serverApiToken;
|
2019-07-15 10:49:13 -07:00
|
|
|
} else if (data.provider === 'sparkpost-smtp') {
|
|
|
|
|
data.username = 'SMTP_Injection';
|
|
|
|
|
data.password = $scope.mailRelay.relay.serverApiToken;
|
2018-01-22 13:01:38 -08:00
|
|
|
} else {
|
|
|
|
|
data.username = $scope.mailRelay.relay.username;
|
|
|
|
|
data.password = $scope.mailRelay.relay.password;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
Client.setMailRelay($scope.domain.domain, data, function (error) {
|
2018-01-22 13:01:38 -08:00
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
$scope.mailRelay.error = error.message;
|
2020-02-27 10:42:30 -08:00
|
|
|
$scope.mailRelay.busy = false;
|
2018-01-22 13:01:38 -08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
$scope.domain.relay = data;
|
2018-01-23 12:30:35 +01:00
|
|
|
|
2020-02-27 10:42:30 -08:00
|
|
|
// let the mail server restart, otherwise we get "Error getting IP" errors during refresh
|
|
|
|
|
$timeout(function () {
|
|
|
|
|
$scope.mailRelay.busy = false;
|
|
|
|
|
$scope.mailRelay.success = true;
|
|
|
|
|
$scope.refreshDomain();
|
|
|
|
|
|
|
|
|
|
// clear success indicator after 5sec
|
|
|
|
|
$timeout(function () { $scope.mailRelay.success = false; }, 5000);
|
|
|
|
|
}, 5000);
|
|
|
|
|
|
2018-01-22 13:01:38 -08:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-05-06 23:47:38 -07:00
|
|
|
function resetDnsRecords() {
|
2018-01-23 12:30:35 +01:00
|
|
|
$scope.expectedDnsRecordsTypes.forEach(function (record) {
|
|
|
|
|
var type = record.value;
|
2018-05-06 23:47:38 -07:00
|
|
|
$scope.expectedDnsRecords[type] = {};
|
|
|
|
|
|
2018-01-23 12:30:35 +01:00
|
|
|
$('#collapse_dns_' + type).collapse('hide');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$('#collapse_outbound_smtp').collapse('hide');
|
|
|
|
|
$('#collapse_rbl').collapse('hide');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function showExpectedDnsRecords() {
|
|
|
|
|
// open the record details if they are not correct
|
|
|
|
|
$scope.expectedDnsRecordsTypes.forEach(function (record) {
|
|
|
|
|
var type = record.value;
|
2020-02-11 21:06:34 +01:00
|
|
|
$scope.expectedDnsRecords[type] = $scope.domain.mailStatus.dns[type] || {};
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-01-23 12:30:35 +01:00
|
|
|
if (!$scope.expectedDnsRecords[type].status) {
|
|
|
|
|
$('#collapse_dns_' + type).collapse('show');
|
|
|
|
|
}
|
2018-01-22 13:01:38 -08:00
|
|
|
});
|
2018-01-23 12:30:35 +01:00
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
if (!$scope.domain.mailStatus.relay.status) {
|
2018-01-23 12:30:35 +01:00
|
|
|
$('#collapse_outbound_smtp').collapse('show');
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
if (!$scope.domain.mailStatus.rbl.status) {
|
2018-01-23 12:30:35 +01:00
|
|
|
$('#collapse_rbl').collapse('show');
|
|
|
|
|
}
|
2018-01-22 13:01:38 -08:00
|
|
|
}
|
|
|
|
|
|
2018-04-09 18:00:08 +02:00
|
|
|
$scope.selectDomain = function () {
|
2020-02-11 21:06:34 +01:00
|
|
|
$location.path('/email/' + $scope.domain.domain, false);
|
2018-04-09 18:00:08 +02:00
|
|
|
};
|
|
|
|
|
|
2020-09-08 19:34:27 -07:00
|
|
|
// this is required because we need to rewrite the CLOUDRON_MAIL_SERVER_HOST env var
|
2018-08-12 13:13:52 -07:00
|
|
|
$scope.reconfigureEmailApps = function () {
|
|
|
|
|
var installedApps = Client.getInstalledApps();
|
|
|
|
|
for (var i = 0; i < installedApps.length; i++) {
|
|
|
|
|
if (!installedApps[i].manifest.addons.email) continue;
|
|
|
|
|
|
2019-10-04 11:20:27 -07:00
|
|
|
Client.repairApp(installedApps[i].id, { }, function (error) {
|
2018-08-12 13:13:52 -07:00
|
|
|
if (error) console.error(error);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-01-23 12:30:35 +01:00
|
|
|
$scope.refreshDomain = function () {
|
|
|
|
|
$scope.refreshBusy = true;
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-05-06 23:47:38 -07:00
|
|
|
resetDnsRecords();
|
2018-01-23 12:30:35 +01:00
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
Client.getMailConfigForDomain(domainName, function (error, mailConfig) {
|
2022-02-17 17:54:44 +01:00
|
|
|
if (error && error.statusCode === 404) return $location.path('/email');
|
2018-01-23 12:30:35 +01:00
|
|
|
if (error) {
|
|
|
|
|
$scope.refreshBusy = false;
|
|
|
|
|
return console.error(error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pre-fill the form
|
|
|
|
|
$scope.mailRelay.relay.provider = mailConfig.relay.provider;
|
|
|
|
|
$scope.mailRelay.relay.host = mailConfig.relay.host;
|
|
|
|
|
$scope.mailRelay.relay.port = mailConfig.relay.port;
|
2019-04-23 15:24:31 -07:00
|
|
|
$scope.mailRelay.relay.acceptSelfSignedCerts = !!mailConfig.relay.acceptSelfSignedCerts;
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.mailRelay.relay.username = '';
|
|
|
|
|
$scope.mailRelay.relay.password = '';
|
|
|
|
|
$scope.mailRelay.relay.serverApiToken = '';
|
|
|
|
|
|
2018-01-23 12:30:35 +01:00
|
|
|
if (mailConfig.relay.provider === 'postmark-smtp') {
|
|
|
|
|
$scope.mailRelay.relay.serverApiToken = mailConfig.relay.username;
|
|
|
|
|
} else if (mailConfig.relay.provider === 'sendgrid-smtp') {
|
|
|
|
|
$scope.mailRelay.relay.serverApiToken = mailConfig.relay.password;
|
2019-07-15 10:49:13 -07:00
|
|
|
} else if (mailConfig.relay.provider === 'sparkpost-smtp') {
|
|
|
|
|
$scope.mailRelay.relay.serverApiToken = mailConfig.relay.password;
|
2018-01-22 13:01:38 -08:00
|
|
|
} else {
|
2018-01-23 12:30:35 +01:00
|
|
|
$scope.mailRelay.relay.username = mailConfig.relay.username;
|
|
|
|
|
$scope.mailRelay.relay.password = mailConfig.relay.password;
|
2018-01-22 13:01:38 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < $scope.mailRelayPresets.length; i++) {
|
2018-01-23 12:30:35 +01:00
|
|
|
if ($scope.mailRelayPresets[i].provider === mailConfig.relay.provider) {
|
2018-01-22 13:01:38 -08:00
|
|
|
$scope.mailRelay.preset = $scope.mailRelayPresets[i];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-24 10:16:11 -07:00
|
|
|
$scope.banner.text = mailConfig.banner.text || '';
|
|
|
|
|
$scope.banner.html = mailConfig.banner.html || '';
|
|
|
|
|
|
2018-01-23 12:41:52 +01:00
|
|
|
// amend to selected domain to be available for the UI
|
2020-02-11 21:06:34 +01:00
|
|
|
$scope.domain.mailConfig = mailConfig;
|
|
|
|
|
$scope.domain.mailStatus = {};
|
2018-01-23 12:41:52 +01:00
|
|
|
|
2020-07-05 12:18:34 -07:00
|
|
|
Client.getMailUsage($scope.domain.domain, function (error, usage) {
|
2018-04-12 13:02:32 +02:00
|
|
|
if (error) console.error(error);
|
|
|
|
|
|
2020-07-05 12:18:34 -07:00
|
|
|
$scope.diskUsage = usage || {}; // if mail server is down, don't stop the listing
|
|
|
|
|
|
|
|
|
|
$scope.mailboxes.refresh(); // relies on disk usage
|
2018-04-12 13:02:32 +02:00
|
|
|
$scope.mailinglists.refresh();
|
|
|
|
|
$scope.catchall.refresh();
|
|
|
|
|
});
|
2018-04-01 21:58:12 +02:00
|
|
|
|
2018-01-23 12:41:52 +01:00
|
|
|
// we will fetch the status without blocking the ui
|
2020-02-11 21:06:34 +01:00
|
|
|
Client.getMailStatusForDomain($scope.domain.domain, function (error, mailStatus) {
|
2018-01-23 12:41:52 +01:00
|
|
|
$scope.refreshBusy = false;
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-01-23 12:41:52 +01:00
|
|
|
if (error) return console.error(error);
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
$scope.domain.mailStatus = mailStatus;
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-01-23 12:30:35 +01:00
|
|
|
showExpectedDnsRecords();
|
|
|
|
|
});
|
2018-01-22 13:01:38 -08:00
|
|
|
});
|
2018-01-23 12:30:35 +01:00
|
|
|
};
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-01-23 12:38:19 +01:00
|
|
|
$scope.refreshStatus = function () {
|
|
|
|
|
$scope.refreshBusy = true;
|
|
|
|
|
|
2020-02-11 21:06:34 +01:00
|
|
|
Client.getMailStatusForDomain($scope.domain.domain, function (error, mailStatus) {
|
2018-01-23 12:38:19 +01:00
|
|
|
if (error) {
|
|
|
|
|
$scope.refreshBusy = false;
|
|
|
|
|
return console.error(error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// overwrite the selected domain status to be available for the UI
|
2020-02-11 21:06:34 +01:00
|
|
|
$scope.domain.mailStatus = mailStatus;
|
2018-01-23 12:38:19 +01:00
|
|
|
|
|
|
|
|
showExpectedDnsRecords();
|
|
|
|
|
|
|
|
|
|
$scope.refreshBusy = false;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2021-12-02 14:49:35 -08:00
|
|
|
$scope.howToConnectInfo = {
|
|
|
|
|
show: function () {
|
|
|
|
|
$('#howToConnectInfoModal').modal('show');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-01-23 15:11:33 +01:00
|
|
|
Client.onReady(function () {
|
2020-02-11 21:06:34 +01:00
|
|
|
$scope.isAdminDomain = $scope.config.adminDomain === domainName;
|
2018-04-09 18:00:08 +02:00
|
|
|
|
2022-02-14 14:55:04 +01:00
|
|
|
Client.getAllUsers(function (error, users) {
|
2018-01-23 15:11:33 +01:00
|
|
|
if (error) return console.error('Unable to get user listing.', error);
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2018-04-05 21:00:33 +02:00
|
|
|
// ensure we have a display value available
|
2020-11-13 13:21:01 -08:00
|
|
|
$scope.owners.push({ header: true, display: $translate.instant('email.mailboxboxDialog.usersHeader') });
|
2020-11-12 23:53:02 -08:00
|
|
|
users.forEach(function (u) {
|
|
|
|
|
$scope.owners.push({ display: u.username || u.email, id: u.id, type: 'user' });
|
2018-04-05 21:00:33 +02:00
|
|
|
});
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2020-11-12 23:53:02 -08:00
|
|
|
Client.getGroups(function (error, groups) {
|
|
|
|
|
if (error) return console.error('Unable to get group listing.', error);
|
2018-12-06 10:28:42 -08:00
|
|
|
|
2020-11-13 13:21:01 -08:00
|
|
|
$scope.owners.push({ header: true, display: $translate.instant('email.mailboxboxDialog.groupsHeader') });
|
2020-11-12 23:53:02 -08:00
|
|
|
groups.forEach(function (g) {
|
|
|
|
|
$scope.owners.push({ display: g.name, id: g.id, type: 'group' });
|
|
|
|
|
});
|
2018-01-22 13:01:38 -08:00
|
|
|
|
2021-12-02 22:21:25 -08:00
|
|
|
$scope.owners.push({ header: true, display: $translate.instant('email.mailboxboxDialog.appsHeader') });
|
|
|
|
|
Client.getInstalledApps().forEach(function (a) {
|
|
|
|
|
if (a.manifest.addons && a.manifest.addons.recvmail) $scope.owners.push({ display: a.label || a.fqdn, id: a.id, type: 'app' });
|
|
|
|
|
});
|
|
|
|
|
|
2020-11-12 23:53:02 -08:00
|
|
|
Client.getDomains(function (error, result) {
|
2022-02-17 17:54:44 +01:00
|
|
|
if (error) return console.error('Unable to list domains.', error);
|
2018-04-09 18:00:08 +02:00
|
|
|
|
2020-11-12 23:53:02 -08:00
|
|
|
$scope.domain = result.filter(function (d) { return d.domain === domainName; })[0];
|
|
|
|
|
$scope.adminDomain = result.filter(function (d) { return d.domain === $scope.config.adminDomain; })[0];
|
|
|
|
|
$scope.refreshDomain();
|
2018-04-09 18:00:08 +02:00
|
|
|
|
2020-11-12 23:53:02 -08:00
|
|
|
async.eachSeries(result, function (domain, iteratorDone) {
|
|
|
|
|
Client.getMailConfigForDomain(domain.domain, function (error, mailConfig) {
|
|
|
|
|
if (error) return console.error('Failed to fetch mail config for domain', domain.domain, error);
|
|
|
|
|
|
|
|
|
|
if (mailConfig.enabled) $scope.incomingDomains.push(domain);
|
|
|
|
|
iteratorDone();
|
|
|
|
|
});
|
|
|
|
|
}, function iteratorDone(error) {
|
|
|
|
|
if (error) return console.error(error);
|
2018-04-09 18:00:08 +02:00
|
|
|
|
2021-11-19 15:45:16 +01:00
|
|
|
$scope.setView($routeParams.view || 'mailboxes', true /* always set */);
|
2020-11-12 23:53:02 -08:00
|
|
|
$scope.ready = true;
|
|
|
|
|
});
|
2020-02-11 21:06:34 +01:00
|
|
|
});
|
|
|
|
|
});
|
2018-04-09 18:00:08 +02:00
|
|
|
});
|
2018-01-22 13:01:38 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// setup all the dialog focus handling
|
2020-02-12 14:51:06 +01:00
|
|
|
['mailboxAddModal', 'mailboxEditModal', 'mailinglistEditModal', 'mailinglistAddModal'].forEach(function (id) {
|
2018-01-22 13:01:38 -08:00
|
|
|
$('#' + id).on('shown.bs.modal', function () {
|
2019-09-11 14:09:53 -07:00
|
|
|
$(this).find('[autofocus]:first').focus();
|
2018-01-22 13:01:38 -08:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$('.modal-backdrop').remove();
|
|
|
|
|
}]);
|