diff --git a/src/routes/settings.js b/src/routes/settings.js index a80a989e0..0ad502ee1 100644 --- a/src/routes/settings.js +++ b/src/routes/settings.js @@ -127,7 +127,7 @@ function setMailConfig(req, res, next) { if (error && error.reason === SettingsError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error) return next(new HttpError(500, error)); - next(new HttpSuccess(200)); + next(new HttpSuccess(202)); }); } @@ -153,7 +153,7 @@ function setMailRelay(req, res, next) { if (error && error.reason === SettingsError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error) return next(new HttpError(500, error)); - next(new HttpSuccess(200)); + next(new HttpSuccess(202)); }); } @@ -178,7 +178,7 @@ function setCatchAllAddress(req, res, next) { if (error && error.reason === SettingsError.BAD_FIELD) return next(new HttpError(400, error.message)); if (error) return next(new HttpError(500, error)); - next(new HttpSuccess(200, {})); + next(new HttpSuccess(202)); }); } @@ -191,7 +191,7 @@ function setCloudronAvatar(req, res, next) { settings.setCloudronAvatar(avatar, function (error) { if (error) return next(new HttpError(500, error)); - next(new HttpSuccess(202, {})); + next(new HttpSuccess(202)); }); } diff --git a/src/routes/test/settings-test.js b/src/routes/test/settings-test.js index fd274d6aa..63d7566a6 100644 --- a/src/routes/test/settings-test.js +++ b/src/routes/test/settings-test.js @@ -299,7 +299,7 @@ describe('Settings API', function () { .query({ access_token: token }) .send({ enabled: true }) .end(function (err, res) { - expect(res.statusCode).to.equal(200); + expect(res.statusCode).to.equal(202); done(); }); }); @@ -351,7 +351,7 @@ describe('Settings API', function () { .query({ access_token: token }) .send({ enabled: true, host: 'host', port: 25, username: 'u', password: 'p', tls: true }) .end(function (err, res) { - expect(res.statusCode).to.equal(200); + expect(res.statusCode).to.equal(202); done(); }); }); @@ -402,7 +402,7 @@ describe('Settings API', function () { .query({ access_token: token }) .send({ address: [ "user1" ] }) .end(function (err, res) { - expect(res.statusCode).to.equal(200); + expect(res.statusCode).to.equal(202); done(); }); }); diff --git a/webadmin/src/js/client.js b/webadmin/src/js/client.js index 19ff1519e..abca9c835 100644 --- a/webadmin/src/js/client.js +++ b/webadmin/src/js/client.js @@ -406,7 +406,7 @@ angular.module('Application').service('Client', ['$http', 'md5', 'Notification', Client.prototype.setCatchallAddresses = function (addresses, callback) { put('/api/v1/settings/catch_all_address', { address: addresses }).success(function(data, status) { - if (status !== 200) return callback(new ClientError(status, data)); + if (status !== 202) return callback(new ClientError(status, data)); callback(null); }).error(defaultErrorHandler(callback)); }; @@ -499,7 +499,21 @@ angular.module('Application').service('Client', ['$http', 'md5', 'Notification', Client.prototype.setMailConfig = function (config, callback) { post('/api/v1/settings/mail_config', config).success(function (data, status) { - if (status !== 200) return callback(new ClientError(status, data)); + if (status !== 202) return callback(new ClientError(status, data)); + callback(null); + }).error(defaultErrorHandler(callback)); + }; + + Client.prototype.getMailRelay = function (callback) { + get('/api/v1/settings/mail_relay').success(function (data, status) { + if (status !== 200 || typeof data !== 'object') return callback(new ClientError(status, data)); + callback(null, data); + }).error(defaultErrorHandler(callback)); + }; + + Client.prototype.setMailRelay = function (config, callback) { + post('/api/v1/settings/mail_relay', config).success(function (data, status) { + if (status !== 202) return callback(new ClientError(status, data)); callback(null); }).error(defaultErrorHandler(callback)); }; diff --git a/webadmin/src/views/email.html b/webadmin/src/views/email.html index 935cde631..2c6a4236b 100644 --- a/webadmin/src/views/email.html +++ b/webadmin/src/views/email.html @@ -34,79 +34,6 @@ -
-
-

SMTP Settings

-
-
- -
-
-
-
- -
-
-
-
-
-
-
- - -
- -
- - - -
- -
- {{ mailRelay.error.smtpHost }} -
- -
-
- -
- {{ mailRelay.error.smtpPort }} -
- -
-
- -
- {{ mailRelay.error.username }} -
- -
-
- -
- {{ mailRelay.error.password }} -
- -
-
- -
- -
-
-
-
-
-
- -
-
-
-

IMAP and SMTP Server

@@ -131,6 +58,80 @@
+
+
+

Outbound Mail Relay

+
+
+ +
+
+
+ Select the mail server through which outbound mails are sent: +
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+ + + +
+ +
+ {{ mailRelay.error.host }} +
+ +
+
+ +
+ {{ mailRelay.error.port }} +
+ +
+ +
+ +
+
+ +
+ {{ mailRelay.error.username }} +
+ +
+
+ +
+ {{ mailRelay.error.password }} +
+ +
+ +
+
+
+
+
+
+ +
+
+
+

Catch-all

diff --git a/webadmin/src/views/email.js b/webadmin/src/views/email.js index d0e57c2a8..2f34b83bb 100644 --- a/webadmin/src/views/email.js +++ b/webadmin/src/views/email.js @@ -85,10 +85,13 @@ angular.module('Application').controller('EmailController', ['$scope', '$locatio }; $scope.mailRelayPresets = [ - { id: 'custom', name: 'Custom', smtpHost: '', smtpPort: 25, tls: false }, - { id: 'google', name: 'Google', smtpHost: 'smtp.gmail.com', smtpPort: 587, tls: true }, - { id: 'sendgrid', name: 'SendGrid', smtpHost: 'smtp.sendgrid.net', smtpPort: 587, tls: true }, - { id: 'ses', name: 'Amazon SES', smtpHost: 'email-smtp.us-east-1.amazonaws.com', smtpPort: 25, tls: true } + { id: 'builtin', name: 'Built-in SMTP server', enabled: false }, + { id: 'ses', name: 'Amazon SES', enabled: true, host: 'email-smtp.us-east-1.amazonaws.com', port: 25, tls: true }, + { id: 'custom', name: 'Custom SMTP server', enabled: true, host: '', port: 587, tls: true }, + { id: 'google', name: 'Google', enabled: true, host: 'smtp.gmail.com', port: 587, tls: true }, + { id: 'mailgun', name: 'Mailgun', enabled: true, host: 'smtp.mailgun.org', port: 587, tls: true }, + { id: 'postmark', name: 'Postmark', enabled: true, host: 'smtp.postmarkapp.com', port: 587, tls: true }, + { id: 'sendgrid', name: 'SendGrid', enabled: true, host: 'smtp.sendgrid.net', port: 587, tls: true }, ]; $scope.mailRelay = { @@ -97,21 +100,32 @@ angular.module('Application').controller('EmailController', ['$scope', '$locatio preset: $scope.mailRelayPresets[0], presetChanged: function () { - $scope.mailRelay.smtpHost = $scope.mailRelay.preset.smtpHost; - $scope.mailRelay.smtpPort = $scope.mailRelay.preset.smtpPort; - $scope.mailRelay.tls = $scope.mailRelay.preset.tls; + $scope.mailRelay.relay.enabled = $scope.mailRelay.preset.enabled; + $scope.mailRelay.relay.presetId = $scope.mailRelay.preset.id; + $scope.mailRelay.relay.host = $scope.mailRelay.preset.host; + $scope.mailRelay.relay.port = $scope.mailRelay.preset.port; + $scope.mailRelay.relay.tls = $scope.mailRelay.preset.tls; }, // form data to be set on load - used: false, - smtpHost: '', - smtpPort: 25, - username: '', - password: '', - tls: true, + relay: { + enabled: false, + presetId: 'builtin', // stash this so we can set the preset label correctly in the UI + host: '', + port: 25, + username: '', + password: '', + tls: true, + }, submit: function () { - console.error('Not implemented'); + $scope.mailRelay.busy = true; + + Client.setMailRelay($scope.mailRelay.relay, function (error) { + if (error) console.error('Unable to set relay', error); + + $scope.mailRelay.busy = false; + }); } }; @@ -123,6 +137,21 @@ angular.module('Application').controller('EmailController', ['$scope', '$locatio }); } + function getMailRelay() { + Client.getMailRelay(function (error, relay) { + if (error) return console.error(error); + + $scope.mailRelay.relay = relay; + + for (var i = 0; i < $scope.mailRelayPresets.length; i++) { + if ($scope.mailRelayPresets[i].id === relay.presetId) { + $scope.mailRelay.preset = $scope.mailRelayPresets[i]; + break; + } + } + }); + } + function getDnsConfig() { Client.getDnsConfig(function (error, dnsConfig) { if (error) return console.error(error); @@ -196,6 +225,7 @@ angular.module('Application').controller('EmailController', ['$scope', '$locatio Client.onReady(function () { getMailConfig(); + getMailRelay(); getDnsConfig(); getSubscription(); getUsers();