Move email related things into separate view

This commit is contained in:
Johannes Zellner
2017-06-02 10:24:46 +02:00
parent fa3f173e8a
commit 8d45ce6971
7 changed files with 255 additions and 165 deletions

View File

@@ -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>

View File

@@ -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'

View File

@@ -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);
}

View 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> &nbsp;
<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> &nbsp;
<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
View 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();
}]);

View File

@@ -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> &nbsp;
<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> &nbsp;
<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>

View File

@@ -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') {