diff --git a/Changes.md b/Changes.md index 819b63628..e3f0ed13a 100644 --- a/Changes.md +++ b/Changes.md @@ -58,6 +58,7 @@ - remove config setting ipv6_enabled #3322 - remove undocumented use of send_email with arity of 2. #3322 - encapsulate force_tls logic into get_force_tls #3322 + - es6(async/promise): pre_send_trans_email_respond, process_delivery - queue/lmtp: refactored for DRY and improved readability #3322 - smtp_client: pass connect_timeout, maybe fixes #3281 - spamassassin: repackaged as NPM module #3348 @@ -66,6 +67,9 @@ - doc(Plugins.md): update registry - remove last vestiges of header_hide_version (long ago renamed) - server.js: use the local logger methods + - es6(async): _graceful, get_smtp_server, setup_smtp_listeners + - replace async.eachLimit with Promise.all batches +- status: replace async.map with Promise.allSettled - get Haraka version from utils.getVersion (which includes git id if running from repo) - tls_socket: remove secureConnection. Fixes #2743 - getSocketOpts is now async diff --git a/outbound/hmail.js b/outbound/hmail.js index 7a7205499..6afe368d2 100644 --- a/outbound/hmail.js +++ b/outbound/hmail.js @@ -262,7 +262,7 @@ class HMailItem extends events.EventEmitter { return this.bounce(`Domain ${this.todo.domain} sends and receives no email (NULL MX)`); } - // resolves the MX hostnames into IPs + // resolves the MX hostnames to IPs this.mxlist = await net_utils.resolve_mx_hosts(mxs); this.try_deliver(); diff --git a/outbound/index.js b/outbound/index.js index d2410ece1..5297cc246 100644 --- a/outbound/index.js +++ b/outbound/index.js @@ -3,7 +3,6 @@ const fs = require('node:fs'); const path = require('node:path'); -const async = require('async'); const { Address } = require('address-rfc2821'); const config = require('haraka-config'); const constants = require('haraka-constants'); @@ -232,75 +231,76 @@ exports.send_trans_email = function (transaction, next) { transaction.results = new ResultStore(connection); } - connection.pre_send_trans_email_respond = retval => { + connection.pre_send_trans_email_respond = async (retval) => { const deliveries = get_deliveries(transaction); const hmails = []; const ok_paths = []; let todo_index = 1; - async.forEachSeries(deliveries, (deliv, cb) => { - const todo = new TODOItem(deliv.domain, deliv.rcpts, transaction); - todo.uuid = `${todo.uuid}.${todo_index}`; - todo_index++; - this.process_delivery(ok_paths, todo, hmails, cb); - }, - (err) => { - if (err) { - for (let i=0, l=ok_paths.length; i {}); - } - transaction.results.add({ name: 'outbound'}, { err }); - if (next) next(constants.denysoft, err); - return; + try { + for (const deliv of deliveries) { + const todo = new TODOItem(deliv.domain, deliv.rcpts, transaction); + todo.uuid = `${todo.uuid}.${todo_index}`; + todo_index++; + await this.process_delivery(ok_paths, todo, hmails); } - - for (const hmail of hmails) { - delivery_queue.push(hmail); + } + catch (err) { + for (let i=0, l=ok_paths.length; i {}); } + transaction.results.add({ name: 'outbound'}, { err }); + if (next) next(constants.denysoft, err); + return; + } - transaction.results.add({ name: 'outbound'}, { pass: "queued" }); - if (next) { - next(constants.ok, `Message Queued (${transaction.uuid})`); - } - }); + for (const hmail of hmails) { + delivery_queue.push(hmail); + } + + transaction.results.add({ name: 'outbound'}, { pass: "queued" }); + if (next) next(constants.ok, `Message Queued (${transaction.uuid})`); } plugins.run_hooks('pre_send_trans_email', connection); } -exports.process_delivery = function (ok_paths, todo, hmails, cb) { - logger.info(exports, `Transaction delivery for domain: ${todo.domain}`); - const fname = _qfile.name(); - const tmp_path = path.join(queue_dir, `${_qfile.platformDOT}${fname}`); - const ws = new FsyncWriteStream(tmp_path, { flags: constants.WRITE_EXCL }); +exports.process_delivery = function (ok_paths, todo, hmails) { + return new Promise((resolve, reject) => { + + logger.info(exports, `Transaction delivery for domain: ${todo.domain}`); + const fname = _qfile.name(); + const tmp_path = path.join(queue_dir, `${_qfile.platformDOT}${fname}`); + const ws = new FsyncWriteStream(tmp_path, { flags: constants.WRITE_EXCL }); + + ws.on('close', () => { + const dest_path = path.join(queue_dir, fname); + fs.rename(tmp_path, dest_path, err => { + if (err) { + logger.error(exports, `Unable to rename tmp file!: ${err}`); + fs.unlink(tmp_path, () => {}); + reject("Queue error"); + } + else { + hmails.push(new HMailItem (fname, dest_path, todo.notes)); + ok_paths.push(dest_path); + resolve(); + } + }) + }) - ws.on('close', () => { - const dest_path = path.join(queue_dir, fname); - fs.rename(tmp_path, dest_path, err => { - if (err) { - logger.error(exports, `Unable to rename tmp file!: ${err}`); - fs.unlink(tmp_path, () => {}); - cb("Queue error"); - } - else { - hmails.push(new HMailItem (fname, dest_path, todo.notes)); - ok_paths.push(dest_path); - cb(); - } + ws.on('error', err => { + logger.error(exports, `Unable to write queue file (${fname}): ${err}`); + ws.destroy(); + fs.unlink(tmp_path, () => {}); + reject("Queueing failed"); }) - }) - ws.on('error', err => { - logger.error(exports, `Unable to write queue file (${fname}): ${err}`); - ws.destroy(); - fs.unlink(tmp_path, () => {}); - cb("Queueing failed"); + this.build_todo(todo, ws, () => { + todo.message_stream.pipe(ws, { dot_stuffing: true }); + }); }) - - this.build_todo(todo, ws, () => { - todo.message_stream.pipe(ws, { dot_stuffing: true }); - }); } exports.build_todo = (todo, ws, write_more) => { diff --git a/outbound/queue.js b/outbound/queue.js index fee9669ea..eec338782 100644 --- a/outbound/queue.js +++ b/outbound/queue.js @@ -86,16 +86,15 @@ exports.load_queue = pid => { } exports._load_cur_queue = (pid, iteratee, cb) => { - const self = exports; logger.info(exports, "Loading outbound queue from ", queue_dir); fs.readdir(queue_dir, (err, files) => { if (err) { return logger.error(exports, `Failed to load queue directory (${queue_dir}): ${err}`); } - self.cur_time = new Date(); // set once so we're not calling it a lot + this.cur_time = new Date(); // set once so we're not calling it a lot - self.load_queue_files(pid, files, iteratee, cb); + this.load_queue_files(pid, files, iteratee, cb); }); } diff --git a/outbound/timer_queue.js b/outbound/timer_queue.js index 2691089a1..46d9c55c4 100644 --- a/outbound/timer_queue.js +++ b/outbound/timer_queue.js @@ -19,6 +19,7 @@ class TQTimer { class TimerQueue { constructor (interval = 1000) { + this.name = 'outbound/timer_queue' this.queue = []; this.interval_timer = setInterval(() => { this.fire(); }, interval); this.interval_timer.unref() // allow server to exit @@ -72,7 +73,7 @@ class TimerQueue { } drain () { - logger.debug({ name: 'outbound/timer_queue'}, `Draining ${this.queue.length} items from the queue`); + logger.debug(this, `Draining ${this.queue.length} items from the queue`); while (this.queue.length) { const to_run = this.queue.shift(); if (to_run.cb) to_run.cb(); diff --git a/plugins/status.js b/plugins/status.js index 39b7e3b53..b77eb89b0 100644 --- a/plugins/status.js +++ b/plugins/status.js @@ -3,8 +3,6 @@ const fs = require('node:fs'); const path = require('node:path'); -const async = require('async'); - exports.register = function () { this.outbound = require('../outbound'); this.queue_dir = require('../outbound/queue').queue_dir; @@ -82,38 +80,36 @@ exports.pool_list = cb => { const result = {}; if (server.notes.pool) { - Object.keys(server.notes.pool).forEach(name => { + for (const name of Object.keys(server.notes.pool)) { const instance = server.notes.pool[name]; result[name] = { inUse: instance.inUseObjectsCount(), size: instance.getPoolSize() }; - }); + } } cb(null, result); } exports.queue_list = function (cb) { - this.outbound.list_queue((err, qlist) => { - if (err) cb(err); - + this.outbound.list_queue((err, qlist = []) => { const result = []; - if (qlist) { - qlist.forEach((todo) => result.push({ + for (const todo of qlist) { + result.push({ file: todo.file, uuid: todo.uuid, queue_time: todo.queue_time, domain: todo.domain, from: todo.mail_from.toString(), to: todo.rcpt_to.map((r) => r.toString()) - })); + }) } cb(err, result); - }); + }) } exports.queue_stats = function (cb) { @@ -166,14 +162,14 @@ exports.queue_push = function (file, cb) { // cluster IPC exports.hook_init_master = function (next) { - const self = this; + const plugin = this; if (!server.cluster) return next(); function message_handler (sender, msg) { if (msg.event !== 'status.request') return; - self.call_workers(msg, (err, response) => { + plugin.call_workers(msg, (response) => { msg.result = response.filter((el) => el != null); msg.event = 'status.result'; sender.send(msg); @@ -215,32 +211,39 @@ exports.call_master = (cmd, cb) => { } exports.call_workers = function (cmd, cb) { - - async.map(server.cluster.workers, (w, done) => { - this.call_worker(w, cmd, done); - }, cb); + Promise.allSettled( + Object.values(server.cluster.workers).map(w => this.call_worker(w, cmd)) + ) + .then(r => { + cb( + // r.filter(s => s.status === 'rejected').flatMap(s => s.reason), + r.filter(s => s.status === 'fulfilled').flatMap(s => s.value), + ) + }) } // sends command to worker and then wait for response or timeout -exports.call_worker = (worker, cmd, cb) => { - let timeout; +exports.call_worker = (worker, cmd) => { + return new Promise((resolve) => { + let timeout; - function message_handler (sender, msg) { - if (sender.id !== worker.id) return; - if (msg.event !== 'status.response') return; + function message_handler (sender, msg) { + if (sender.id !== worker.id) return; + if (msg.event !== 'status.response') return; - clearTimeout(timeout); - server.cluster.removeListener('message', message_handler); + clearTimeout(timeout); + server.cluster.removeListener('message', message_handler); - cb(null, msg.result); - } + resolve(msg.result); + } - timeout = setTimeout(() => { - server.cluster.removeListener('message', message_handler); - cb(); - }, 1000); + timeout = setTimeout(() => { + server.cluster.removeListener('message', message_handler); + resolve(); + }, 1000); - server.cluster.on('message', message_handler); - worker.send(cmd); + server.cluster.on('message', message_handler); + worker.send(cmd); + }) } diff --git a/server.js b/server.js index ccda7140b..68ba3fe74 100644 --- a/server.js +++ b/server.js @@ -7,13 +7,13 @@ const os = require('node:os'); const path = require('node:path'); const tls = require('node:tls'); -const async = require('async'); const daemon = require('daemon'); +const constants = require('haraka-constants'); + const tls_socket = require('./tls_socket'); const conn = require('./connection'); const outbound = require('./outbound'); const endpoint = require('./endpoint'); -const constants = require('haraka-constants'); const Server = exports; Server.logger = require('./logger'); @@ -148,7 +148,7 @@ Server.gracefulShutdown = () => { }); } -Server._graceful = shutdown => { +Server._graceful = async (shutdown) => { if (!Server.cluster && shutdown) { for (const module of ['outbound', 'cfreader', 'plugins']) { process.emit('message', {event: `${module}.shutdown`}); @@ -167,66 +167,80 @@ Server._graceful = shutdown => { const disconnect_timeout = 30; const exit_timeout = 30; cluster.removeAllListeners('exit'); + // we reload using eachLimit where limit = num_workers - 1 // this kills all-but-one workers in parallel, leaving one running // for new connections, and then restarts that one last worker. + const worker_ids = Object.keys(cluster.workers); let limit = worker_ids.length - 1; if (limit < 2) limit = 1; - async.eachLimit(worker_ids, limit, (id, cb) => { - Server.lognotice(`Killing node: ${id}`); - const worker = cluster.workers[id]; - for (const module of ['outbound', 'cfreader', 'plugins']) { - worker.send({event: `${module }.shutdown`}); - } - worker.disconnect(); - let disconnect_received = false; - const disconnect_timer = setTimeout(() => { - if (!disconnect_received) { - Server.logcrit("Disconnect never received by worker. Killing."); - worker.kill(); - } - }, disconnect_timeout * 1000); - worker.once("disconnect", () => { - clearTimeout(disconnect_timer); - disconnect_received = true; - Server.lognotice("Disconnect complete"); - let dead = false; - const timer = setTimeout(() => { - if (!dead) { - Server.logcrit(`Worker ${id} failed to shutdown. Killing.`); - worker.kill(); + + const todo = [] + + for (const id of Object.keys(cluster.workers)) { + todo.push((id) => { + return new Promise((resolve) => { + Server.lognotice(`Killing worker: ${id}`); + const worker = cluster.workers[id]; + for (const module of ['outbound', 'cfreader', 'plugins']) { + worker.send({event: `${module }.shutdown`}); } - }, exit_timeout * 1000); - worker.once("exit", () => { - dead = true; - clearTimeout(timer); - if (shutdown) cb(); - }); - }); - if (shutdown) return; - const newWorker = cluster.fork(); - newWorker.once("listening", () => { - Server.lognotice("Replacement worker online."); - newWorker.on('exit', (code, signal) => { - cluster_exit_listener(newWorker, code, signal); - }); - cb(); - }); - }, err => { - // err can basically never happen, but fuckit... - if (err) Server.logerror(err); - if (shutdown) { - Server.loginfo("Workers closed. Shutting down master process subsystems"); - for (const module of ['outbound', 'cfreader', 'plugins']) { - process.emit('message', {event: `${module}.shutdown`}); - } - const t2 = setTimeout(shutdown, Server.cfg.main.force_shutdown_timeout * 1000); - return t2.unref(); + worker.disconnect(); + let disconnect_received = false; + const disconnect_timer = setTimeout(() => { + if (!disconnect_received) { + Server.logcrit("Disconnect never received by worker. Killing."); + worker.kill(); + } + }, disconnect_timeout * 1000); + + worker.once('disconnect', () => { + clearTimeout(disconnect_timer); + disconnect_received = true; + Server.lognotice('Disconnect complete'); + let dead = false; + const timer = setTimeout(() => { + if (!dead) { + Server.logcrit(`Worker ${id} failed to shutdown. Killing.`); + worker.kill(); + } + }, exit_timeout * 1000); + worker.once('exit', () => { + dead = true; + clearTimeout(timer); + if (shutdown) resolve() + }) + }) + if (!shutdown) { + const newWorker = cluster.fork(); + newWorker.once('listening', () => { + Server.lognotice('Replacement worker online.'); + newWorker.on('exit', (code, signal) => { + cluster_exit_listener(newWorker, code, signal); + }); + resolve() + }) + } + }) + }) + } + + while (todo.length) { + // process batches of workers + await Promise.all(todo.splice(0, limit)) + } + + if (shutdown) { + Server.loginfo("Workers closed. Shutting down master process subsystems"); + for (const module of ['outbound', 'cfreader', 'plugins']) { + process.emit('message', {event: `${module}.shutdown`}); } - graceful_in_progress = false; - Server.lognotice(`Reload complete, workers: ${JSON.stringify(Object.keys(cluster.workers))}`); - }); + const t2 = setTimeout(shutdown, Server.cfg.main.force_shutdown_timeout * 1000); + return t2.unref(); + } + graceful_in_progress = false; + Server.lognotice(`Reload complete, workers: ${JSON.stringify(Object.keys(cluster.workers))}`); } Server.sendToMaster = (command, params) => { @@ -342,7 +356,7 @@ Server.load_default_tls_config = done => { }) } -Server.get_smtp_server = (ep, inactivity_timeout, done) => { +Server.get_smtp_server = async (ep, inactivity_timeout) => { let server; function onConnect (client) { @@ -364,86 +378,89 @@ Server.get_smtp_server = (ep, inactivity_timeout, done) => { if (ep.port === parseInt(Server.cfg.main.smtps_port, 10)) { Server.loginfo('getting SocketOpts for SMTPS server'); - tls_socket.getSocketOpts('*').then(opts => { - Server.loginfo(`Creating TLS server on ${ep}`); + const opts = await tls_socket.getSocketOpts('*') + Server.loginfo(`Creating TLS server on ${ep}`); - opts.rejectUnauthorized = tls_socket.get_rejectUnauthorized(opts.rejectUnauthorized, ep.port, tls_socket.cfg.main.requireAuthorized) + opts.rejectUnauthorized = tls_socket.get_rejectUnauthorized(opts.rejectUnauthorized, ep.port, tls_socket.cfg.main.requireAuthorized) - server = tls.createServer(opts, onConnect); - tls_socket.addOCSP(server); - server.has_tls=true; - server.on('resumeSession', (id, rsDone) => { - Server.loginfo('client requested TLS resumeSession'); - rsDone(null, null); - }) - Server.listeners.push(server); - done(server); + server = tls.createServer(opts, onConnect); + tls_socket.addOCSP(server); + server.has_tls=true; + server.on('resumeSession', (id, rsDone) => { + Server.loginfo('client requested TLS resumeSession'); + rsDone(null, null); }) + Server.listeners.push(server); + return server } else { server = tls_socket.createServer(onConnect); server.has_tls = false; - tls_socket.getSocketOpts('*').then(opts => { - Server.listeners.push(server); - done(server); - }) + const opts = await tls_socket.getSocketOpts('*') + Server.listeners.push(server); + return server } } -Server.setup_smtp_listeners = (plugins2, type, inactivity_timeout) => { +Server.setup_smtp_listeners = async (plugins2, type, inactivity_timeout) => { - async.each( - Server.get_listen_addrs(Server.cfg.main), // array of listeners + const errors = [] - function setupListener (listen_address, listenerDone) { + for (const listen_address of Server.get_listen_addrs(Server.cfg.main)) { - const ep = endpoint(listen_address, 25); - if (ep instanceof Error) return listenerDone( - new Error(`Invalid "listen" format in smtp.ini: ${listen_address}`)); + const ep = endpoint(listen_address, 25); - Server.get_smtp_server(ep, inactivity_timeout, (server) => { - if (!server) return listenerDone(); + if (ep instanceof Error) { + Server.logerror(`Invalid "listen" format in smtp.ini: ${listen_address}`) + continue + } - server.notes = Server.notes; - if (Server.cluster) server.cluster = Server.cluster; + const server = await Server.get_smtp_server(ep, inactivity_timeout) + if (!server) continue; - server - .on('listening', function () { - const addr = this.address(); - Server.lognotice(`Listening on ${endpoint(addr)}`); - listenerDone(); - }) - .on('close', () => { - Server.loginfo(`Listener ${ep} stopped`); - }) - .on('error', e => { - if (e.code !== 'EAFNOSUPPORT') return listenerDone(e); - // Fallback from IPv6 to IPv4 if not supported - // But only if we supplied the default of [::0]:25 - if (/^::0/.test(ep.host) && Server.default_host) { - server.listen(ep.port, '0.0.0.0', 0); - return; - } - // Pass error to callback - listenerDone(e); - }); - ep.bind(server, {backlog: 0}); - }); - }, - function runInitHooks (err) { - if (err) { - Server.logerror(`Failed to setup listeners: ${err.message}`); - return logger.dump_and_exit(-1); - } - Server.listening(); - plugins2.run_hooks(`init_${type}`, Server); + server.notes = Server.notes; + if (Server.cluster) server.cluster = Server.cluster; + + server + .on('listening', function () { + const addr = this.address(); + Server.lognotice(`Listening on ${endpoint(addr)}`); + }) + .on('close', () => { + Server.loginfo(`Listener ${ep} stopped`); + }) + .on('error', e => { + errors.push(e) + Server.logerror(`Failed to setup listeners: ${e.message}`); + if (e.code !== 'EAFNOSUPPORT') { + Server.logerror(e) + return + } + // Fallback from IPv6 to IPv4 if not supported + // But only if we supplied the default of [::0]:25 + if (/^::0/.test(ep.host) && Server.default_host) { + server.listen(ep.port, '0.0.0.0', 0); + return; + } + // Pass error to callback + Server.logerror(e) + }) + + ep.bind(server, {backlog: 0}); + } + + if (errors.length) { + for (const e of errors) { + Server.logerror(`Failed to setup listeners: ${e.message}`); } - ); + return logger.dump_and_exit(-1); + } + Server.listening(); + plugins2.run_hooks(`init_${type}`, Server); } Server.setup_http_listeners = () => { - if (!Server.http.cfg) return; - if (!Server.http.cfg.listen) return; + if (!Server.http?.cfg?.listen) return; const listeners = Server.get_listen_addrs(Server.http.cfg, 80); if (!listeners.length) return; @@ -453,8 +470,7 @@ Server.setup_http_listeners = () => { Server.loginfo('express loaded at Server.http.express'); } catch (err) { - Server.logerror('express failed to load. No http server. ' + - ' Try installing express with: npm install -g express'); + Server.logerror('express failed to load. No http server. Install express with: npm install -g express'); return; } @@ -462,17 +478,17 @@ Server.setup_http_listeners = () => { Server.http.app = app; Server.loginfo('express app is at Server.http.app'); - function setupListener (listen_address, cb) { + for (const listen_address of listeners) { + const ep = endpoint(listen_address, 80); if (ep instanceof Error) { - return cb(new Error(`Invalid format for listen in http.ini: ${listen_address}`)); + Server.logerror(`Invalid format for listen in http.ini: ${listen_address}`) + continue } if (443 == ep.port) { - // clone the default TLS opts - const tlsOpts = Object.assign({}, tls_socket.certsByHost['*']); + const tlsOpts = { ...tls_socket.certsByHost['*'] } tlsOpts.requestCert = false; // not appropriate for HTTPS - // console.log(tlsOpts); Server.http.server = require('https').createServer(tlsOpts, app); } else { @@ -482,30 +498,19 @@ Server.setup_http_listeners = () => { Server.listeners.push(Server.http.server); Server.http.server.on('listening', function () { - const addr = this.address(); - Server.lognotice(`Listening on ${endpoint(addr)}`); - cb(); - }); + Server.lognotice(`Listening on ${endpoint(this.address())}`); + }) Server.http.server.on('error', e => { Server.logerror(e); - cb(e); - }); + }) ep.bind(Server.http.server, {backlog: 0}); } - function registerRoutes (err) { - if (err) { - Server.logerror(`Failed to setup http routes: ${err.message}`); - } - - Server.plugins.run_hooks('init_http', Server); - app.use(Server.http.express.static(Server.get_http_docroot())); - app.use(Server.handle404); - } - - async.each(listeners, setupListener, registerRoutes); + Server.plugins.run_hooks('init_http', Server); + app.use(Server.http.express.static(Server.get_http_docroot())); + app.use(Server.handle404); } Server.init_master_respond = (retval, msg) => { @@ -636,13 +641,12 @@ Server.init_http_respond = () => { Server.init_wss_respond = () => { Server.loginfo('init_wss_respond'); - // Server.logdebug(arguments); } Server.get_http_docroot = () => { if (Server.http.cfg.docroot) return Server.http.cfg.docroot; - Server.http.cfg.docroot = path.join( (process.env.HARAKA || __dirname), '/html'); + Server.http.cfg.docroot = path.join( (process.env.HARAKA || __dirname), 'http', 'html'); Server.loginfo(`using html docroot: ${Server.http.cfg.docroot}`); return Server.http.cfg.docroot; } diff --git a/test/fixtures/util_hmailitem.js b/test/fixtures/util_hmailitem.js index e3237bb3f..ddc975e44 100644 --- a/test/fixtures/util_hmailitem.js +++ b/test/fixtures/util_hmailitem.js @@ -79,11 +79,7 @@ exports.createHMailItem = (outbound_context, options, callback) => { const hmails = []; const ok_paths = []; - outbound_context.exports.process_delivery(ok_paths, todo, hmails, err => { - if (err) { - callback(`process_delivery error: ${err}`); - return; - } + outbound_context.exports.process_delivery(ok_paths, todo, hmails).then(() => { if (hmails.length == 0) { callback('No hmail producted'); return; @@ -92,8 +88,10 @@ exports.createHMailItem = (outbound_context, options, callback) => { hmail.hostlist = [ delivery_domain ]; callback(null, hmail); } - }); - + }) + .catch(err => { + callback(`process_delivery error: ${err}`); + }) } /** diff --git a/test/server.js b/test/server.js index ed199073b..a2039457d 100644 --- a/test/server.js +++ b/test/server.js @@ -135,7 +135,7 @@ describe('server', () => { }) it('gets a net server object', (done) => { - this.server.get_smtp_server(endpoint('0.0.0.0:2501'), 10, (server) => { + this.server.get_smtp_server(endpoint('0.0.0.0:2501'), 10).then(server => { if (!server) { console.error('unable to bind to 0.0.0.0:2501'); if (process.env.CI) return // can't bind to IP/port (fails on Travis) @@ -151,7 +151,7 @@ describe('server', () => { it('gets a TLS net server object', (done) => { this.server.cfg.main.smtps_port = 2502; - this.server.get_smtp_server(endpoint('0.0.0.0:2502'), 10, (server) => { + this.server.get_smtp_server(endpoint('0.0.0.0:2502'), 10).then((server) => { if (!server) { console.error('unable to bind to 0.0.0.0:2502'); if (process.env.CI) return // can't bind to IP/port (fails on Travis) diff --git a/tls_socket.js b/tls_socket.js index 5876f2b8b..a4e04b2a2 100644 --- a/tls_socket.js +++ b/tls_socket.js @@ -660,7 +660,6 @@ function getCertFor (host) { return certsByHost['*']; // the default TLS cert } - function connect (conn_options = {}) { // called by outbound/client_pool, smtp_client, plugins/spamassassin,avg,clamd