diff --git a/migrations/20200331164304-apps-alter-mailboxDomain.js b/migrations/20200331164304-apps-alter-mailboxDomain.js new file mode 100644 index 000000000..14346079e --- /dev/null +++ b/migrations/20200331164304-apps-alter-mailboxDomain.js @@ -0,0 +1,28 @@ +'use strict'; + +let async = require('async'); + +exports.up = function(db, callback) { + db.runSql('ALTER TABLE apps MODIFY mailboxDomain VARCHAR(128)', [], function (error) { // make it nullable + if (error) console.error(error); + + // clear mailboxName/Domain for apps that do not use mail addons + db.all('SELECT * FROM apps', function (error, apps) { + if (error) return callback(error); + + async.eachSeries(apps, function (app, iteratorDone) { + var manifest = JSON.parse(app.manifestJson); + if (manifest.addons['sendmail'] || manifest.addons['recvmail']) return iteratorDone(); + + db.runSql('UPDATE apps SET mailboxName=?, mailboxDomain=? WHERE id=?', [ null, null, app.id ], iteratorDone); + }, callback); + }); + }); +}; + +exports.down = function(db, callback) { + db.runSql('ALTER TABLE apps MODIFY manifestJson VARCHAR(128) NOT NULL', [], function (error) { + if (error) console.error(error); + callback(error); + }); +}; diff --git a/migrations/schema.sql b/migrations/schema.sql index 6f1b460e9..41e14a9c4 100644 --- a/migrations/schema.sql +++ b/migrations/schema.sql @@ -79,8 +79,8 @@ CREATE TABLE IF NOT EXISTS apps( reverseProxyConfigJson TEXT, // { robotsTxt, csp } enableBackup BOOLEAN DEFAULT 1, // misnomer: controls automatic daily backups enableAutomaticUpdate BOOLEAN DEFAULT 1, - mailboxName VARCHAR(128), // mailbox of this app. default allocated as '.app' - mailboxDomain VARCHAR(128) NOT NULL, // mailbox domain of this apps + mailboxName VARCHAR(128), // mailbox of this app + mailboxDomain VARCHAR(128), // mailbox domain of this apps label VARCHAR(128), // display name tagsJson VARCHAR(2048), // array of tags dataDir VARCHAR(256) UNIQUE, diff --git a/src/addons.js b/src/addons.js index d6e54e4e8..a091f3699 100644 --- a/src/addons.js +++ b/src/addons.js @@ -524,7 +524,14 @@ function teardownAddons(app, addons, callback) { debugApp(app, 'Tearing down addon %s with options %j', addon, addons[addon]); KNOWN_ADDONS[addon].teardown(app, addons[addon], iteratorCallback); - }, callback); + }, function (error) { + if (error) return callback(error); + + if (app.manifest.addons.sendmail || app.manifest.addons.recvmail) return callback(); + + // clear mailbox name if neither are used + appdb.update(app.id, { mailboxName: null, mailboxDomain: null }, callback); + }); } function backupAddons(app, addons, callback) { diff --git a/src/apps.js b/src/apps.js index 6e39b6014..d164c504b 100644 --- a/src/apps.js +++ b/src/apps.js @@ -699,6 +699,10 @@ function validateLocations(locations, callback) { }); } +function hasMailAddon(manifest) { + return manifest.addons.sendmail || manifest.addons.recvmail; +} + function install(data, auditSource, callback) { assert(data && typeof data === 'object'); assert.strictEqual(typeof auditSource, 'object'); @@ -757,7 +761,8 @@ function install(data, auditSource, callback) { error = validateEnv(env); if (error) return callback(error); - const mailboxName = mailboxNameForLocation(location, manifest); + const mailboxName = hasMailAddon(manifest) ? mailboxNameForLocation(location, manifest) : null; + const mailboxDomain = hasMailAddon(manifest) ? domain : null; const appId = uuid.v4(); if (icon) { @@ -785,7 +790,7 @@ function install(data, auditSource, callback) { sso: sso, debugMode: debugMode, mailboxName: mailboxName, - mailboxDomain: domain, + mailboxDomain: mailboxDomain, enableBackup: enableBackup, enableAutomaticUpdate: enableAutomaticUpdate, alternateDomains: alternateDomains, @@ -1026,6 +1031,8 @@ function setMailbox(app, mailboxName, mailboxDomain, auditSource, callback) { let error = checkAppState(app, exports.ISTATE_PENDING_RECREATE_CONTAINER); if (error) return callback(error); + if (!hasMailAddon(app.manifest)) return callback(new BoxError(BoxError.BAD_FIELD, 'App does not use mail addons')); + mail.getDomain(mailboxDomain, function (error) { if (error) return callback(error); @@ -1033,7 +1040,7 @@ function setMailbox(app, mailboxName, mailboxDomain, auditSource, callback) { error = mail.validateName(mailboxName); if (error) return callback(new BoxError(BoxError.BAD_FIELD, error.message, { field: 'mailboxName' })); } else { - mailboxName = mailboxNameForLocation(app.location, app.manifest); + mailboxName = mailboxNameForLocation(app.location, app.domain, app.manifest); } const task = { @@ -1161,7 +1168,10 @@ function setLocation(app, data, auditSource, callback) { } // move the mailbox name to match the new location - if (app.mailboxName.endsWith('.app')) values.mailboxName = mailboxNameForLocation(values.location, app.manifest); + if (hasMailAddon(app.manifest) && app.mailboxName.endsWith('.app')) { + values.mailboxName = mailboxNameForLocation(values.location, app.manifest); + values.mailboxDomain = values.domain; + } if ('alternateDomains' in data) { values.alternateDomains = data.alternateDomains; @@ -1532,7 +1542,12 @@ function clone(app, data, user, auditSource, callback) { error = validatePortBindings(portBindings, manifest); if (error) return callback(error); - const mailboxName = app.mailboxName.endsWith('.app') ? mailboxNameForLocation(location, manifest) : app.mailboxName; + let mailboxName = null, mailboxDomain = null; + if (hasMailAddon(manifest)) { + mailboxName = app.mailboxName.endsWith('.app') ? mailboxNameForLocation(location, manifest) : app.mailboxName; + mailboxDomain = domain; + } + const locations = [{subdomain: location, domain}]; validateLocations(locations, function (error, domainObjectMap) { if (error) return callback(error); @@ -1546,7 +1561,7 @@ function clone(app, data, user, auditSource, callback) { accessRestriction: app.accessRestriction, sso: !!app.sso, mailboxName: mailboxName, - mailboxDomain: domain, + mailboxDomain: mailboxDomain, enableBackup: app.enableBackup, reverseProxyConfig: app.reverseProxyConfig, env: app.env,