Move email related things into separate view
This commit is contained in:
@@ -180,6 +180,7 @@
|
||||
<li ng-show="user.admin"><a href="#/tokens"><i class="fa fa-key fa-fw"></i> API Access</a></li>
|
||||
<li ng-show="user.admin"><a href="#/certs"><i class="fa fa-certificate fa-fw"></i> Domain & Certs</a></li>
|
||||
<li ng-show="user.admin"><a href="#/graphs"><i class="fa fa-bar-chart fa-fw"></i> Graphs</a></li>
|
||||
<li ng-show="user.admin"><a href="#/email"><i class="fa fa-envelope fa-fw"></i> Email</a></li>
|
||||
<li ng-show="user.admin"><a href="#/settings"><i class="fa fa-wrench fa-fw"></i> Settings</a></li>
|
||||
<li ng-show="user.admin" class="divider"></li>
|
||||
<li ng-show="user.admin"><a href="#/support"><i class="fa fa-comment fa-fw"></i> Support</a></li>
|
||||
|
||||
@@ -46,6 +46,9 @@ app.config(['$routeProvider', function ($routeProvider) {
|
||||
}).when('/certs', {
|
||||
controller: 'CertsController',
|
||||
templateUrl: 'views/certs.html'
|
||||
}).when('/email', {
|
||||
controller: 'EmailController',
|
||||
templateUrl: 'views/email.html'
|
||||
}).when('/settings', {
|
||||
controller: 'SettingsController',
|
||||
templateUrl: 'views/settings.html'
|
||||
|
||||
@@ -91,7 +91,7 @@ angular.module('Application').controller('MainController', ['$scope', '$route',
|
||||
|
||||
if (!result.dns.spf.status || !result.dns.dkim.status || !result.dns.ptr.status || !result.outboundPort25.status) {
|
||||
var actionScope = $scope.$new(true);
|
||||
actionScope.action = '/#/settings';
|
||||
actionScope.action = '/#/email';
|
||||
|
||||
Client.notify('DNS Configuration', 'Please setup all required DNS records to guarantee correct mail delivery', false, 'info', actionScope);
|
||||
}
|
||||
|
||||
115
webadmin/src/views/email.html
Normal file
115
webadmin/src/views/email.html
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
<!-- Modal enable email -->
|
||||
<div class="modal fade" id="enableEmailModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">Cloudron Email Server</h4>
|
||||
</div>
|
||||
<div class="modal-body" ng-show="dnsConfig.provider === 'noop' || dnsConfig.provider === 'manual'">
|
||||
No DNS provider is setup. Displayed DNS records will have to be setup manually.<br/>
|
||||
</div>
|
||||
<div class="modal-body" ng-show="dnsConfig.provider === 'route53' || dnsConfig.provider === 'digitalocean'">
|
||||
The Cloudron will setup Email related DNS records automatically.
|
||||
If this domain is already configured to handle email with some other provider, it will <b>overwrite</b> those records.
|
||||
<br/><br/>
|
||||
Disabling Cloudron Email later will <b>not</b> put the old records back.
|
||||
<br/><br/>
|
||||
Status of DNS Records will show an error when DNS is propagating (~5 minutes).
|
||||
<br/>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-success" ng-click="email.enable()">I understand, enable</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="section-header">
|
||||
<div class="text-left">
|
||||
<h1>Email</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-header">
|
||||
<div class="text-left">
|
||||
<h3>IMAP and SMTP Server</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom: 15px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
Cloudron has a built-in email server that allows users to send and receive email for your domain.
|
||||
The <a href="https://cloudron.io/references/usermanual.html#email" target="_blank">User manual</a> has information on how to setup email clients.
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12" ng-show="dnsConfig.provider !== 'caas'">
|
||||
<button ng-class="mailConfig.enabled ? 'btn btn-danger' : 'btn btn-primary'" ng-click="email.toggle()" ng-enabled="mailConfig">{{ mailConfig.enabled ? "Disable Email" : "Enable Email" }}</button>
|
||||
</div>
|
||||
<div class="col-md-12" ng-show="dnsConfig.provider === 'caas'">
|
||||
<span class="text-danger text-bold">This feature requires the Cloudron to be on <a href="https://cloudron.io/references/usermanual.html#entire-cloudron-on-a-custom-domain" target="_blank">custom domain</a>.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-header">
|
||||
<div class="text-left">
|
||||
<h3>DNS Records</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom: 15px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12" ng-show="(dnsConfig.provider !== 'caas')">
|
||||
Set the following DNS records to guarantee email delivery:
|
||||
|
||||
<br/><br/>
|
||||
|
||||
<div ng-repeat="record in expectedDnsRecordsTypes">
|
||||
<div class="row" ng-if="mailConfig.enabled || (record.name !== 'DMARC' && record.name !== 'MX')">
|
||||
<div class="col-xs-12">
|
||||
<p class="text-muted">
|
||||
<i ng-class="expectedDnsRecords[record.value].status ? 'fa fa-check-circle text-success' : 'fa fa-exclamation-triangle text-danger'"></i>
|
||||
<a href="" data-toggle="collapse" data-parent="#accordion" data-target="#collapse_dns_{{ record.value }}">{{ record.name }} record</a>
|
||||
<button class="btn btn-xs btn-default" ng-click="email.refresh()" ng-disabled="email.refreshBusy" ng-show="!expectedDnsRecords[record.value].status"><i class="fa fa-refresh" ng-class="{ 'fa-pulse': email.refreshBusy }"></i></button>
|
||||
</p>
|
||||
<div id="collapse_dns_{{ record.value }}" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<p>Domain: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].domain }}</tt></b></p>
|
||||
<p>Record type: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].type }}</tt></b></p>
|
||||
<p style="overflow: auto; white-space: nowrap;">Expected value: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].expected }}</tt></b></p>
|
||||
<p style="overflow: auto; white-space: nowrap;">Current value: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].value ? expectedDnsRecords[record.value].value : '[not set]' }}</tt></b></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p class="text-muted">
|
||||
<i ng-class="outboundPort25.status ? 'fa fa-check-circle text-success' : 'fa fa-exclamation-triangle text-danger'"></i>
|
||||
<a href="" data-toggle="collapse" data-parent="#accordion" data-target="#collapse_dns_port">
|
||||
Outbound SMTP (Port 25)
|
||||
</a>
|
||||
<button class="btn btn-xs btn-default" ng-click="email.refresh()" ng-disabled="email.refreshBusy" ng-show="!outboundPort25.status"><i class="fa fa-refresh" ng-class="{ 'fa-pulse': email.refreshBusy }"></i></button>
|
||||
</p>
|
||||
<div id="collapse_dns_port" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<p><b> {{ outboundPort25.value }} </b> </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Offset the footer -->
|
||||
<br/><br/>
|
||||
118
webadmin/src/views/email.js
Normal file
118
webadmin/src/views/email.js
Normal file
@@ -0,0 +1,118 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('Application').controller('EmailController', ['$scope', '$location', '$rootScope', 'Client', 'AppStore', function ($scope, $location, $rootScope, Client, AppStore) {
|
||||
Client.onReady(function () { if (!Client.getUserInfo().admin) $location.path('/'); });
|
||||
|
||||
$scope.client = Client;
|
||||
$scope.user = Client.getUserInfo();
|
||||
$scope.config = Client.getConfig();
|
||||
$scope.dnsConfig = {};
|
||||
$scope.outboundPort25 = {};
|
||||
$scope.expectedDnsRecords = {};
|
||||
$scope.expectedDnsRecordsTypes = [
|
||||
{ name: 'MX', value: 'mx' },
|
||||
{ name: 'DKIM', value: 'dkim' },
|
||||
{ name: 'SPF', value: 'spf' },
|
||||
{ name: 'DMARC', value: 'dmarc' },
|
||||
{ name: 'PTR', value: 'ptr' }
|
||||
];
|
||||
$scope.mailConfig = null;
|
||||
|
||||
$scope.showView = function (view) {
|
||||
// wait for dialog to be fully closed to avoid modal behavior breakage when moving to a different view already
|
||||
$('.modal').on('hidden.bs.modal', function () {
|
||||
$('.modal').off('hidden.bs.modal');
|
||||
$location.path(view);
|
||||
});
|
||||
|
||||
$('.modal').modal('hide');
|
||||
};
|
||||
|
||||
$scope.email = {
|
||||
refreshBusy: false,
|
||||
|
||||
toggle: function () {
|
||||
if ($scope.mailConfig.enabled) return $scope.email.disable();
|
||||
|
||||
// show warning first
|
||||
$('#enableEmailModal').modal('show');
|
||||
},
|
||||
|
||||
enable: function () {
|
||||
$('#enableEmailModal').modal('hide');
|
||||
|
||||
Client.setMailConfig({ enabled: true }, function (error) {
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.mailConfig.enabled = true;
|
||||
});
|
||||
},
|
||||
|
||||
disable: function () {
|
||||
Client.setMailConfig({ enabled: false }, function (error) {
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.mailConfig.enabled = false;
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function () {
|
||||
$scope.email.refreshBusy = true;
|
||||
|
||||
showExpectedDnsRecords(function (error) {
|
||||
if (error) console.error(error);
|
||||
|
||||
$scope.email.refreshBusy = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function getMailConfig() {
|
||||
Client.getMailConfig(function (error, mailConfig) {
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.mailConfig = mailConfig;
|
||||
|
||||
showExpectedDnsRecords();
|
||||
});
|
||||
}
|
||||
|
||||
function getDnsConfig() {
|
||||
Client.getDnsConfig(function (error, dnsConfig) {
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.dnsConfig = dnsConfig;
|
||||
});
|
||||
}
|
||||
|
||||
function showExpectedDnsRecords(callback) {
|
||||
callback = callback || function (error) { if (error) console.error(error); };
|
||||
|
||||
Client.getEmailStatus(function (error, result) {
|
||||
if (error) return callback(error);
|
||||
|
||||
$scope.expectedDnsRecords = result.dns;
|
||||
$scope.outboundPort25 = result.outboundPort25;
|
||||
|
||||
// open the record details if they are not correct
|
||||
for (var type in $scope.expectedDnsRecords) {
|
||||
if (!$scope.expectedDnsRecords[type].status) {
|
||||
$('#collapse_dns_' + type).collapse('show');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$scope.outboundPort25.status) {
|
||||
$('#collapse_dns_port').collapse('show');
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
|
||||
Client.onReady(function () {
|
||||
getMailConfig();
|
||||
getDnsConfig();
|
||||
});
|
||||
|
||||
$('.modal-backdrop').remove();
|
||||
}]);
|
||||
@@ -221,6 +221,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal subscription required -->
|
||||
<div class="modal" id="subscriptionRequiredModal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
The Cloudron Email server is only available in the paid plans.<br/>
|
||||
<br/>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="section-header">
|
||||
@@ -303,75 +320,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-header">
|
||||
<div class="text-left">
|
||||
<h3>Email</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom: 15px;">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
Cloudron has a built-in email server that allows users to send and receive email for your domain.
|
||||
The <a href="https://cloudron.io/references/usermanual.html#email" target="_blank">User manual</a> has information on how to setup email clients.
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12" ng-show="dnsConfig.provider !== 'caas'">
|
||||
<button ng-class="mailConfig.enabled ? 'btn btn-danger' : 'btn btn-primary'" ng-click="email.toggle()" ng-enabled="mailConfig">{{ mailConfig.enabled ? "Disable Email" : "Enable Email" }}</button>
|
||||
</div>
|
||||
<div class="col-md-12" ng-show="dnsConfig.provider === 'caas'">
|
||||
<span class="text-danger text-bold">This feature requires the Cloudron to be on <a href="https://cloudron.io/references/usermanual.html#entire-cloudron-on-a-custom-domain" target="_blank">custom domain</a>.</span>
|
||||
</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-12" ng-show="(dnsConfig.provider !== 'caas')">
|
||||
Set the following DNS records to guarantee email delivery:
|
||||
|
||||
<br/><br/>
|
||||
|
||||
<div ng-repeat="record in expectedDnsRecordsTypes">
|
||||
<div class="row" ng-if="mailConfig.enabled || (record.name !== 'DMARC' && record.name !== 'MX')">
|
||||
<div class="col-xs-12">
|
||||
<p class="text-muted">
|
||||
<i ng-class="expectedDnsRecords[record.value].status ? 'fa fa-check-circle text-success' : 'fa fa-exclamation-triangle text-danger'"></i>
|
||||
<a href="" data-toggle="collapse" data-parent="#accordion" data-target="#collapse_dns_{{ record.value }}">{{ record.name }} record</a>
|
||||
<button class="btn btn-xs btn-default" ng-click="email.refresh()" ng-disabled="email.refreshBusy" ng-show="!expectedDnsRecords[record.value].status"><i class="fa fa-refresh" ng-class="{ 'fa-pulse': email.refreshBusy }"></i></button>
|
||||
</p>
|
||||
<div id="collapse_dns_{{ record.value }}" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<p>Domain: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].domain }}</tt></b></p>
|
||||
<p>Record type: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].type }}</tt></b></p>
|
||||
<p style="overflow: auto; white-space: nowrap;">Expected value: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].expected }}</tt></b></p>
|
||||
<p style="overflow: auto; white-space: nowrap;">Current value: <b ng-click-select><tt>{{ expectedDnsRecords[record.value].value ? expectedDnsRecords[record.value].value : '[not set]' }}</tt></b></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<p class="text-muted">
|
||||
<i ng-class="outboundPort25.status ? 'fa fa-check-circle text-success' : 'fa fa-exclamation-triangle text-danger'"></i>
|
||||
<a href="" data-toggle="collapse" data-parent="#accordion" data-target="#collapse_dns_port">
|
||||
Outbound SMTP (Port 25)
|
||||
</a>
|
||||
<button class="btn btn-xs btn-default" ng-click="email.refresh()" ng-disabled="email.refreshBusy" ng-show="!outboundPort25.status"><i class="fa fa-refresh" ng-class="{ 'fa-pulse': email.refreshBusy }"></i></button>
|
||||
</p>
|
||||
<div id="collapse_dns_port" class="panel-collapse collapse">
|
||||
<div class="panel-body">
|
||||
<p><b> {{ outboundPort25.value }} </b> </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section-header">
|
||||
<div class="text-left">
|
||||
<h3>Backups</h3>
|
||||
|
||||
@@ -7,20 +7,8 @@ angular.module('Application').controller('SettingsController', ['$scope', '$loca
|
||||
$scope.user = Client.getUserInfo();
|
||||
$scope.config = Client.getConfig();
|
||||
$scope.backupConfig = {};
|
||||
$scope.dnsConfig = {};
|
||||
$scope.outboundPort25 = {};
|
||||
$scope.expectedDnsRecords = {};
|
||||
$scope.expectedDnsRecordsTypes = [
|
||||
{ name: 'MX', value: 'mx' },
|
||||
{ name: 'DKIM', value: 'dkim' },
|
||||
{ name: 'SPF', value: 'spf' },
|
||||
{ name: 'DMARC', value: 'dmarc' },
|
||||
{ name: 'PTR', value: 'ptr' }
|
||||
];
|
||||
$scope.appstoreConfig = {};
|
||||
|
||||
$scope.mailConfig = null;
|
||||
|
||||
$scope.lastBackup = null;
|
||||
$scope.backups = [];
|
||||
|
||||
@@ -303,45 +291,6 @@ angular.module('Application').controller('SettingsController', ['$scope', '$loca
|
||||
}
|
||||
};
|
||||
|
||||
$scope.email = {
|
||||
refreshBusy: false,
|
||||
|
||||
toggle: function () {
|
||||
if ($scope.mailConfig.enabled) return $scope.email.disable();
|
||||
|
||||
// show warning first
|
||||
$('#enableEmailModal').modal('show');
|
||||
},
|
||||
|
||||
enable: function () {
|
||||
$('#enableEmailModal').modal('hide');
|
||||
|
||||
Client.setMailConfig({ enabled: true }, function (error) {
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.mailConfig.enabled = true;
|
||||
});
|
||||
},
|
||||
|
||||
disable: function () {
|
||||
Client.setMailConfig({ enabled: false }, function (error) {
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.mailConfig.enabled = false;
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function () {
|
||||
$scope.email.refreshBusy = true;
|
||||
|
||||
showExpectedDnsRecords(function (error) {
|
||||
if (error) console.error(error);
|
||||
|
||||
$scope.email.refreshBusy = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.s3like = function (provider) {
|
||||
return provider === 's3' || provider === 'minio';
|
||||
};
|
||||
@@ -526,16 +475,6 @@ angular.module('Application').controller('SettingsController', ['$scope', '$loca
|
||||
});
|
||||
}
|
||||
|
||||
function getMailConfig() {
|
||||
Client.getMailConfig(function (error, mailConfig) {
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.mailConfig = mailConfig;
|
||||
|
||||
showExpectedDnsRecords();
|
||||
});
|
||||
}
|
||||
|
||||
function getBackupConfig() {
|
||||
Client.getBackupConfig(function (error, backupConfig) {
|
||||
if (error) return console.error(error);
|
||||
@@ -552,14 +491,6 @@ angular.module('Application').controller('SettingsController', ['$scope', '$loca
|
||||
});
|
||||
}
|
||||
|
||||
function getDnsConfig() {
|
||||
Client.getDnsConfig(function (error, dnsConfig) {
|
||||
if (error) return console.error(error);
|
||||
|
||||
$scope.dnsConfig = dnsConfig;
|
||||
});
|
||||
}
|
||||
|
||||
function getAutoupdatePattern() {
|
||||
Client.getAutoupdatePattern(function (error, result) {
|
||||
if (error) return console.error(error);
|
||||
@@ -569,30 +500,6 @@ angular.module('Application').controller('SettingsController', ['$scope', '$loca
|
||||
});
|
||||
}
|
||||
|
||||
function showExpectedDnsRecords(callback) {
|
||||
callback = callback || function (error) { if (error) console.error(error); };
|
||||
|
||||
Client.getEmailStatus(function (error, result) {
|
||||
if (error) return callback(error);
|
||||
|
||||
$scope.expectedDnsRecords = result.dns;
|
||||
$scope.outboundPort25 = result.outboundPort25;
|
||||
|
||||
// open the record details if they are not correct
|
||||
for (var type in $scope.expectedDnsRecords) {
|
||||
if (!$scope.expectedDnsRecords[type].status) {
|
||||
$('#collapse_dns_' + type).collapse('show');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$scope.outboundPort25.status) {
|
||||
$('#collapse_dns_port').collapse('show');
|
||||
}
|
||||
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
|
||||
function getPlans() {
|
||||
AppStore.getSizes(function (error, result) {
|
||||
if (error) return console.error(error);
|
||||
@@ -688,9 +595,7 @@ angular.module('Application').controller('SettingsController', ['$scope', '$loca
|
||||
|
||||
Client.onReady(function () {
|
||||
fetchBackups();
|
||||
getMailConfig();
|
||||
getBackupConfig();
|
||||
getDnsConfig();
|
||||
getAutoupdatePattern();
|
||||
|
||||
if ($scope.config.provider === 'caas') {
|
||||
|
||||
Reference in New Issue
Block a user