diff --git a/src/platform.js b/src/platform.js index 7b754f6ac..7175c43c5 100644 --- a/src/platform.js +++ b/src/platform.js @@ -242,10 +242,14 @@ function createMailConfig(callback) { debug('createMailConfig: generating mail config'); user.getOwner(function (error, owner) { + if (error) return callback(error); + var alertsTo = config.provider() === 'caas' ? [ 'support@cloudron.io' ] : [ ]; alertsTo.concat(error ? [] : owner.email).join(','); settings.getCatchAllAddress(function (error, address) { + if (error) return callback(error); + var catchAll = address.join(','); if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/mail.ini', @@ -253,7 +257,23 @@ function createMailConfig(callback) { return callback(new Error('Could not create mail var file:' + safe.error.message)); } - callback(); + settings.getMailRelay(function (error, relay) { + if (error) return callback(error); + + const enabled = relay.enabled || false, + host = relay.host || '', + port = relay.port || 25, + tls = !!relay.tls, + username = relay.username || '', + password = relay.password || ''; + + if (!safe.fs.writeFileSync(paths.ADDON_CONFIG_DIR + '/mail/smtp_forward.ini', + `enable_outbound=${enabled}\nhost=${host}\nport=${port}\nenable_tls=${tls}\nauth_user=${username}\nauth_pass=${password}`, 'utf8')) { + return callback(new Error('Could not create mail var file:' + safe.error.message)); + } + + callback(); + }); }); }); } diff --git a/src/routes/settings.js b/src/routes/settings.js index 5e4e324d7..a80a989e0 100644 --- a/src/routes/settings.js +++ b/src/routes/settings.js @@ -24,6 +24,9 @@ exports = module.exports = { getMailConfig: getMailConfig, setMailConfig: setMailConfig, + getMailRelay: getMailRelay, + setMailRelay: setMailRelay, + getCatchAllAddress: getCatchAllAddress, setCatchAllAddress: setCatchAllAddress, @@ -128,6 +131,32 @@ function setMailConfig(req, res, next) { }); } +function getMailRelay(req, res, next) { + settings.getMailRelay(function (error, mail) { + if (error) return next(new HttpError(500, error)); + + next(new HttpSuccess(200, mail)); + }); +} + +function setMailRelay(req, res, next) { + assert.strictEqual(typeof req.body, 'object'); + + if (typeof req.body.enabled !== 'boolean') return next(new HttpError(400, 'enabled is required')); + if ('host' in req.body && typeof req.body.host !== 'string') return next(new HttpError(400, 'host must be a string')); + if ('port' in req.body && typeof req.body.port !== 'number') return next(new HttpError(400, 'port must be a string')); + if ('tls' in req.body && typeof req.body.tls !== 'boolean') return next(new HttpError(400, 'tls must be a boolean')); + if ('username' in req.body && typeof req.body.username !== 'string') return next(new HttpError(400, 'username must be a string')); + if ('password' in req.body && typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be a string')); + + settings.setMailRelay(req.body, function (error) { + 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)); + }); +} + function getCatchAllAddress(req, res, next) { settings.getCatchAllAddress(function (error, address) { if (error) return next(new HttpError(500, error)); diff --git a/src/server.js b/src/server.js index 57562563f..dada05f19 100644 --- a/src/server.js +++ b/src/server.js @@ -211,6 +211,8 @@ function initializeExpressSync() { router.post('/api/v1/settings/appstore_config', settingsScope, routes.user.requireAdmin, routes.settings.setAppstoreConfig); router.get ('/api/v1/settings/mail_config', settingsScope, routes.user.requireAdmin, routes.settings.getMailConfig); router.post('/api/v1/settings/mail_config', settingsScope, routes.user.requireAdmin, routes.settings.setMailConfig); + router.get ('/api/v1/settings/mail_relay', settingsScope, routes.user.requireAdmin, routes.settings.getMailRelay); + router.post('/api/v1/settings/mail_relay', settingsScope, routes.user.requireAdmin, routes.settings.setMailRelay); router.get ('/api/v1/settings/catch_all_address', settingsScope, routes.user.requireAdmin, routes.settings.getCatchAllAddress); router.put ('/api/v1/settings/catch_all_address', settingsScope, routes.user.requireAdmin, routes.settings.setCatchAllAddress); diff --git a/src/settings.js b/src/settings.js index 88f1feed4..5ad2be911 100644 --- a/src/settings.js +++ b/src/settings.js @@ -44,6 +44,9 @@ exports = module.exports = { getMailConfig: getMailConfig, setMailConfig: setMailConfig, + getMailRelay: getMailRelay, + setMailRelay: setMailRelay, + setCatchAllAddress: setCatchAllAddress, getCatchAllAddress: getCatchAllAddress, @@ -61,6 +64,7 @@ exports = module.exports = { UPDATE_CONFIG_KEY: 'update_config', APPSTORE_CONFIG_KEY: 'appstore_config', MAIL_CONFIG_KEY: 'mail_config', + MAIL_RELAY_KEY: 'mail_relay', CATCH_ALL_ADDRESS: 'catch_all_address', events: null @@ -109,6 +113,7 @@ var gDefaults = (function () { result[exports.UPDATE_CONFIG_KEY] = { prerelease: false }; result[exports.APPSTORE_CONFIG_KEY] = {}; result[exports.MAIL_CONFIG_KEY] = { enabled: false }; + result[exports.MAIL_RELAY_KEY] = { enabled: false }; result[exports.CATCH_ALL_ADDRESS] = [ ]; return result; @@ -660,6 +665,32 @@ function setMailConfig(mailConfig, callback) { }); } +function getMailRelay(callback) { + assert.strictEqual(typeof callback, 'function'); + + settingsdb.get(exports.MAIL_RELAY_KEY, function (error, value) { + if (error && error.reason === DatabaseError.NOT_FOUND) return callback(null, gDefaults[exports.MAIL_RELAY_KEY]); + if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error)); + + callback(null, JSON.parse(value)); + }); +} + +function setMailRelay(relay, callback) { + assert.strictEqual(typeof relay, 'object'); + assert.strictEqual(typeof callback, 'function'); + + settingsdb.set(exports.MAIL_RELAY_KEY, JSON.stringify(relay), function (error) { + if (error) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error)); + + exports.events.emit(exports.MAIL_RELAY_KEY, relay); + + platform.createMailConfig(NOOP_CALLBACK); + + callback(null); + }); +} + function getCatchAllAddress(callback) { assert.strictEqual(typeof callback, 'function');