diff --git a/src/cloudron.js b/src/cloudron.js index 86a226654..dde5c089b 100644 --- a/src/cloudron.js +++ b/src/cloudron.js @@ -31,7 +31,6 @@ var appdb = require('./appdb.js'), BackupsError = require('./backups.js').BackupsError, caas = require('./caas.js'), certificates = require('./certificates.js'), - child_process = require('child_process'), clients = require('./clients.js'), config = require('./config.js'), constants = require('./constants.js'), @@ -43,6 +42,7 @@ var appdb = require('./appdb.js'), eventlog = require('./eventlog.js'), fs = require('fs'), locker = require('./locker.js'), + mail = require('./mail.js'), mailer = require('./mailer.js'), nginx = require('./nginx.js'), os = require('os'), @@ -144,7 +144,6 @@ function onDomainConfigured(callback) { async.series([ clients.addDefaultClients, certificates.ensureFallbackCertificate, - ensureDkimKey, cron.initialize // required for caas heartbeat before activation ], callback); } @@ -233,8 +232,14 @@ function dnsSetup(adminFqdn, domain, zoneName, provider, dnsConfig, callback) { domains.get(domain, function (error, result) { if (error && error.reason !== DomainError.NOT_FOUND) return callback(new SettingsError(SettingsError.INTERNAL_ERROR, error)); - if (!result) domains.add(domain, zoneName, provider, dnsConfig, null /* cert */, done); - else domains.update(domain, provider, dnsConfig, null /* cert */, done); + if (!result) { + async.series([ + domains.add.bind(null, domain, zoneName, provider, dnsConfig, null /* cert */), + mail.add(null, domain) + ], done); + } else { + domains.update(domain, provider, dnsConfig, null /* cert */, done); + } }); } @@ -470,33 +475,6 @@ function getConfig(callback) { }); } -function ensureDkimKey(callback) { - assert(config.fqdn(), 'fqdn is not set'); - - var dkimPath = path.join(paths.MAIL_DATA_DIR, 'dkim/' + config.fqdn()); - var dkimPrivateKeyFile = path.join(dkimPath, 'private'); - var dkimPublicKeyFile = path.join(dkimPath, 'public'); - var dkimSelectorFile = path.join(dkimPath, 'selector'); - - if (!fs.existsSync(dkimPrivateKeyFile) || !fs.existsSync(dkimPublicKeyFile) || !fs.existsSync(dkimSelectorFile)) { - debug('Generating new DKIM keys'); - - if (!safe.fs.mkdirSync(dkimPath) && safe.error.code !== 'EEXIST') { - debug('Error creating dkim.', safe.error); - return null; - } - - child_process.execSync('openssl genrsa -out ' + dkimPrivateKeyFile + ' 1024'); - child_process.execSync('openssl rsa -in ' + dkimPrivateKeyFile + ' -out ' + dkimPublicKeyFile + ' -pubout -outform PEM'); - - safe.fs.writeFileSync(dkimSelectorFile, config.dkimSelector(), 'utf8'); - } else { - debug('DKIM keys already present'); - } - - callback(); -} - function readDkimPublicKeySync() { if (!config.fqdn()) { debug('Cannot read dkim public key without a domain.', safe.error); diff --git a/src/config.js b/src/config.js index e695d4c27..e71b8a6fc 100644 --- a/src/config.js +++ b/src/config.js @@ -243,6 +243,8 @@ function hasIPv6() { return fs.existsSync(IPV6_PROC_FILE); } +// it has to change with the adminLocation so that multiple cloudrons +// can send out emails at the same time. function dkimSelector() { var loc = adminLocation(); return loc === 'my' ? 'cloudron' : `cloudron-${loc.replace(/\./g, '')}`; diff --git a/src/domaindb.js b/src/domaindb.js index 5c14da92a..fd93359e5 100644 --- a/src/domaindb.js +++ b/src/domaindb.js @@ -60,13 +60,9 @@ function add(name, domain, callback) { assert.strictEqual(typeof domain.config, 'object'); assert.strictEqual(typeof callback, 'function'); - var queries = []; - queries.push({ query: 'INSERT INTO domains (domain, zoneName, provider, configJson) VALUES (?, ?, ?, ?)', args: [ name, domain.zoneName, domain.provider, JSON.stringify(domain.config) ] }); - queries.push({ query: 'INSERT INTO mail (domain) VALUES (?)', args: [ name ] }); - - database.transaction(queries, function (error, result) { + database.query('INSERT INTO domains (domain, zoneName, provider, configJson) VALUES (?, ?, ?, ?)', [ name, domain.zoneName, domain.provider, JSON.stringify(domain.config) ], function (error) { if (error && error.code === 'ER_DUP_ENTRY') return callback(new DatabaseError(DatabaseError.ALREADY_EXISTS, error)); - if (error || result[1].affectedRows !== 1) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); + if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); callback(null); }); @@ -101,14 +97,10 @@ function del(domain, callback) { assert.strictEqual(typeof domain, 'string'); assert.strictEqual(typeof callback, 'function'); - var queries = []; - queries.push({ query: 'DELETE FROM mail WHERE domain=?', args: [ domain ] }); - queries.push({ query: 'DELETE FROM domains WHERE domain=?', args: [ domain ] }); - - database.transaction(queries, function (error, result) { + database.query('DELETE FROM domains WHERE domain=?', [ domain ], function (error, result) { if (error && error.code === 'ER_ROW_IS_REFERENCED_2') return callback(new DatabaseError(DatabaseError.IN_USE)); if (error) return callback(new DatabaseError(DatabaseError.INTERNAL_ERROR, error)); - if (result[1].affectedRows !== 1) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); + if (result.affectedRows === 0) return callback(new DatabaseError(DatabaseError.NOT_FOUND)); callback(null); }); diff --git a/src/mail.js b/src/mail.js index 8925a5cdf..9188c2fcb 100644 --- a/src/mail.js +++ b/src/mail.js @@ -46,6 +46,7 @@ var assert = require('assert'), net = require('net'), nodemailer = require('nodemailer'), os = require('os'), + path = require('path'), paths = require('./paths.js'), safe = require('safetydance'), shell = require('./shell.js'), @@ -577,16 +578,44 @@ function getAll(callback) { }); } +function ensureDkimKey(domain, callback) { + assert.strictEqual(typeof domain, 'string'); + assert.strictEqual(typeof callback, 'function'); + + var dkimPath = path.join(paths.MAIL_DATA_DIR, `dkim/${domain}`); + var dkimPrivateKeyFile = path.join(dkimPath, 'private'); + var dkimPublicKeyFile = path.join(dkimPath, 'public'); + var dkimSelectorFile = path.join(dkimPath, 'selector'); + + debug('Generating new DKIM keys'); + + if (!safe.fs.mkdirSync(dkimPath) && safe.error.code !== 'EEXIST') { + debug('Error creating dkim.', safe.error); + return new MailError(MailError.INTERNAL_ERROR, safe.error); + } + + if (!safe.child_process.execSync('openssl genrsa -out ' + dkimPrivateKeyFile + ' 1024')) return new MailError(MailError.INTERNAL_ERROR, safe.error); + if (!safe.child_process.execSync('openssl rsa -in ' + dkimPrivateKeyFile + ' -out ' + dkimPublicKeyFile + ' -pubout -outform PEM')) return new MailError(MailError.INTERNAL_ERROR, safe.error); + + if (!safe.fs.writeFileSync(dkimSelectorFile, config.dkimSelector(), 'utf8')) return new MailError(MailError.INTERNAL_ERROR, safe.error); + + callback(); +} + function add(domain, callback) { assert.strictEqual(typeof domain, 'string'); assert.strictEqual(typeof callback, 'function'); - maildb.add(domain, function (error) { - if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(new MailError(MailError.ALREADY_EXISTS, error.message)); - if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new MailError(MailError.NOT_FOUND, error.message)); + ensureDkimKey(domain, function (error) { if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error)); - callback(); + maildb.add(domain, function (error) { + if (error && error.reason === DatabaseError.ALREADY_EXISTS) return callback(new MailError(MailError.ALREADY_EXISTS, error.message)); + if (error && error.reason === DatabaseError.NOT_FOUND) return callback(new MailError(MailError.NOT_FOUND, error.message)); + if (error) return callback(new MailError(MailError.INTERNAL_ERROR, error)); + + callback(); + }); }); }