node-poplib
node-poplib offers an MIT-licensed client library for the POP3 protocol. It is currently provides the following capabilities:
- USER, PASS, APOP
- LIST, TOP, RETR, DELE
- UIDL, NOOP, CAPA
- RSET, QUIT
- Plaintext and encrypted TLS support
- STLS
- SASL PLAIN CRAM-MD5
It complies to:
- RFC 1939 (POP3)
- RFC 2595 (STLS);
- RFC 5034 (SASL AUTH)
- RFC 2195 (CRAM-MD5)
Installation
You have two installation options:
-
Via npm:
npm install poplib
-
Download the source and install it yourself
Quick demo
Connect to GMail's POP3 servers using the provided demo script as follows:
$ node demos/demo.js --host pop.gmail.com --port 995 --username user@gmail.com --password potato --tls on --debug on --networkdebug on
Server: '+OK Gpop ready for requests from 1.2.3.4 bh7pf61475604pab.24\r\n'
CONNECT success
Client: 'USER user@gmail.com\r\n'
Server: '+OK send PASS\r\n'
Client: 'PASS potato\r\n'
Server: '-ERR [AUTH] Username and password not accepted.\r\n'
LOGIN/PASS failed
Client: 'QUIT\r\n'
Server: '+OK Farewell.\r\n'
QUIT success
Detailed Usage
node-poplib is event based. It is best to illustrate via examples:
Here we initialize the client (for plain text transmission):
var POP3Client = require("poplib");
var client = new POP3Client(port, host, {
tlserrs: false,
enabletls: true,
debug: false
});
The third parameter, options
, takes three options. If enabletls
is true, the library will use a TLS connection. Note that you will have to set the correct port (generally 995). If tlserrs
is true, then TLS errors will be ignored. Finally, the debug
parameter prints out requests and responses.
Next, we trap several common states:
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.login(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 underlying 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:
client.on("connect", function() {
console.log("CONNECT success");
client.login(username, password);
});
Note that on successful login, we try listing. 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.
client.on("login", 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");
});
API
login(username, password)
Self explanatory. This executes USER
and PASS
. Do not use over cleartext channels. Preferably don't use it at all as auth()
implements AUTH
which deprecates the need for USER and PASS. Emits login
event.
apop(username, password)
This executes APOP
. Requires server side support. Preferably don't use it as auth()
implements AUTH
which deprecates the need for USER and PASS. Emits apop
event.
auth(type, username, password)
This executes AUTH
. Requires server side support. Currently only "PLAIN" and "CRAM-MD5" types are supported. Emits auth
event.
stls()
This executes STLS
. Requires server side support (check using capa()
first). According to the RFC's, using STLS
is preferable to a purely TLS connection (although some servers only support purely TLS connections). Emits stls
event.
capa()
This executes CAPA
. Requires server side support. Emits capa
event.
list([msgnumber])
This executes LIST
. If the optional msgnumber
is provided, then LIST msgnumber
is executed. Emits list
event.
top(msgnumber, lines)
This executes TOP
. Requires server side support. msgnumber
and lines
must be provided. TEmits top
event.
stat()
This executes STAT
. Emits stat
event.
uidl([msgnumber])
This executes UIDL
. If the optional msgnumber
is provided, then UIDL msgnumber
is executed. Emits uidl
event.
retr(msgnumber)
This executes RETR
. msgnumber
must be provided. Emits retr
event.
dele(msgnumber)
This executes DELE
. msgnumber
must be provided. Emits dele
event.
rset()
This executes RSET
. Emits rset
event.
noop()
This executes NOOP
. Emits noop
event.
quit()
This executes QUIT
. Emits quit
event.
Events
connect
The connect
event is emitted upon competion of connection attempt (initiated in the constructor). The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- rawdata: string containing success or error message from the server
login
The login
event is emitted upon competion of login()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- rawdata: string containing success or error message from the server
apop
The apop
event is emitted upon competion of apop()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- rawdata: string containing success or error message from the server
auth
The auth
event is emitted upon competion of auth()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- rawdata: string containing success or error message from the server
stls
The stls
event is emitted upon competion of stls()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- rawdata: string containing success or error message from the server
capa
The capa
event is emitted upon competion of capa()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- data: if status is true, this is an array containing list of server capabilities
- rawdata: string containing success or error message from the server
list
The list
event is emitted upon competion of list()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
msgcount: this contains the number of messages return by the
list()
method. If a valid msgnumber was provided, this value will naturally be1
(elsenull
) - msgnumber: if msgnumber was provided to the method, the provided value will be reflected here (else
undefined
) - data: if status is true, this is an array containing list of server capabilities (else
null
) - rawdata: string containing success or error message from the server
top
The top
event is emitted upon competion of top()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- msgnumber: if msgnumber was provided to the method, the provided value will be reflected here (else
undefined
) - data: if status is true, this is an ASCII string containing the returnValue (else
null
) - rawdata: string containing success or error message from the server
stat
The stat
event is emitted upon competion of stat()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- data: if status is true, an object with keys
count
andoctet
(elsenull
) - rawdata: string containing success or error message from the server
uidl
The uidl
event is emitted upon competion of uidl()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- msgnumber: if msgnumber was provided to the method, the provided value will be reflected here (else
undefined
) - data: if status is true, this is an array containing the UIDL list (else
null
) - rawdata: string containing success or error message from the server
retr
The retr
event is emitted upon competion of retr()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- msgnumber: the
msgnumber
provided to the method - data: if status is
true
, the results are returned as an ASCII string (elsenull
) - rawdata: string containing success or error message from the server
dele
The dele
event is emitted upon competion of the dele()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- msgnumber: the
msgnumber
provided to the method - rawdata: string containing success or error message from the server
rset
The rset
event is emitted upon competion of the rset()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- rawdata: string containing success or error message from the server
noop
The noop
event is emitted upon competion of the noop()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
- rawdata: string containing success or error message from the server
quit
The quit
event is emitted upon competion of the quit()
method. The arguments, in order, are:
- status: boolean true or false, indicating whether the execution was successful
-
- rawdata: string containing success or error message from the server
error
The error
event is emitted if there is an error
event from the underlying socket. The original error object is passed as an argument.
invalid-state
The invalid-state
event is emitted when an action not allowed within the current state s attmempted (eg, attempting to RETR
-ieve a message when AUTH
-entication has not been completed).
locked
The locked
event is emitted when a method is called while existing execution has not finished executing (eg, attempting to RETR
-ieve a message while the remote server has not finished sending LIST
data).
Tests & Demos
Tests are in tests
. Demos are in demos
.
There is a full-featured POP3 client example in demos/demo.js
. There is also a simple example of downloading all emails in a POP3 server and saving it locally in an mbox formatted file in demos/retrieve-all.js
.
For testing 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"
You can execute the test-runner as follows:
./runner.sh username password pop3server pop3port pop3tlsport testemail@address.com