From b22f8efa31991faf18025be0307415fb577cbbf8 Mon Sep 17 00:00:00 2001 From: Zack Schuster Date: Thu, 28 Jun 2018 17:55:20 -0700 Subject: [PATCH] add jsdoc types to client --- smtp/client.js | 193 ++++++++++++++++++++++++++++++++++++----------- smtp/date.js | 1 - smtp/message.js | 12 +-- smtp/response.js | 1 + smtp/smtp.js | 38 +++++----- 5 files changed, 169 insertions(+), 76 deletions(-) diff --git a/smtp/client.js b/smtp/client.js index 57b4085..c14f9ec 100644 --- a/smtp/client.js +++ b/smtp/client.js @@ -3,16 +3,60 @@ const { Message, create } = require('./message'); const addressparser = require('addressparser'); class Client { + /** + * @typedef {Object} SMTPOptions + * @property {number} [timeout] + * @property {string} [user] + * @property {string} [password] + * @property {string} [domain] + * @property {string} [host] + * @property {number} [port] + * @property {boolean} [ssl] + * @property {boolean} [tls] + * @property {string[]} [authentication] + * + * @typedef {Object} MessageStack + * @property {Function} [callback] + * @property {Message} message + * @property {string} [returnPath] + * @property {string} [from] + * @property {Array} [to] + * @property {Array} [cc] + * @property {Array} [bcc] + * @property {string} [text] + * @property {*} [attachment] + * + * @constructor + * @param {SMTPOptions} server smtp options + */ constructor(server) { this.smtp = new SMTP(server); //this.smtp.debug(1); + /** + * @type {MessageStack[]} + */ this.queue = []; + + /** + * @type {NodeJS.Timer} + */ this.timer = null; + + /** + * @type {boolean} + */ this.sending = false; + + /** + * @type {boolean} + */ this.ready = false; } + /** + * @returns {void} + */ _poll() { clearTimeout(this.timer); @@ -34,7 +78,15 @@ class Client { } } + /** + * @param {MessageStack} stack stack + * @returns {void} + */ _connect(stack) { + /** + * @param {Error} err callback error + * @returns {void} + */ const connect = err => { if (!err) { const begin = err => { @@ -68,66 +120,85 @@ class Client { this.smtp.connect(connect); } + /** + * @param {Message|MessageStack} msg msg + * @param {Function} callback callback + * @returns {void} + */ send(msg, callback) { - if ( - !(msg instanceof Message) && - msg.from && - (msg.to || msg.cc || msg.bcc) && - (msg.text !== undefined || this._containsInlinedHtml(msg.attachment)) - ) { - msg = create(msg); - } + const canMakeMessage = m => { + return ( + m.from && + (m.to || m.cc || m.bcc) && + (m.text !== undefined || this._containsInlinedHtml(m.attachment)) + ); + }; + /** + * @type {Message} + */ + const message = + msg instanceof Message ? msg : canMakeMessage(msg) ? create(msg) : null; - if (msg instanceof Message) { - msg.valid((valid, why) => { - if (valid) { - const stack = { - message: msg, - to: addressparser(msg.header.to), - from: addressparser(msg.header.from)[0].address, - callback: (callback || function() {}).bind(this), - }; - - if (msg.header.cc) { - stack.to = stack.to.concat(addressparser(msg.header.cc)); - } - - if (msg.header.bcc) { - stack.to = stack.to.concat(addressparser(msg.header.bcc)); - } - - if ( - msg.header['return-path'] && - addressparser(msg.header['return-path']).length - ) { - stack.returnPath = addressparser( - msg.header['return-path'] - )[0].address; - } - - this.queue.push(stack); - this._poll(); - } else { - callback(new Error(why), msg); - } - }); - } else { + if (message == null) { callback(new Error('message is not a valid Message instance'), msg); + return; } + + message.valid((valid, why) => { + if (valid) { + /** + * @type {MessageStack} + */ + const stack = { + message: message, + to: addressparser(message.header.to), + from: addressparser(message.header.from)[0].address, + callback: (callback || function() {}).bind(this), + }; + + if (message.header.cc) { + stack.to = stack.to.concat(addressparser(message.header.cc)); + } + + if (message.header.bcc) { + stack.to = stack.to.concat(addressparser(message.header.bcc)); + } + + if ( + message.header['return-path'] && + addressparser(message.header['return-path']).length + ) { + stack.returnPath = addressparser( + message.header['return-path'] + )[0].address; + } + + this.queue.push(stack); + this._poll(); + } else { + callback(new Error(why), msg); + } + }); } + /** + * @param {*} attachment attachment + * @returns {boolean} does contain + */ _containsInlinedHtml(attachment) { if (Array.isArray(attachment)) { - return attachment.some(() => { - return att => { - return this._isAttachmentInlinedHtml(att); - }; + return attachment.some(att => { + return this._isAttachmentInlinedHtml(att); }); } else { return this._isAttachmentInlinedHtml(attachment); } } + /** + * @param {*} attachment attachment + * @returns {boolean} is inlined + */ _isAttachmentInlinedHtml(attachment) { return ( attachment && @@ -136,7 +207,16 @@ class Client { ); } + /** + * @param {MessageStack} stack stack + * @param {Function} next next + * @returns {Function} callback + */ _sendsmtp(stack, next) { + /** + * @param {Error} [err] error + * @returns {void} + */ return err => { if (!err && next) { next.apply(this, [stack]); @@ -148,12 +228,20 @@ class Client { }; } + /** + * @param {MessageStack} stack stack + * @returns {void} + */ _sendmail(stack) { const from = stack.returnPath || stack.from; this.sending = true; this.smtp.mail(this._sendsmtp(stack, this._sendrcpt), '<' + from + '>'); } + /** + * @param {MessageStack} stack stack + * @returns {void} + */ _sendrcpt(stack) { const to = stack.to.shift().address; this.smtp.rcpt( @@ -162,10 +250,18 @@ class Client { ); } + /** + * @param {MessageStack} stack stack + * @returns {void} + */ _senddata(stack) { this.smtp.data(this._sendsmtp(stack, this._sendmessage)); } + /** + * @param {MessageStack} stack stack + * @returns {void} + */ _sendmessage(stack) { const stream = stack.message.stream(); @@ -184,6 +280,11 @@ class Client { }); } + /** + * @param {Error} err err + * @param {MessageStack} stack stack + * @returns {void} + */ _senddone(err, stack) { this.sending = false; stack.callback(err, stack.message); diff --git a/smtp/date.js b/smtp/date.js index 52287f1..ab09a1a 100644 --- a/smtp/date.js +++ b/smtp/date.js @@ -23,7 +23,6 @@ function getRFC2822Date(date = new Date(), useUtc = false) { return dates.join(' '); } /** - * * @param {Date} [date] an optional date to convert to RFC2822 format (UTC) * @returns {string} the converted date */ diff --git a/smtp/message.js b/smtp/message.js index 3b9b8f0..debc3fe 100644 --- a/smtp/message.js +++ b/smtp/message.js @@ -166,15 +166,7 @@ class Message { } /** - * This callback is displayed as part of the Requester class. - * @callback validCallback - * @param {boolean} isValid isValid - * @param {string} [message] message - * @returns {void} - */ - - /** - * @param {validCallback} callback the function to call with validation info + * @param {function(boolean, string): void} callback This callback is displayed as part of the Requester class. * @returns {void} */ valid(callback) { @@ -185,7 +177,7 @@ class Message { if (!(this.header.to || this.header.cc || this.header.bcc)) { callback(false, 'message does not have a valid recipient'); } else if (this.attachments.length === 0) { - callback(true); + callback(true, undefined); } else { const failed = []; diff --git a/smtp/response.js b/smtp/response.js index 981484e..dcea031 100644 --- a/smtp/response.js +++ b/smtp/response.js @@ -121,6 +121,7 @@ class SMTPResponse { stream.setTimeout(timeout, timedout); } } + /** * @param {Socket | TLSSocket} stream the open socket to stream a response from * @param {number} timeout the time to wait (in milliseconds) before closing the socket diff --git a/smtp/smtp.js b/smtp/smtp.js index cd1d918..2266bac 100644 --- a/smtp/smtp.js +++ b/smtp/smtp.js @@ -35,8 +35,8 @@ const log = (...args) => { }; /** - * @param {Function} callback the function to call - * @param {...any} args the arguments to apply to the function + * @param {function(...*): void} callback the function to call + * @param {...*} args the arguments to apply to the function * @returns {void} */ const caller = (callback, ...args) => { @@ -193,7 +193,7 @@ class SMTP extends EventEmitter { * @typedef {Object} ConnectOptions * @property {boolean} [ssl] * - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @param {number} [port] the port to use for the connection * @param {string} [host] the hostname to use for the connection * @param {ConnectOptions} [options={}] the options @@ -332,7 +332,7 @@ class SMTP extends EventEmitter { /** * @param {string} cmd command to issue - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @param {(number[] | number)} [codes=[250]] array codes * @returns {void} */ @@ -371,7 +371,7 @@ class SMTP extends EventEmitter { * Hostname to send for self command defaults to the FQDN of the local * host. * - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @param {string} domain the domain to associate with the 'helo' request * @returns {void} */ @@ -387,7 +387,7 @@ class SMTP extends EventEmitter { } /** - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @returns {void} */ starttls(callback) { @@ -445,7 +445,7 @@ class SMTP extends EventEmitter { } /** - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @param {string} domain the domain to associate with the 'ehlo' request * @returns {void} */ @@ -476,7 +476,7 @@ class SMTP extends EventEmitter { /** * SMTP 'help' command, returns text from the server - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @param {string} domain the domain to associate with the 'help' request * @returns {void} */ @@ -485,7 +485,7 @@ class SMTP extends EventEmitter { } /** - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @returns {void} */ rset(callback) { @@ -493,7 +493,7 @@ class SMTP extends EventEmitter { } /** - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @returns {void} */ noop(callback) { @@ -501,7 +501,7 @@ class SMTP extends EventEmitter { } /** - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @param {string} from the sender * @returns {void} */ @@ -510,7 +510,7 @@ class SMTP extends EventEmitter { } /** - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @param {string} to the receiver * @returns {void} */ @@ -519,7 +519,7 @@ class SMTP extends EventEmitter { } /** - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @returns {void} */ data(callback) { @@ -527,7 +527,7 @@ class SMTP extends EventEmitter { } /** - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @returns {void} */ data_end(callback) { @@ -547,7 +547,7 @@ class SMTP extends EventEmitter { * SMTP 'verify' command -- checks for address validity. * * @param {string} address the address to validate - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @returns {void} */ verify(address, callback) { @@ -558,7 +558,7 @@ class SMTP extends EventEmitter { * SMTP 'expn' command -- expands a mailing list. * * @param {string} address the mailing list to expand - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @returns {void} */ expn(address, callback) { @@ -571,7 +571,7 @@ class SMTP extends EventEmitter { * If there has been no previous EHLO or HELO command self session, self * method tries ESMTP EHLO first. * - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @param {string} [domain] the domain to associate with the command * @returns {void} */ @@ -597,7 +597,7 @@ class SMTP extends EventEmitter { * * This method will return normally if the authentication was successful. * - * @param {Function} callback function to call after response + * @param {function(...*): void} callback function to call after response * @param {string} [user] the username to authenticate with * @param {string} [password] the password for the authentication * @param {{ method: string, domain: string }} [options] login options @@ -768,7 +768,7 @@ class SMTP extends EventEmitter { } /** - * @param {Function} [callback] function to call after response + * @param {function(...*): void} [callback] function to call after response * @returns {void} */ quit(callback) {