diff --git a/package.json b/package.json index 9c59c78c..62cbb13c 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "node-red": "^2.1.4", "node-red-node-test-helper": "^0.2.7", "nodemailer": "^6.7.2", - "poplib": "^0.1.7", + "node-pop3": "^0.8.0", "proxyquire": "^2.1.3", "pushbullet": "^2.4.0", "sentiment": "^2.1.0", diff --git a/social/email/61-email.js b/social/email/61-email.js index 275e90e5..f51c6710 100644 --- a/social/email/61-email.js +++ b/social/email/61-email.js @@ -6,7 +6,7 @@ const { domainToUnicode } = require("url"); * POP3 protocol - RFC1939 - https://www.ietf.org/rfc/rfc1939.txt * * Dependencies: - * * poplib - https://www.npmjs.com/package/poplib + * * node-pop3 - https://www.npmjs.com/package/node-pop3 * * nodemailer - https://www.npmjs.com/package/nodemailer * * imap - https://www.npmjs.com/package/imap * * mailparser - https://www.npmjs.com/package/mailparser @@ -16,7 +16,7 @@ module.exports = function(RED) { "use strict"; var util = require("util"); var Imap = require('imap'); - var POP3Client = require("./poplib.js"); + var Pop3Command = require("node-pop3"); var nodemailer = require("nodemailer"); var simpleParser = require("mailparser").simpleParser; var SMTPServer = require("smtp-server").SMTPServer; @@ -178,6 +178,7 @@ module.exports = function(RED) { // Setup the EmailInNode function EmailInNode(n) { var imap; + var pop3; RED.nodes.createNode(this,n); this.name = n.name; @@ -272,106 +273,75 @@ module.exports = function(RED) { // Check the POP3 email mailbox for any new messages. For any that are found, // retrieve each message, call processNewMessage to process it and then delete // the messages from the server. - function checkPOP3(msg,send,done) { - var currentMessage; - var maxMessage; - //node.log("Checking POP3 for new messages"); - - // Form a new connection to our email server using POP3. - var pop3Client = new POP3Client( - node.inport, node.inserver, - {enabletls: node.useSSL} // Should we use SSL to connect to our email server? - ); - - // If we have a next message to retrieve, ask to retrieve it otherwise issue a - // quit request. - function nextMessage() { - if (currentMessage > maxMessage) { - pop3Client.quit(); - setInputRepeatTimeout(); - done(); - return; - } - pop3Client.retr(currentMessage); - currentMessage++; - } // End of nextMessage - - pop3Client.on("stat", function(status, data) { - // Data contains: - // { - // count: - // octect: - // } - if (status) { - currentMessage = 1; - maxMessage = data.count; - nextMessage(); - } else { - node.log(util.format("stat error: %s %j", status, data)); - } + async function checkPOP3(msg,send,done) { + var tout = (node.repeat > 0) ? node.repeat - 500 : 15000; + var currentMessage = 1; + var maxMessage = 0; + var nextMessage; + + pop3 = new Pop3Command({ + "host": node.inserver, + "tls": node.useSSL, + "timeout": tout, + "port": node.inport }); + try { + node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"}); + await pop3.connect(); - pop3Client.on("error", function(err) { + await pop3.command('USER', node.userid); + await pop3.command('PASS', node.password); + } catch(err) { + node.error(err.message,err); + node.status({fill:"red",shape:"ring",text:"email.status.connecterror"}); setInputRepeatTimeout(); - node.log("error: " + JSON.stringify(err)); done(); - }); - - pop3Client.on("connect", function() { - //node.log("We are now connected"); - pop3Client.login(node.userid, node.password); - }); - - pop3Client.on("login", function(status, rawData) { - //node.log("login: " + status + ", " + rawData); - if (status) { - pop3Client.stat(); - } else { - node.log(util.format("login error: %s %j", status, rawData)); - pop3Client.quit(); - setInputRepeatTimeout(); - done(); + return; + } + maxMessage = (await pop3.STAT()).split(" ")[0]; + if(maxMessage>0) { + node.status({fill:"blue", shape:"dot", text:"email.status.fetching"}); + while(currentMessage<=maxMessage) { + try { + nextMessage = await pop3.RETR(currentMessage); + } catch(err) { + node.error(RED._("email.errors.fetchfail", err.message),err); + node.status({fill:"red",shape:"ring",text:"email.status.fetcherror"}); + setInputRepeatTimeout(); + done(); + return; + } + try { + // We have now received a new email message. Create an instance of a mail parser + // and pass in the email message. The parser will signal when it has parsed the message. + simpleParser(nextMessage, {}, function(err, parsed) { + //node.log(util.format("simpleParser: on(end): %j", mailObject)); + if (err) { + node.status({fill:"red", shape:"ring", text:"email.status.parseerror"}); + node.error(RED._("email.errors.parsefail", {folder:node.box}), err); + } + else { + processNewMessage(msg, parsed); + } + }); + //processNewMessage(msg, nextMessage); + } catch(err) { + node.error(RED._("email.errors.parsefail", {folder:node.box}), err); + node.status({fill:"red",shape:"ring",text:"email.status.parseerror"}); + setInputRepeatTimeout(); + done(); + return; + } + await pop3.DELE(currentMessage); + currentMessage++; } - }); + await pop3.QUIT(); + node.status({fill:"green",shape:"dot",text:"finished"}); + setTimeout(status_clear, 5000); + setInputRepeatTimeout(); + done(); + } - pop3Client.on("retr", function(status, msgNumber, data, rawData) { - // node.log(util.format("retr: status=%s, msgNumber=%d, data=%j", status, msgNumber, data)); - if (status) { - // We have now received a new email message. Create an instance of a mail parser - // and pass in the email message. The parser will signal when it has parsed the message. - simpleParser(data, {}, function(err, parsed) { - //node.log(util.format("simpleParser: on(end): %j", mailObject)); - if (err) { - node.status({fill:"red", shape:"ring", text:"email.status.parseerror"}); - node.error(RED._("email.errors.parsefail", {folder:node.box}), err); - } - else { - processNewMessage(msg, parsed); - } - }); - pop3Client.dele(msgNumber); - } - else { - node.log(util.format("retr error: %s %j", status, rawData)); - pop3Client.quit(); - setInputRepeatTimeout(); - done(); - } - }); - - pop3Client.on("invalid-state", function(cmd) { - node.log("Invalid state: " + cmd); - }); - - pop3Client.on("locked", function(cmd) { - node.log("We were locked: " + cmd); - }); - - // When we have deleted the last processed message, we can move on to - // processing the next message. - pop3Client.on("dele", function(status, msgNumber) { - nextMessage(); - }); } // End of checkPOP3 @@ -595,6 +565,10 @@ module.exports = function(RED) { } }); + function status_clear() { + node.status({}); + } + function setInputRepeatTimeout() { // Set the repetition timer as needed if (!isNaN(node.repeat) && node.repeat > 0) { diff --git a/social/email/package.json b/social/email/package.json index f71a40cc..fe1d19e0 100644 --- a/social/email/package.json +++ b/social/email/package.json @@ -4,12 +4,14 @@ "description": "Node-RED nodes to send and receive simple emails.", "dependencies": { "imap": "^0.8.19", + "node-pop3": "^0.8.0", "mailparser": "~3.5.0", "nodemailer": "^6.8.0", "smtp-server": "^3.11.0" }, "bundledDependencies": [ "imap", + "node-pop3", "mailparser", "nodemailer", "smtp-server" diff --git a/social/email/poplib.js b/social/email/poplib.js deleted file mode 100644 index 9fcaa80f..00000000 --- a/social/email/poplib.js +++ /dev/null @@ -1,859 +0,0 @@ -/* - - Node.js POP3 client library - - Copyright (C) 2011-2013 by Ditesh Shashikant Gathani - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - -*/ - -var net = require("net"), - tls = require("tls"), - util = require("util"), - crypto = require("crypto"), - events = require("events"); - -// Constructor -function POP3Client(port, host, options) { - - if (options === undefined) { options = {}; } - - // Optional constructor arguments - var enabletls = options.enabletls !== undefined ? options.enabletls: false; - var ignoretlserrs = options.ignoretlserrs !== undefined ? options.ignoretlserrs: false; - var debug = options.debug || false; - - var tlsDirectOpts = options.tlsopts !== undefined ? options.tlsopts: {}; - - // Private variables follow - var self = this; - var response = null; - var checkResp = true; - var bufferedData = ""; - var state = 0; - var locked = false; - var multiline = false; - var socket = null; - var tlssock = null; - var callback = function(resp, data) { - - if (resp === false) { - - locked = false; - callback = function() {}; - self.emit("connect", false, data); - - } else { - - // Checking for APOP support - var banner = data.trim(); - var bannerComponents = banner.split(" "); - - for(var i=0; i < bannerComponents.length; i++) { - - if (bannerComponents[i].indexOf("@") > 0) { - - self.data["apop"] = true; - self.data["apop-timestamp"] = bannerComponents[i]; - break; - - } - } - - state = 1; - self.data["banner"] = banner; - self.emit("connect", true, data); - - } - }; - - // Public variables follow - this.data = { - - host: host, - port: port, - banner: "", - stls: false, - apop: false, - username: "", - tls: enabletls, - ignoretlserrs: ignoretlserrs - - }; - - // Privileged methods follow - this.setCallback = function(cb) { callback = cb; }; - this.getCallback = function() { return callback }; - this.setState = function(val) { state = val; }; - this.getState = function() { return state; }; - this.setLocked = function(val) { locked = val; }; - this.getLocked = function() { return locked; }; - this.setMultiline = function(val) { multiline = val; }; - this.getMultiline = function() { return multiline; }; - - // Writes to remote server socket - this.write = function(command, argument) { - - var text = command; - - if (argument !== undefined) { text = text + " " + argument + "\r\n"; } - else { text = text + "\r\n"; } - - if (debug) { console.log("Client: " + util.inspect(text)); } - - socket.write(text); - - }; - - // Kills the socket connection - this.end = function() { - socket.end(); - }; - - // Upgrades a standard unencrypted TCP connection to use TLS - // Liberally copied and modified from https://gist.github.com/848444 - // starttls() should be a private function, but I can't figure out - // how to get a public prototypal method (stls) to talk to private method (starttls) - // which references private variables without going through a privileged method - this.starttls = function(options) { - - var s = socket; - s.removeAllListeners("end"); - s.removeAllListeners("data"); - s.removeAllListeners("error"); - socket=null; - - var sslcontext = require('crypto').createCredentials(options); - var pair = tls.createSecurePair(sslcontext, false); - var cleartext = pipe(pair); - - pair.on('secure', function() { - - var verifyError = pair.ssl.verifyError(); - cleartext.authorized = true; - - if (verifyError) { - - cleartext.authorized = false; - cleartext.authorizationError = verifyError; - - } - - cleartext.on("data", onData); - cleartext.on("error", onError); - cleartext.on("end", onEnd); - socket=cleartext; - (self.getCallback())(cleartext.authorized, cleartext.authorizationError); - - }); - - cleartext._controlReleased = true; - - function pipe(pair) { - - pair.encrypted.pipe(s); - s.pipe(pair.encrypted); - - pair.fd = s.fd; - var cleartext = pair.cleartext; - cleartext.socket = s; - cleartext.encrypted = pair.encrypted; - cleartext.authorized = false; - - function onerror(e) { - if (cleartext._controlReleased) { cleartext.emit('error', e); } - } - - function onclose() { - s.removeListener('error', onerror); - s.removeListener('close', onclose); - } - - s.on('error', onerror); - s.on('close', onclose); - return cleartext; - - } - }; - - // Private methods follow - // Event handlers follow - function onData(data) { - - data = data.toString("ascii"); - bufferedData += data; - - if (debug) { console.log("Server: " + util.inspect(data)); } - - if (checkResp === true) { - - if (bufferedData.substr(0, 3) === "+OK") { - - checkResp = false; - response = true; - - } else if (bufferedData.substr(0, 4) === "-ERR") { - - checkResp = false; - response = false; - - // The following is only used for SASL - } else if (multiline === false) { - - checkResp = false; - response = true; - - } - } - - if (checkResp === false) { - - if (multiline === true && (response === false || bufferedData.substr(bufferedData.length-5) === "\r\n.\r\n")) { - - // Make a copy to avoid race conditions - var responseCopy = response; - var bufferedDataCopy = bufferedData; - - response = null; - checkResp = true; - multiline = false; - bufferedData = ""; - - callback(responseCopy, bufferedDataCopy); - - } else if (multiline === false) { - - // Make a copy to avoid race conditions - var responseCopy = response; - var bufferedDataCopy = bufferedData; - - response = null; - checkResp = true; - multiline = false; - bufferedData = ""; - - callback(responseCopy, bufferedDataCopy); - - } - } - } - - function onError(err) { - if (err.errno === 111) { self.emit("connect", false, err); } - else { self.emit("error", err); } - } - - function onEnd(data) { - self.setState(0); - socket = null; - } - - function onClose() { - self.emit("close"); - } - - // Constructor code follows - // Set up EventEmitter constructor function - events.EventEmitter.call(this); - - // Remote end socket - if (enabletls === true) { - - tlssock = tls.connect({ - host: host, - port: port, - rejectUnauthorized: !self.data.ignoretlserrs - }, function() { - - if (tlssock.authorized === false && self.data["ignoretlserrs"] === false) { - self.emit("tls-error", tlssock.authorizationError); - } - - } - ); - - socket = tlssock; - - } else { socket = new net.createConnection(port, host); } - - // Set up event handlers - socket.on("data", onData); - socket.on("error", onError); - socket.on("end", onEnd); - socket.on("close", onClose); - -} - -util.inherits(POP3Client, events.EventEmitter); - -POP3Client.prototype.login = function (username, password) { - - var self = this; - - if (self.getState() !== 1) { self.emit("invalid-state", "login"); } - else if (self.getLocked() === true) { self.emit("locked", "login"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - if (resp === false) { - - self.setLocked(false); - self.setCallback(function() {}); - self.emit("login", false, data); - - } else { - - self.setCallback(function(resp, data) { - - self.setLocked(false); - self.setCallback(function() {}); - - if (resp !== false) { self.setState(2); } - self.emit("login", resp, data); - - }); - - self.setMultiline(false); - self.write("PASS", password); - - } - }); - - self.setMultiline(false); - self.write("USER", username); - - } -}; - -// SASL AUTH implementation -// Currently supports SASL PLAIN and CRAM-MD5 -POP3Client.prototype.auth = function (type, username, password) { - - type = type.toUpperCase(); - var self = this; - var types = {"PLAIN": 1, "CRAM-MD5": 1}; - var initialresp = ""; - - if (self.getState() !== 1) { self.emit("invalid-state", "auth"); } - else if (self.getLocked() === true) { self.emit("locked", "auth"); } - - if ((type in types) === false) { - - self.emit("auth", false, "Invalid auth type", null); - return; - - } - - function tlsok() { - - if (type === "PLAIN") { - - initialresp = " " + new Buffer(username + "\u0000" + username + "\u0000" + password).toString("base64") + "="; - self.setCallback(function(resp, data) { - - if (resp !== false) { self.setState(2); } - self.emit("auth", resp, data, data); - - }); - - } else if (type === "CRAM-MD5") { - - self.setCallback(function(resp, data) { - - if (resp === false) { self.emit("auth", resp, "Server responded -ERR to AUTH CRAM-MD5", data); } - else { - - var challenge = new Buffer(data.trim().substr(2), "base64").toString(); - var hmac = crypto.createHmac("md5", password); - var response = new Buffer(username + " " + hmac.update(challenge).digest("hex")).toString("base64"); - - self.setCallback(function(resp, data) { - - var errmsg = null; - - if (resp !== false) { self.setState(2); } - else {errmsg = "Server responded -ERR to response"; } - - self.emit("auth", resp, null, data); - - }); - - self.write(response); - - } - }); - } - - self.write("AUTH " + type + initialresp); - - } - - if (self.data["tls"] === false && self.data["stls"] === false) { - - // Remove all existing STLS listeners - self.removeAllListeners("stls"); - - self.on("stls", function(resp, rawdata) { - - if (resp === false) { - - // We (optionally) ignore self signed cert errors, - // in blatant violation of RFC 2595, Section 2.4 - if (self.data["ignoretlserrs"] === true && rawdata === "DEPTH_ZERO_SELF_SIGNED_CERT"){ tlsok(); } - else { self.emit("auth", false, "Unable to upgrade connection to STLS", rawdata); } - - } else { tlsok(); } - - }); - - self.stls(); - - } else { tlsok(); } -}; - -POP3Client.prototype.apop = function (username, password) { - - var self = this; - - if (self.getState() !== 1) { self.emit("invalid-state", "apop"); } - else if (self.getLocked() === true) { self.emit("locked", "apop"); } - else if (self.data["apop"] === false) { self.emit("apop", false, "APOP support not detected on remote server"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - self.setLocked(false); - self.setCallback(function() {}); - - if (resp === true) { self.setState(2); } - self.emit("apop", resp, data); - - }); - - self.setMultiline(false); - self.write("APOP", username + " " + crypto.createHash("md5").update(self.data["apop-timestamp"] + password).digest("hex")); - - } -}; - -POP3Client.prototype.stls = function() { - - var self = this; - - if (self.getState() !== 1) { self.emit("invalid-state", "stls"); } - else if (self.getLocked() === true) { self.emit("locked", "stls"); } - else if (self.data["tls"] === true) { self.emit("stls", false, "Unable to execute STLS as TLS connection already established"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - self.setLocked(false); - self.setCallback(function() {}); - - if (resp === true) { - - self.setCallback(function(resp, data) { - - if (resp === false && self.data["ignoretlserrs"] === true && data === "DEPTH_ZERO_SELF_SIGNED_CERT") {resp = true; } - self.data["stls"] = true; - self.emit("stls", resp, data); - - }); - - self.starttls(); - - } else { self.emit("stls", false, data); } - }); - - self.setMultiline(false); - self.write("STLS"); - - } -}; - - -POP3Client.prototype.top = function(msgnumber, lines) { - - var self = this; - - if (self.getState() !== 2) { self.emit("invalid-state", "top"); } - else if (self.getLocked() === true) { self.emit("locked", "top"); } - else { - - self.setCallback(function(resp, data) { - - var returnValue = null; - self.setLocked(false); - self.setCallback(function() {}); - - if (resp !== false) { - - returnValue = ""; - var startOffset = data.indexOf("\r\n", 0) + 2; - var endOffset = data.indexOf("\r\n.\r\n", 0) + 2; - - if (endOffset > startOffset) {returnValue = data.substr(startOffset, endOffset-startOffset); } - - } - - self.emit("top", resp, msgnumber, returnValue, data); - - }); - - self.setMultiline(true); - self.write("TOP", msgnumber + " " + lines); - - } -}; - -POP3Client.prototype.list = function(msgnumber) { - - var self = this; - - if (self.getState() !== 2) { self.emit("invalid-state", "list"); } - else if (self.getLocked() === true) { self.emit("locked", "list"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - var returnValue = null; - var msgcount = 0; - self.setLocked(false); - self.setCallback(function() {}); - - if (resp !== false) { - - returnValue = []; - var listitem = ""; - if (msgnumber !== undefined) { - - msgcount = 1 - listitem = data.split(" "); - returnValue[listitem[1]] = listitem[2]; - - } else { - - var offset = 0; - var newoffset = 0; - var returnValue = []; - var startOffset = data.indexOf("\r\n", 0) + 2; - var endOffset = data.indexOf("\r\n.\r\n", 0) + 2; - - if (endOffset > startOffset) { - - data = data.substr(startOffset, endOffset-startOffset); - - while(true) { - - if (offset > endOffset) { break; } - - newoffset = data.indexOf("\r\n", offset); - - if (newoffset < 0) { break; } - - msgcount++; - listitem = data.substr(offset, newoffset-offset); - listitem = listitem.split(" "); - returnValue[listitem[0]] = listitem[1]; - offset = newoffset + 2; - - } - } - } - } - - self.emit("list", resp, msgcount, msgnumber, returnValue, data); - - }); - - if (msgnumber !== undefined) { self.setMultiline(false); } - else { self.setMultiline(true); } - - self.write("LIST", msgnumber); - - } -}; - -POP3Client.prototype.stat = function() { - - var self = this; - - if (self.getState() !== 2) { self.emit("invalid-state", "stat"); } - else if (self.getLocked() === true) { self.emit("locked", "stat"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - var returnValue = null; - self.setLocked(false); - self.setCallback(function() {}); - - if (resp !== false) { - - var listitem = data.split(" "); - returnValue = { - - "count": listitem[1].trim(), - "octets": listitem[2].trim(), - - }; - } - - self.emit("stat", resp, returnValue, data); - - }); - - self.setMultiline(false); - self.write("STAT", undefined); - - } -}; - -POP3Client.prototype.uidl = function(msgnumber) { - - var self = this; - - if (self.getState() !== 2) { self.emit("invalid-state", "uidl"); } - else if (self.getLocked() === true) { self.emit("locked", "uidl"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - var returnValue = null; - self.setLocked(false); - self.setCallback(function() {}); - - if (resp !== false) { - - returnValue = []; - var listitem = ""; - if (msgnumber !== undefined) { - - listitem = data.split(" "); - returnValue[listitem[1]] = listitem[2].trim(); - - } else { - - var offset = 0; - - var newoffset = 0; - var returnValue = []; - var startOffset = data.indexOf("\r\n", 0) + 2; - var endOffset = data.indexOf("\r\n.\r\n", 0) + 2; - - if (endOffset > startOffset) { - - data = data.substr(startOffset, endOffset-startOffset); - endOffset -= startOffset; - - while (offset < endOffset) { - - newoffset = data.indexOf("\r\n", offset); - listitem = data.substr(offset, newoffset-offset); - listitem = listitem.split(" "); - returnValue[listitem[0]] = listitem[1]; - offset = newoffset + 2; - - } - } - } - } - - self.emit("uidl", resp, msgnumber, returnValue, data); - - }); - - if (msgnumber !== undefined) { self.setMultiline(false); } - else { self.setMultiline(true); } - - self.write("UIDL", msgnumber); - - } -}; - -POP3Client.prototype.retr = function(msgnumber) { - - var self = this; - - if (self.getState() !== 2) { self.emit("invalid-state", "retr"); } - else if (self.getLocked() === true) { self.emit("locked", "retr"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - var returnValue = null; - self.setLocked(false); - self.setCallback(function() {}); - - if (resp !== false) { - - var startOffset = data.indexOf("\r\n", 0) + 2; - var endOffset = data.indexOf("\r\n.\r\n", 0); - returnValue = data.substr(startOffset, endOffset-startOffset); - - } - - self.emit("retr", resp, msgnumber, returnValue, data); - - }); - - self.setMultiline(true); - self.write("RETR", msgnumber); - - } -}; - -POP3Client.prototype.dele = function(msgnumber) { - - var self = this; - - if (self.getState() !== 2) { self.emit("invalid-state", "dele"); } - else if (self.getLocked() === true) { self.emit("locked", "dele"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - self.setLocked(false); - self.setCallback(function() {}); - self.emit("dele", resp, msgnumber, data); - - }); - - self.setMultiline(false); - self.write("DELE", msgnumber); - - } -}; - -POP3Client.prototype.noop = function() { - - var self = this; - - if (self.getState() !== 2) { self.emit("invalid-state", "noop"); } - else if (self.getLocked() === true) { self.emit("locked", "noop"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - self.setLocked(false); - self.setCallback(function() {}); - self.emit("noop", resp, data); - - }); - - self.setMultiline(false); - self.write("NOOP", undefined); - - } -}; - -POP3Client.prototype.rset = function() { - - var self = this; - - if (self.getState() !== 2) { self.emit("invalid-state", "rset"); } - else if (self.getLocked() === true) { self.emit("locked", "rset"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - self.setLocked(false); - self.setCallback(function() {}); - self.emit("rset", resp, data); - - }); - - self.setMultiline(false); - self.write("RSET", undefined); - - } -}; - -POP3Client.prototype.capa = function() { - - var self = this; - - if (self.getState() === 0) { self.emit("invalid-state", "quit"); } - else if (self.getLocked() === true) { self.emit("locked", "capa"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - var returnValue = null; - self.setLocked(false); - self.setCallback(function() {}); - - if (resp === true) { - - var startOffset = data.indexOf("\r\n", 0) + 2; - var endOffset = data.indexOf("\r\n.\r\n", 0); - returnValue = data.substr(startOffset, endOffset-startOffset); - returnValue = returnValue.split("\r\n"); - - } - - self.emit("capa", resp, returnValue, data); - - }); - - self.setMultiline(true); - self.write("CAPA", undefined); - - } -}; - -POP3Client.prototype.quit = function() { - - var self = this; - - if (self.getState() === 0) { self.emit("invalid-state", "quit"); } - else if (self.getLocked() === true) { self.emit("locked", "quit"); } - else { - - self.setLocked(true); - self.setCallback(function(resp, data) { - - self.setLocked(false); - self.setCallback(function() {}); - - self.end(); - self.emit("quit", resp, data); - - }); - - self.setMultiline(false); - self.write("QUIT", undefined); - - } -}; - -module.exports = POP3Client; \ No newline at end of file