diff --git a/src/routes/settings.js b/src/routes/settings.js index d767a14b1..25308cdfd 100644 --- a/src/routes/settings.js +++ b/src/routes/settings.js @@ -10,7 +10,7 @@ exports = module.exports = { getCloudronAvatar: getCloudronAvatar, setCloudronAvatar: setCloudronAvatar, - getEmailDnsRecords: getEmailDnsRecords, + getEmailStatus: getEmailStatus, getDnsConfig: getDnsConfig, setDnsConfig: setDnsConfig, @@ -150,8 +150,8 @@ function getCloudronAvatar(req, res, next) { }); } -function getEmailDnsRecords(req, res, next) { - settings.getEmailDnsRecords(function (error, records) { +function getEmailStatus(req, res, next) { + settings.getEmailStatus(function (error, records) { if (error) return next(new HttpError(500, error)); next(new HttpSuccess(200, records)); diff --git a/src/server.js b/src/server.js index f50c7eafe..971a558a3 100644 --- a/src/server.js +++ b/src/server.js @@ -188,7 +188,7 @@ function initializeExpressSync() { router.post('/api/v1/settings/cloudron_name', settingsScope, routes.user.requireAdmin, routes.settings.setCloudronName); router.get ('/api/v1/settings/cloudron_avatar', settingsScope, routes.user.requireAdmin, routes.settings.getCloudronAvatar); router.post('/api/v1/settings/cloudron_avatar', settingsScope, routes.user.requireAdmin, multipart, routes.settings.setCloudronAvatar); - router.get ('/api/v1/settings/email_dns_records', settingsScope, routes.user.requireAdmin, routes.settings.getEmailDnsRecords); + router.get ('/api/v1/settings/email_status', settingsScope, routes.user.requireAdmin, routes.settings.getEmailStatus); router.get ('/api/v1/settings/dns_config', settingsScope, routes.user.requireAdmin, routes.settings.getDnsConfig); router.post('/api/v1/settings/dns_config', settingsScope, routes.user.requireAdmin, routes.settings.setDnsConfig); router.get ('/api/v1/settings/backup_config', settingsScope, routes.user.requireAdmin, routes.settings.getBackupConfig); diff --git a/src/settings.js b/src/settings.js index 249b376b4..c2a799fff 100644 --- a/src/settings.js +++ b/src/settings.js @@ -6,7 +6,7 @@ exports = module.exports = { initialize: initialize, uninitialize: uninitialize, - getEmailDnsRecords: getEmailDnsRecords, + getEmailStatus: getEmailStatus, getAutoupdatePattern: getAutoupdatePattern, setAutoupdatePattern: setAutoupdatePattern, @@ -74,6 +74,7 @@ var assert = require('assert'), cloudron = require('./cloudron.js'), CloudronError = cloudron.CloudronError, moment = require('moment-timezone'), + net = require('net'), paths = require('./paths.js'), safe = require('safetydance'), settingsdb = require('./settingsdb.js'), @@ -143,10 +144,10 @@ function uninitialize(callback) { callback(); } -function getEmailDnsRecords(callback) { +function getEmailStatus(callback) { assert.strictEqual(typeof callback, 'function'); - var records = {}; + var records = {}, outboundPort25 = {}; var dkimKey = cloudron.readDkimPublicKeySync(); if (!dkimKey) return callback(new CloudronError(CloudronError.INTERNAL_ERROR, new Error('Failed to read dkim public key'))); @@ -279,6 +280,44 @@ function getEmailDnsRecords(callback) { }); } + function checkOutbound25(callback) { + var smtpServer = _.sample([ + 'smtp.gmail.com', + 'smtp.live.com', + 'smtp.mail.yahoo.com', + 'smtp.o2.ie', + 'smtp.comcast.net', + 'outgoing.verizon.net' + ]); + + outboundPort25 = { + value: 'OK', + status: false + }; + + var client = new net.Socket(); + client.setTimeout(5000); + client.connect(25, smtpServer); + client.on('connect', function () { + outboundPort25.status = true; + outboundPort25.value = 'OK'; + client.end(); + callback(); + }); + client.on('timeout', function () { + outboundPort25.status = false; + outboundPort25.value = 'Connect to ' + smtpServer + ' timed out'; + client.destroy(); + callback(new Error('Timeout')); + }); + client.on('error', function (error) { + outboundPort25.status = false; + outboundPort25.value = 'Connect to ' + smtpServer + ' failed: ' + error.message; + client.destroy(); + callback(error); + }); + } + function ignoreError(what, func) { return function (callback) { func(function (error) { @@ -298,9 +337,10 @@ function getEmailDnsRecords(callback) { ignoreError('spf', checkSpf), ignoreError('dmarc', checkDmarc), ignoreError('dkim', checkDkim), - ignoreError('ptr', checkPtr) + ignoreError('ptr', checkPtr), + ignoreError('port25', checkOutbound25) ], function () { - callback(null, records); + callback(null, { dns: records, outboundPort25: outboundPort25 } ); }); } diff --git a/webadmin/src/js/client.js b/webadmin/src/js/client.js index 79334284c..a5163cb31 100644 --- a/webadmin/src/js/client.js +++ b/webadmin/src/js/client.js @@ -440,8 +440,8 @@ angular.module('Application').service('Client', ['$http', 'md5', 'Notification', }).error(defaultErrorHandler(callback)); }; - Client.prototype.getExpectedDnsRecords = function (callback) { - get('/api/v1/settings/email_dns_records').success(function(data, status) { + Client.prototype.getEmailStatus = function (callback) { + get('/api/v1/settings/email_status').success(function(data, status) { if (status !== 200) return callback(new ClientError(status, data)); callback(null, data); }).error(defaultErrorHandler(callback)); diff --git a/webadmin/src/js/main.js b/webadmin/src/js/main.js index ed6ecbb8d..922bd3a54 100644 --- a/webadmin/src/js/main.js +++ b/webadmin/src/js/main.js @@ -76,10 +76,10 @@ angular.module('Application').controller('MainController', ['$scope', '$route', if (result.provider === 'caas') return; - Client.getExpectedDnsRecords(function (error, result) { + Client.getEmailStatus(function (error, result) { if (error) return console.error(error); - if (!result.spf.status || !result.dkim.status || !result.ptr.status) { + if (!result.dns.spf.status || !result.dns.dkim.status || !result.dns.ptr.status || !result.outboundPort25.status) { var actionScope = $scope.$new(true); actionScope.action = '/#/settings'; diff --git a/webadmin/src/views/settings.html b/webadmin/src/views/settings.html index 058111352..c40b8bef1 100644 --- a/webadmin/src/views/settings.html +++ b/webadmin/src/views/settings.html @@ -319,6 +319,21 @@ + +
+
+

+ Outbound SMTP (Port 25) + +

+ Advanced +
+
+

{{ outboundPort25.value }}

+
+
+
+

diff --git a/webadmin/src/views/settings.js b/webadmin/src/views/settings.js index 0466acbf9..e15cffaed 100644 --- a/webadmin/src/views/settings.js +++ b/webadmin/src/views/settings.js @@ -8,6 +8,7 @@ angular.module('Application').controller('SettingsController', ['$scope', '$loca $scope.config = Client.getConfig(); $scope.backupConfig = {}; $scope.dnsConfig = {}; + $scope.outboundPort25 = {}; $scope.expectedDnsRecords = {}; $scope.expectedDnsRecordsTypes = [ { name: 'MX', value: 'mx' }, @@ -509,10 +510,11 @@ angular.module('Application').controller('SettingsController', ['$scope', '$loca function showExpectedDnsRecords(callback) { callback = callback || function (error) { if (error) console.error(error); }; - Client.getExpectedDnsRecords(function (error, dnsRecords) { + Client.getEmailStatus(function (error, result) { if (error) return callback(error); - $scope.expectedDnsRecords = dnsRecords; + $scope.expectedDnsRecords = result.dns; + $scope.outboundPort25 = result.outboundPort25; callback(null); });