Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit e9bdb91d018985ae03e1850d736d99beca46fe65 0 parents
@ditesh authored
2  .gitignore
@@ -0,0 +1,2 @@
+.*.sw?
+.lock-wscript
172 README.md
@@ -0,0 +1,172 @@
+# node-pop3-client
+
+node-pop3-client offers an MIT-licensed client library for the POP3 protocol. It is currently RFC1939 compliant and offers the following capabilities:
+
+* USER, PASS
+* LIST, TOP, RETR, DELE
+* UIDL, NOOP, CAPA
+* RSET, QUIT
+* Plaintext and TLS support
+
+## Installation
+
+You have two installation options:
+
+0. Via npm: `npm install node-pop3-client`
+
+1. Download the source and install it yourself
+
+## Usage
+
+node-pop3-client is event based. It is best to illustrate via examples:
+
+Here we initialize the client (for plain text transmission):
+
+````javascript
+var POP3Client = require("node-pop3-client");
+var client = new POP3Client(port, host, tls);
+````
+
+If the tls parameter is true, the library will use a TLS connection. Note that you will have to set the correct port (generally 995).
+
+Next, we trap several common states:
+
+````javascript
+client.on("error", function(err) {
+
+ if (err.errno === 111) console.log("Unable to connect to server");
+ else console.log("Server error occurred");
+
+ console.log(err);
+
+});
+
+client.on("connect", function() {
+
+ console.log("CONNECT success");
+ client.auth(username, password);
+
+});
+
+client.on("invalid-state", function(cmd) {
+ console.log("Invalid state. You tried calling " + cmd);
+});
+
+client.on("locked", function(cmd) {
+ console.log("Current command has not finished yet. You tried calling " + cmd);
+});
+````
+
+The error event is emitted when there is a network error. The Node.js error object is passed back to user-code.
+
+The connect event is emitted when the connection to the remote server is successful.
+
+The invalid-state event is emitted when you try to carry out an action not allowed within your current state (eg, attempting to RETR-ieve a message when authentication has not been completed).
+
+The locked event is emitted when you try to execute another command while the current command has not finished executing successfully (eg, attempting to RETR-ieve a message while the remote server has not finished sending LIST data).
+
+On a successful connect, we try authenticating:
+
+````javascript
+client.on("connect", function() {
+
+ console.log("CONNECT success");
+ client.auth(username, password);
+
+});
+````
+
+Note that on successful auth, we try listing. Note that for all events, the first received argument is always a boolean indicating whether the command succeeded. The last received argument is always the raw unparsed data received from the remote server. The intermediate arguments contain parsed data.
+
+````javascript
+client.on("auth", function(status, rawdata) {
+
+ if (status) {
+
+ console.log("LOGIN/PASS success");
+ client.list();
+
+ } else {
+
+ console.log("LOGIN/PASS failed");
+ client.quit();
+
+ }
+});
+
+// Data is a 1-based index of messages, if there are any messages
+client.on("list", function(status, msgcount, msgnumber, data, rawdata) {
+
+ if (status === false) {
+
+ console.log("LIST failed");
+ client.quit();
+
+ } else {
+
+ console.log("LIST success with " + msgcount + " element(s)");
+
+ if (msgcount > 0)
+ client.retr(1);
+ else
+ client.quit();
+
+ }
+});
+
+client.on("retr", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("RETR success for msgnumber " + msgnumber);
+ client.dele(msgnumber);
+ client.quit();
+
+ } else {
+
+ console.log("RETR failed for msgnumber " + msgnumber);
+ client.quit();
+
+ }
+});
+
+client.on("dele", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("DELE success for msgnumber " + msgnumber);
+ client.quit();
+
+ } else {
+
+ console.log("DELE failed for msgnumber " + msgnumber);
+ client.quit();
+
+ }
+});
+
+client.on("quit", function(status, rawdata) {
+
+ if (status === true) console.log("QUIT success");
+ else console.log("QUIT failed");
+
+});
+
+````
+
+See tests and demos for more examples.
+
+## Demos
+
+For test purposes, you can use the following sendmail.sh script to pump email into your SMTP server for retrieval via POP3:
+
+`./sendmail.sh 10 "user@example.com" "this is my subject" "this is my body"`
+
+
+There is a full-featured POP3 client example in `tests/demo.js`.
+
+There is also a simple example of downloading all emails in a POP3 server and saving it locally in am mbox formatted file in `tests/retrieve-all.js`.
+
+There is a TLS example in `tests/tls.js`.
+
+If you want to try APOP support, see `tests/apop.js`.
627 main.js
@@ -0,0 +1,627 @@
+/*
+
+ Node.js POP3 client library
+
+ Copyright (C) 2011 by Ditesh Shashikant Gathani <ditesh@gathani.org>
+
+ 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"),
+ events = require("events"),
+ hashlib = require("hashlib");
+
+// Constructor
+function POP3Client(port, host, enabletls, debug) {
+
+ // Set up EventEmitter constructor function
+ events.EventEmitter.call(this);
+
+ // Closure variables for socket.on("data")
+ var self = this;
+ var response = null;
+ var checkResp = true;
+ var bufferedData = "";
+
+ // Variables for the object
+ self.state = 0,
+ self.locked = false,
+ self.multiline = false,
+ self.data = {
+
+ apop: false,
+ banner: "",
+ username: "",
+ host: host,
+ port: port,
+ tls: enabletls
+
+ },
+ self.callback = function(resp, data) {
+
+ if (resp === false) {
+
+ self.locked = false;
+ self.callback = function() {};
+ self.emit("connect-failure", 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;
+
+ }
+ }
+
+ self.state = 1;
+ self.data["banner"] = banner;
+ self.emit("connect", data);
+
+ }
+ };
+
+ // Remote end socket
+
+ if (enabletls === true) {
+
+ self.conn = tls.connect(port, host, function() {
+
+ if (self.conn.authorized === false)
+ self.emit("tls-error", self.conn.authorizationError);
+
+ });
+
+ self.socket = self.conn;
+
+ } else {
+
+ self.socket = new net.createConnection(port, host);
+
+ }
+
+ self.socket.on("data", function(data) {
+
+ data = data.toString("ascii");
+ bufferedData += data;
+
+ if (debug) util.log(data);
+
+ if (checkResp === true && bufferedData.substr(0, 3) === "+OK") {
+
+ checkResp = false;
+ response = true;
+
+ } else if (checkResp === true && bufferedData.substr(0, 4) === "-ERR") {
+
+ checkResp = false;
+ response = false;
+
+ }
+
+ if (checkResp === false) {
+
+ if (self.multiline === true && bufferedData.substr(bufferedData.length-5) === "\r\n.\r\n") {
+
+ checkResp = true;
+ self.callback(response, String(bufferedData));
+ self.multiline = false;
+ bufferedData = "";
+ response = null;
+
+ } else if (self.multiline === false) {
+
+ checkResp = true;
+ self.callback(response, bufferedData);
+ self.multiline = false;
+ bufferedData = "";
+ response = null;
+
+ }
+ }
+ });
+
+ self.socket.on("error", function(err) {
+ self.emit("error", err);
+ });
+
+ self.socket.on("end", function(data) {
+
+ self.state = 0;
+ self.socket = null;
+
+ });
+
+ // Private helper methods
+ // Writes to remote server socket
+ self.write = function(command, argument) {
+
+ var text = command;
+
+ if (argument !== undefined)
+ text = text + " " + argument + "\r\n";
+ else
+ text = text + "\r\n";
+
+ if (debug) util.log(text);
+
+ self.socket.write(text);
+
+ };
+}
+
+util.inherits(POP3Client, events.EventEmitter);
+
+POP3Client.prototype.connect = function(port, host) {
+
+ // XXX
+
+};
+
+POP3Client.prototype.auth = function (username, password) {
+
+ var self = this;
+
+ if (self.state !== 1) self.emit("invalid-state", "auth");
+ else if (self.locked === true) self.emit("locked", "auth");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ if (resp === false) {
+
+ self.locked = false;
+ self.callback = function() {};
+ self.emit("auth", false, data);
+
+ } else {
+
+ self.callback = function(resp, data) {
+
+ self.locked = false;
+ self.callback = function() {};
+
+ if (resp !== false)
+ self.state = 2;
+
+ self.emit("auth", resp, data);
+
+ };
+
+ self.multiline = false;
+ self.write("PASS", password);
+
+ }
+ };
+
+ self.multiline = false;
+ self.write("USER", username);
+
+ }
+};
+
+POP3Client.prototype.apop = function (username, password) {
+
+ var self = this;
+
+ if (self.state !== 1) self.emit("invalid-state", "apop");
+ else if (self.locked === true) self.emit("locked", "apop");
+ else if (self.data["apop"] === false) self.emit("apop", false, "APOP support not detected on remote server");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ self.locked = false;
+ self.callback = function() {};
+
+ if (resp === true)
+ self.state = 2;
+
+ self.emit("apop", resp, data);
+
+ };
+
+ self.multiline = false;
+ self.write("APOP", username + " " + hashlib.md5(self.data["apop-timestamp"] + password));
+
+ }
+};
+
+POP3Client.prototype.top = function(msgnumber, lines) {
+
+ var self = this;
+
+ if (self.state !== 2) self.emit("invalid-state", "top");
+ else if (self.locked === true) self.emit("locked", "top");
+ else {
+
+ self.callback = function(resp, data) {
+
+ var returnValue = null;
+ self.locked = false;
+ self.callback = 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.multiline = true;
+ self.write("TOP", msgnumber + " " + lines);
+
+ }
+};
+
+POP3Client.prototype.list = function(msgnumber) {
+
+ var self = this;
+
+ if (self.state !== 2) self.emit("invalid-state", "list");
+ else if (self.locked === true) self.emit("locked", "list");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ var returnValue = null;
+ var msgcount = 0;
+ self.locked = false;
+ self.callback = function() {};
+
+ if (resp !== false) {
+
+ returnValue = [];
+
+ if (msgnumber !== undefined) {
+
+ msgcount = 1
+ listitem = data.split(" ");
+ returnValue[listitem[1]] = listitem[2];
+
+ } else {
+
+ var offset = 0;
+ var listitem = "";
+ 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.multiline = false;
+ else self.multiline = true;
+
+ self.write("LIST", msgnumber);
+
+ }
+};
+
+POP3Client.prototype.stat = function() {
+
+ var self = this;
+
+ if (self.state !== 2) self.emit("invalid-state", "stat");
+ else if (self.locked === true) self.emit("locked", "stat");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ var returnValue = null;
+ self.locked = false;
+ self.callback = function() {};
+
+ if (resp !== false) {
+
+ listitem = data.split(" ");
+ returnValue = {
+
+ "count": listitem[1].trim(),
+ "octets": listitem[2].trim(),
+
+ };
+ }
+
+ self.emit("stat", resp, returnValue, data);
+
+ }
+
+ self.multiline = false;
+ self.write("STAT", undefined);
+
+ }
+};
+
+POP3Client.prototype.uidl = function(msgnumber) {
+
+ var self = this;
+
+ if (self.state !== 2) self.emit("invalid-state", "uidl");
+ else if (self.locked === true) self.emit("locked", "uidl");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ var returnValue = null;
+ self.locked = false;
+ self.callback = function() {};
+
+ if (resp !== false) {
+
+ returnValue = [];
+
+ if (msgnumber !== undefined) {
+
+ listitem = data.split(" ");
+ returnValue[listitem[1]] = listitem[2].trim();
+
+ } else {
+
+ var offset = 0;
+ var listitem = "";
+ 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);
+ 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.multiline = false;
+ else self.multiline = true;
+
+ self.write("UIDL", msgnumber);
+
+ }
+};
+
+POP3Client.prototype.retr = function(msgnumber) {
+
+ var self = this;
+
+ if (self.state !== 2) self.emit("invalid-state", "retr");
+ else if (self.locked === true) self.emit("locked", "retr");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ var returnValue = null;
+ self.locked = false;
+ self.callback = 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.multiline = true;
+ self.write("RETR", msgnumber);
+
+ }
+};
+
+POP3Client.prototype.dele = function(msgnumber) {
+
+ var self = this;
+
+ if (self.state !== 2) self.emit("invalid-state", "dele");
+ else if (self.locked === true) self.emit("locked", "dele");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ self.locked = false;
+ self.callback = function() {};
+ self.emit("dele", resp, msgnumber, data);
+
+ }
+
+ self.multiline = false;
+ self.write("DELE", msgnumber);
+
+ }
+};
+
+POP3Client.prototype.noop = function() {
+
+ var self = this;
+
+ if (self.state !== 2) self.emit("invalid-state", "noop");
+ else if (self.locked === true) self.emit("locked", "noop");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ self.locked = false;
+ self.callback = function() {};
+ self.emit("noop", resp, data);
+
+ }
+
+ self.multiline = false;
+ self.write("NOOP", undefined);
+
+ }
+};
+
+POP3Client.prototype.rset = function() {
+
+ var self = this;
+
+ if (self.state !== 2) self.emit("invalid-state", "rset");
+ else if (self.locked === true) self.emit("locked", "rset");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ self.locked = false;
+ self.callback = function() {};
+ self.emit("rset", resp, data);
+
+ }
+
+ self.multiline = false;
+ self.write("RSET", undefined);
+
+ }
+};
+
+POP3Client.prototype.capa = function() {
+
+ var self = this;
+
+ if (self.locked === true) self.emit("locked", "capa");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ var returnValue = null;
+ self.locked = false;
+ self.callback = 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.multiline = true;
+ self.write("CAPA", undefined);
+
+ }
+};
+
+POP3Client.prototype.quit = function() {
+
+ var self = this;
+
+ if (self.state === 0) self.emit("invalid-state", "quit");
+ else if (self.locked === true) self.emit("locked", "quit");
+ else {
+
+ self.locked = true;
+ self.callback = function(resp, data) {
+
+ self.locked = false;
+ self.callback = function() {};
+
+ self.socket.end();
+ self.emit("quit", resp, data);
+
+ }
+
+ self.multiline = false;
+ self.write("QUIT", undefined);
+
+ }
+};
+
+module.exports = POP3Client;
15 package.json
@@ -0,0 +1,15 @@
+{
+ "name": "pop3-client",
+ "version": "v0.1.0",
+ "description": "POP3 client written in Node.js",
+ "homepage": "https://github.com/ditesh/node-pop3-client",
+ "keywords": ["server", "POP3", "mail", "pop3", "client", "pop", "email"],
+ "author": {
+ "name": "Ditesh Shashikant Gathani",
+ "email": "ditesh@gathani.org",
+ "url": "http://ditesh.gathani.org/blog/"
+ },
+ "dependencies": ["unixlib", "optimist", "simplelogger", "hashlib"]
+ "repository": { "type" : "git", "url" : "https://github.com/ditesh/node-pop3-client.git" },
+ "main": "main.js"
+}
131 tests/apop.js
@@ -0,0 +1,131 @@
+/*
+
+ Node.js POP3 client demo in retrieving all POP3 messages into mbox file
+
+ Copyright (C) 2011 by Ditesh Shashikant Gathani <ditesh@gathani.org>
+
+ 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 POP3Client = require("../main.js");
+var argv = require('optimist')
+ .usage("Usage: $0 --host [host] --port [port] --username [username] --password [password] --debug [on/off] --networkdebug [on/off]")
+ .demand(['username', 'password'])
+ .argv;
+
+var host = argv.host || "localhost";
+var port = argv.port || 995;
+var debug = argv.debug === "on" ? true : false;
+var networkdebug = argv.networkdebug || false;
+var filename = argv.filename;
+var username = argv.username;
+var password = argv.password;
+var totalmsgcount = 0;
+var currentmsg = 0;
+
+var client = new POP3Client(port, host, true, networkdebug);
+
+client.on("error", function(err) {
+
+ if (err.errno === 111) console.log("Unable to connect to server");
+ else console.log("Server error occurred");
+
+ console.log(err);
+
+});
+
+client.on("connect", function() {
+
+ console.log("CONNECT success");
+ client.apop(username, password);
+
+});
+
+client.on("invalid-state", function(cmd) {
+ console.log("Invalid state. You tried calling " + cmd);
+});
+
+client.on("locked", function(cmd) {
+ console.log("Current command has not finished yet. You tried calling " + cmd);
+});
+
+client.on("apop", function(status, data) {
+
+ if (status) {
+
+ console.log("APOP success");
+ client.list();
+
+ } else {
+
+ console.log("APOP failed");
+ client.quit();
+
+ }
+
+});
+
+client.on("list", function(status, msgcount, msgnumber, data, rawdata) {
+
+ if (status === false) {
+
+ console.log("LIST failed");
+ client.quit();
+
+ } else if (msgcount > 0) {
+
+ totalmsgcount = msgcount;
+ currentmsg = 1;
+ console.log("LIST success with " + msgcount + " message(s)");
+ client.retr(1);
+
+ } else {
+
+ console.log("LIST success with 0 message(s)");
+ client.quit();
+
+ }
+});
+
+client.on("retr", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("RETR success " + msgnumber);
+ currentmsg += 1;
+
+ fs.write(fd, new Buffer(data + "\r\n\r\n"), 0, data.length+4, null, function(err, written, buffer) {
+ client.quit();
+ });
+
+ } else {
+
+ console.log("RETR failed for msgnumber " + msgnumber);
+ client.quit();
+
+ }
+});
+
+client.on("quit", function(status, rawdata) {
+
+ if (status === true) console.log("QUIT success");
+ else console.log("QUIT failed");
+
+});
241 tests/demo.js
@@ -0,0 +1,241 @@
+/*
+
+ Node.js POP3 client demo
+
+ Copyright (C) 2011 by Ditesh Shashikant Gathani <ditesh@gathani.org>
+
+ 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 util = require("util");
+var POP3Client = require("../main.js");
+var argv = require('optimist')
+ .usage("Usage: $0 --host [host] --port [port] --username [username] --password [password] --debug [on/off] --networkdebug [on/off] --msgnumber [number]")
+ .demand(['username', 'password'])
+ .argv;
+
+var host = argv.host || "localhost";
+var port = argv.port || 110;
+var debug = argv.debug === "on" ? true : false;
+var networkdebug = argv.networkdebug || false;
+var msgnumber = argv.msgnumber;
+var username = argv.username;
+var password = argv.password;
+
+var client = new POP3Client(port, host, false, networkdebug);
+
+client.on("error", function(err) {
+
+ if (err.errno === 111) console.log("Unable to connect to server");
+ else console.log("Server error occurred");
+
+ console.log(err);
+
+});
+
+client.on("connect", function(rawdata) {
+
+ console.log("CONNECT success");
+ client.auth(username, password);
+
+});
+
+client.on("invalid-state", function(cmd) {
+ console.log("Invalid state. You tried calling " + cmd);
+});
+
+client.on("locked", function(cmd) {
+ console.log("Current command has not finished yet. You tried calling " + cmd);
+});
+
+client.on("auth", function(status, rawdata) {
+
+ if (status) {
+
+ console.log("LOGIN/PASS success");
+ client.capa();
+
+ } else {
+
+ console.log("LOGIN/PASS failed");
+ client.quit();
+
+ }
+
+});
+
+client.on("capa", function(status, data, rawdata) {
+
+ if (status) {
+
+ console.log("CAPA success");
+ if (debug) console.log(" Parsed data: " + util.inspect(data));
+ client.noop();
+
+ } else {
+
+ console.log("CAPA failed");
+ client.quit();
+
+ }
+
+});
+
+
+client.on("noop", function(status, rawdata) {
+
+ if (status) {
+
+ console.log("NOOP success");
+ client.stat();
+
+ } else {
+
+ console.log("NOOP failed");
+ client.quit();
+
+ }
+
+});
+
+
+client.on("stat", function(status, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("STAT success");
+ if (debug) console.log(" Parsed data: " + util.inspect(data));
+ client.list(msgnumber);
+
+ } else {
+
+ console.log("STAT failed");
+ client.quit();
+
+ }
+});
+
+client.on("list", function(status, msgcount, msgnumber, data, rawdata) {
+
+ if (status === false) {
+
+ if (msgnumber !== undefined)
+ console.log("LIST failed for msgnumber " + msgnumber);
+ else
+ console.log("LIST failed");
+
+ client.quit();
+
+ } else if (msgcount === 0) {
+
+ console.log("LIST success with 0 elements");
+ client.quit();
+
+ } else {
+
+ console.log("LIST success with " + msgcount + " element(s)");
+ client.uidl(msgnumber);
+
+ }
+});
+
+client.on("uidl", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("UIDL success for msgnumber " + msgnumber);
+ if (debug) console.log(" Parsed data: " + data);
+ client.top(msgnumber, 10);
+
+ } else {
+
+ console.log("UIDL failed for msgnumber " + msgnumber);
+ client.quit();
+
+ }
+});
+
+
+client.on("top", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("TOP success for msgnumber " + msgnumber);
+ if (debug) console.log(" Parsed data: " + data);
+ client.retr(msgnumber);
+
+ } else {
+
+ console.log("TOP failed for msgnumber " + msgnumber);
+ client.quit();
+
+ }
+});
+
+client.on("retr", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("RETR success for msgnumber " + msgnumber);
+ if (debug) console.log(" Parsed data: " + data);
+
+ if (msgnumber !== undefined)
+ client.dele(msgnumber);
+ else
+ client.quit();
+
+ } else {
+
+ console.log("RETR failed for msgnumber " + msgnumber);
+ client.quit();
+
+ }
+});
+
+client.on("dele", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("DELE success for msgnumber " + msgnumber);
+ client.rset();
+
+ } else {
+
+ console.log("DELE failed for msgnumber " + msgnumber);
+ client.quit();
+
+ }
+});
+
+client.on("rset", function(status, rawdata) {
+
+ if (status === true) console.log("RSET success");
+ else console.log("RSET failed");
+
+ client.quit();
+
+});
+
+client.on("quit", function(status, rawdata) {
+
+ if (status === true) console.log("QUIT success");
+ else console.log("QUIT failed");
+
+});
161 tests/retrieve-all.js
@@ -0,0 +1,161 @@
+/*
+
+ Node.js POP3 client demo in retrieving all POP3 messages into mbox file
+
+ Copyright (C) 2011 by Ditesh Shashikant Gathani <ditesh@gathani.org>
+
+ 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 fs = require("fs");
+var POP3Client = require("../main.js");
+var argv = require('optimist')
+ .usage("Usage: $0 --host [host] --port [port] --username [username] --password [password] --filename [filename] --debug [on/off] --networkdebug [on/off] --tls [on/off]")
+ .demand(['username', 'password', 'filename'])
+ .argv;
+
+var host = argv.host || "localhost";
+var port = argv.port || 110;
+var debug = argv.debug === "on" ? true : false;
+var tls = argv.tls === "on" ? true : false;
+var networkdebug = argv.networkdebug || false;
+var filename = argv.filename;
+var username = argv.username;
+var password = argv.password;
+var totalmsgcount = 0;
+var currentmsg = 0;
+
+var fd = fs.openSync(filename, "a+");
+
+var client = new POP3Client(port, host, tls, networkdebug);
+
+client.on("error", function(err) {
+
+ if (err.errno === 111) console.log("Unable to connect to server");
+ else console.log("Server error occurred");
+
+ console.log(err);
+
+});
+
+client.on("connect", function() {
+
+ console.log("CONNECT success");
+ client.auth(username, password);
+
+});
+
+client.on("invalid-state", function(cmd) {
+ console.log("Invalid state. You tried calling " + cmd);
+});
+
+client.on("locked", function(cmd) {
+ console.log("Current command has not finished yet. You tried calling " + cmd);
+});
+
+client.on("auth", function(status, data) {
+
+ if (status) {
+
+ console.log("LOGIN/PASS success");
+ client.list();
+
+ } else {
+
+ console.log("LOGIN/PASS failed");
+ client.quit();
+
+ }
+
+});
+
+client.on("list", function(status, msgcount, msgnumber, data, rawdata) {
+
+ if (status === false) {
+
+ console.log("LIST failed");
+ client.quit();
+
+ } else if (msgcount > 0) {
+
+ totalmsgcount = msgcount;
+ currentmsg = 1;
+ console.log("LIST success with " + msgcount + " message(s)");
+ client.retr(1);
+
+ } else {
+
+ console.log("LIST success with 0 message(s)");
+ client.quit();
+
+ }
+});
+
+client.on("retr", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("RETR success " + msgnumber);
+ currentmsg += 1;
+
+ fs.write(fd, new Buffer(data + "\r\n\r\n"), 0, data.length+4, null, function(err, written, buffer) {
+
+ if (err) client.rset();
+ else client.dele(msgnumber);
+
+ });
+
+ } else {
+
+ console.log("RETR failed for msgnumber " + msgnumber);
+ client.rset();
+
+ }
+});
+
+client.on("dele", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("DELE success for msgnumber " + msgnumber);
+
+ if (currentmsg > totalmsgcount)
+ client.quit();
+ else
+ client.retr(currentmsg);
+
+ } else {
+
+ console.log("DELE failed for msgnumber " + msgnumber);
+ client.rset();
+
+ }
+});
+
+client.on("rset", function(status,rawdata) {
+ client.quit();
+});
+
+client.on("quit", function(status, rawdata) {
+
+ if (status === true) console.log("QUIT success");
+ else console.log("QUIT failed");
+
+});
49 tests/sendmail.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+# Email pumper helper script
+#
+# Copyright (C) 2011 by Ditesh Shashikant Gathani <ditesh@gathani.org>
+#
+# 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.
+
+echo "sendmail.sh v0.1 - a utility to pump email into an SMTP server"
+echo "Copyright (c) 2011 Ditesh Shashikant Gathani <ditesh@gathani.org>"
+echo
+
+if [ $# -ne 4 ]; then
+
+ echo "Usage:"
+ echo " sendmail.sh <number of emails> <to> <subject> <body>"
+ exit 1
+
+fi
+
+echo "Sending $1 email(s)"
+echo " to: $2"
+echo " subject: \"$3\""
+echo " body: \"$4\""
+echo
+
+for i in `seq 1 $1`; do
+ echo -n "."
+ echo "$4" | mail -s "$3" "$2";
+done
+
+echo " done."
+echo
131 tests/tls.js
@@ -0,0 +1,131 @@
+/*
+
+ Node.js POP3 client demo in retrieving all POP3 messages into mbox file
+
+ Copyright (C) 2011 by Ditesh Shashikant Gathani <ditesh@gathani.org>
+
+ 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 POP3Client = require("../main.js");
+var argv = require('optimist')
+ .usage("Usage: $0 --host [host] --port [port] --username [username] --password [password] --debug [on/off] --networkdebug [on/off]")
+ .demand(['username', 'password'])
+ .argv;
+
+var host = argv.host || "localhost";
+var port = argv.port || 995;
+var debug = argv.debug === "on" ? true : false;
+var networkdebug = argv.networkdebug || false;
+var filename = argv.filename;
+var username = argv.username;
+var password = argv.password;
+var totalmsgcount = 0;
+var currentmsg = 0;
+
+var client = new POP3Client(port, host, true, networkdebug);
+
+client.on("error", function(err) {
+
+ if (err.errno === 111) console.log("Unable to connect to server");
+ else console.log("Server error occurred");
+
+ console.log(err);
+
+});
+
+client.on("connect", function() {
+
+ console.log("CONNECT success");
+ client.auth(username, password);
+
+});
+
+client.on("invalid-state", function(cmd) {
+ console.log("Invalid state. You tried calling " + cmd);
+});
+
+client.on("locked", function(cmd) {
+ console.log("Current command has not finished yet. You tried calling " + cmd);
+});
+
+client.on("auth", function(status, data) {
+
+ if (status) {
+
+ console.log("LOGIN/PASS success");
+ client.list();
+
+ } else {
+
+ console.log("LOGIN/PASS failed");
+ client.quit();
+
+ }
+
+});
+
+client.on("list", function(status, msgcount, msgnumber, data, rawdata) {
+
+ if (status === false) {
+
+ console.log("LIST failed");
+ client.quit();
+
+ } else if (msgcount > 0) {
+
+ totalmsgcount = msgcount;
+ currentmsg = 1;
+ console.log("LIST success with " + msgcount + " message(s)");
+ client.retr(1);
+
+ } else {
+
+ console.log("LIST success with 0 message(s)");
+ client.quit();
+
+ }
+});
+
+client.on("retr", function(status, msgnumber, data, rawdata) {
+
+ if (status === true) {
+
+ console.log("RETR success " + msgnumber);
+ currentmsg += 1;
+
+ fs.write(fd, new Buffer(data + "\r\n\r\n"), 0, data.length+4, null, function(err, written, buffer) {
+ client.quit();
+ });
+
+ } else {
+
+ console.log("RETR failed for msgnumber " + msgnumber);
+ client.quit();
+
+ }
+});
+
+client.on("quit", function(status, rawdata) {
+
+ if (status === true) console.log("QUIT success");
+ else console.log("QUIT failed");
+
+});
23 tests/tlstest.js
@@ -0,0 +1,23 @@
+var fs = require("fs");
+var tls = require("tls");
+
+var conn = tls.connect(995, "pop.gmail.com", function() {
+
+ console.log("in callback", conn.authorized, conn.authorizationError);
+
+ });
+
+conn.on("data", function(data) {
+
+ console.log(conn.authorized, conn.authorizationError);
+
+ if (conn.authorized)
+ console.log(data.toString());
+
+});
+
+conn.on("error", function(err) {
+
+ console.log(err);
+
+});
Please sign in to comment.
Something went wrong with that request. Please try again.