Giter VIP home page Giter VIP logo

yapople's Introduction

yapople

Yet another POP3 library

Coverage Status NPM version

The design propose of the library is simplicity. A lot of common tasks with you POP3 mailbox doesn't require knowledge of the eleven POP3 commands. You just want to retrieve some messages from your mailbox and that's all! So here is quick example how to do this with 'yapople':

const { Client } = require('yapople');
const client = new Client({
  host: 'pop.mail.ru',
  port:  995,
  tls: true,
  mailparser: true,
  username: 'username',
  password: 'password',
  options: {
    secureContext: {
      passphrase: "passphrase"
    }
  }
});
(async () => {
    await client.connect();
    const messages = await client.retrieveAll();
    messages.forEach((message) => {
      console.log(message.subject);
    });
    await client.quit();
})().catch(console.error);

Or with the old callback style:

var Client = require('yapople').Client;
var client = new Client({
  host: 'pop.mail.ru',
  port:  995,
  tls: true,
  mailparser: true,
  username: 'username',
  password: 'password',
  options: {
    secureContext: {
      passphrase: "passphrase"
    }
  }
});
client.connect(function() {
  client.retrieveAll(function(err, messages) {
    messages.forEach(function(message) {
      console.log(message.subject);
    });
    client.quit();
  })
})

Also this is a callback-driven and command-queued library instead of poplib So you can run methods in chain, don't think about already running command and get what you want in callback instead of putting somewhere event-listener functions to retrieve data. You can add connection options (optional) after callback.

Uses the last TLS Api (since crypto.createCredentials is deprecated), so it works only with node.js v.0.12 or later.

Installation

npm install yapople

Tests

npm test

Constructor properties

When you create new Client object you should pass an object which describes connection properties.

  • host or hostname - string - mailserver hostname
  • port - number - port, usually 110 or 995 for TLS connection
  • username - string - mailbox username
  • password - string - mailbox password
  • mailparser - boolean - use mailparser library to automatically decode messages
  • tls - boolean - use TLS encryption
  • options - object - Optional configuration JSON object for socket creation. (see. TLS and NET)

Properties

  • connected - boolean - connect and login state

Methods

All the methods can be used both callback-style or promise-style if callback has been omitted. In the examples below only async-await style will be used.

connect([options], [callback])

  • options - object
  • callback - function(err)

Connect to the mailserver using hostname and port. Starts TLS connection if tls property is true. Then login into your mailbox using credentials properties username and password.

If options is defined, valuse from options will be used to connect for tls.connect or net.createConnection functions. Precedence goes to them instead of constructor options.

count([callback])

  • callback - function(err, count)

Returns a count of the messages in the mailbox

retrieve(what, [callback])

  • what - number or array of numbers - message number, or an array of message numbers
  • callback - function(err, messages)

Retrieve a message/messages by its number/numbers. If the mailparser argument is true returned messages will be parsed and looks like an objects. Otherwise it will be strings. Notice that results are sparse array with indexes representing message numbers. You can access message with its number like that messages[number] and use all HOF like this messages.map(function(mail, num){ return [num, mail.subject]; }). Or you can represent it like normal array with construction like this: messages.filter(a => a)

retrieveAll([callback])

  • callback - function(err, messages)

Retrieve all messages in mailbox. Result is a sparse array starting from 1.

delete(what, [callback])

  • what - number or array of numbers - message number, or an array of message numbers
  • callback - function(err, messages)

Delete a message/messages by its number/numbers. If you delete several messages and get an error for some message, all you delete transaction will be reset.

Note that if your connection to the server is broken at all then the messages will not actually be deleted. You need to cleanly disconnect from the mail server for this to happen.

deleteAll([callback])

  • callback - function(err, statuses)

Delete all messages in mailbox.

retrieveAndDeleteAll([callback])

  • callback - function(err, messages)

Retrieve and delete all messages in mailbox. Result is a sparse array starting from 1. In a callback function you'll get an error message or an array of retrieved emails. If you get an error for some reason, all you delete transaction will be reset.

list(number, [callback])

  • number - number (optional) - message number
  • callback - function(err, info)

Returns length of a message in octets. If no number passed, list returns an object contains message numbers as a keys and message lengths as a values

quit([callback])

disconnect([callback])

  • callback - function(err)

Finish current session and disconnect. All messages marked as deleted after this command will be erased.

Protocol methods

retr(what, [callback])

  • what - number or string - message number
  • callback - function(err, message)

Retrieve full message by its number.

stat([callback])

  • what - number or string - message number
  • callback - function(err, stat)

Returns an stat object representing the number of messages currently in the mailbox (count property) and the size in bytes (length property).

top(number, linesCount, [callback])

  • number - number or string - message number
  • linesCount - number or string - the number of lines of the message body you would like returned
  • callback - function(err)

Retrieve part of the message including headers, or only headers.

dele(number, [callback])

  • number - number or string - message number
  • callback - function(err, response)

Delete a message by its number.

Changelog

0.4.0

  • all methods returns promises
  • tests were rewritten in js and jest
  • additional parameter options in the constructor and connect method

yapople's People

Contributors

agsh avatar bitdeli-chef avatar dependabot[bot] avatar devchanki avatar lioreshai avatar prabhakar-poudel avatar russellhofmann avatar salketer avatar savoiebz avatar wslee94 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

yapople's Issues

RetrieveAll() erroring without specifying cause

Here's what I've got:

import consola from 'consola'
import { extract, LetterparserMail } from 'letterparser'
import { Client, YapopleClientConfig } from 'yapople'

const emailService = async (): Promise<LetterparserMail[]> => {
  try {
    const messageList: LetterparserMail[] = []

    if (process.env.EMAIL_ADDRESS && process.env.EMAIL_PASSWORD && process.env.EMAIL_HOST) {
      const clientConfig: YapopleClientConfig = {
        host: process.env.EMAIL_HOST,
        port: 995,
        tls: true,
        mailparser: false,
        username: process.env.EMAIL_ADDRESS,
        password: process.env.EMAIL_PASSWORD
      }
      const client = new Client(clientConfig)

      consola.log(`Connecting to ${process.env.EMAIL_HOST}`)
      await client.connect()

      const count = await client.count()
      consola.log(`${count} messages found on server`)

      try {
        const msgs = await client.retrieveAll()
        msgs.forEach(msg => messageList.push(extract(msg.toString())))
      } catch (err) {
        consola.log(`Error retrieving messages from server: ${err}`)
      }
      consola.log(`Messages parsed: ${messageList.length}`)

      await client.quit()
    } else {
      consola.error('EMAIL_ADDRESS, EMAIL_PASSWORD, and EMAIL_HOST environment variables are required')
    }

    return messageList
  } catch (error) {
    consola.error(error)
    throw error
  }
}

export default emailService

And here's what's happening:

Connecting to imap.migadu.com                                                                 14:20:47
285 messages found on server                                                                  14:20:47
                                         												      14:20:53
After all, it takes a lot of emotional energy to curate the best
AWS news for you every week. If you think your AWS bill is high,
you should see my therapy invoices.

Living my truth,

Corey

P.S. Here=E2=80=99s a hot tip for keeping yourself comfy at re:Invent (
https://click.lastweekinaws.com/d0uvkvx9rdamu0m345im/9qhzhdul6698w0c9/aHR0c=
HM6Ly93d3cubGFzdHdlZWtpbmF3cy5jb20vYmxvZy9pbS1hbi1hd3MtY2VydGlmaWVkLWNsb3Vk=
LXByYWN0aXRpb25lci8=3D
). Don=E2=80=99t say it came from me.

What'd you think of this email?

=F0=9F=91=8E (
https://click.lastweekinaws.com/d0uvkvx9rdamu0m345im/e0h97qlxi0unx3z2gwh8/a=
HR0cHM6Ly93d3cubGFzdHdlZWtpbmF3cy5jb20vc3BlY2lhbC90aHVtYnNkb3duLw=3D=3D
)
=F0=9F=91=8D (
https://click.lastweekinaws.com/d0uvkvx9rdamu0m345im/8ghrwvprt3u5468xvxtk/a=
HR0cHM6Ly93d3cubGFzdHdlZWtpbmF3cy5jb20vc3BlY2lhbC90aHVtYnN1cC8=3D
)

---------------
I=E2=80=99m Corey Quinn
---------------

  I help companies address their horrifying AWS bills
  by both reducing the dollars spent and help
  at Client.onData (node_modules/yapople/lib/yapople.js:108:19)
  at TLSSocket.emit (events.js:375:28)
  at addChunk (internal/streams/readable.js:290:12)
  at readableAddChunk (internal/streams/readable.js:265:9)
  at TLSSocket.Readable.push (internal/streams/readable.js:204:10)
  at TLSWrap.onStreamRead (internal/stream_base_commons.js:188:23)


Messages parsed: 0     																	      14:20:53

events.js:352
      throw er; // Unhandled 'error' event
      ^

Error
Emitted 'error' event on TLSSocket instance at:
    at TLSSocket._emitTLSError (_tls_wrap.js:892:10)
    at TLSWrap.onerror (_tls_wrap.js:416:11)

Once it gets there, it just hangs and never proceeds. As you can see, I've disabled parsing in your library, so that shouldn't be the cause. I'm running Node 14 LTS.

[Question] How to wait for a new email ?

I'm trying to do this :

  1. I run a script
  2. The script waits for an email
  3. I send the email
  4. The script shows the received email

Here's my code :

const { Client } = require('yapople');;

const client = new Client({
    host,
    port,
    tls,
    mailparser,
    username,
    password
});

client.connect(error => {
    const
        handleError = error => {
            client.quit();
            console.error(error);
        },
        _ = () => {
            client.retrieveAndDeleteAll((error, [message] = []) => {
                if(error) return handleError(error);
                if(message) console.log(message); // <-- Expected new message
                else return setTimeout(_, 250);
                client.quit();
            });
        };
    if(error) return handleError(error);
    client.retrieveAndDeleteAll((error) => {
        if(error) return handleError(error);
        _();
    });
});

The email never arrives, I eventually will get the following error :

Error: [IN-USE] Mailbox is locked by another POP3 session.

However, if I rerun and do a console.log of my first call to client.retrieveAndDeleteAll, the email I sent will be there.

Thanks

[Question] How to wait for a new email ?

I'm trying to do this :

  1. I run a script
  2. The script waits for an email
  3. I send the email
  4. The script shows the received email

Here's my code :

const { Client } = require('yapople');;

const client = new Client({
    host,
    port,
    tls,
    mailparser,
    username,
    password
});

client.connect(error => {
    const
        handleError = error => {
            client.quit();
            console.error(error);
        },
        _ = () => {
            client.retrieveAndDeleteAll((error, [message] = []) => {
                if(error) return handleError(error);
                if(message) console.log(message); // <-- Expected new message
                else return setTimeout(_, 250);
                client.quit();
            });
        };
    if(error) return handleError(error);
    client.retrieveAndDeleteAll((error) => {
        if(error) return handleError(error);
        _();
    });
});

The email never arrives, I eventually will get the following error :

Error: [IN-USE] Mailbox is locked by another POP3 session.

However, if I rerun and do a console.log of my first call to client.retrieveAndDeleteAll, the email I sent will be there.

Thanks

tls: error after socket.close()

when tls is used, quit() command writes "quit" and immediately closed socket with socket.end()

this seems to confuse tls, I'm getting random errors like

Error: read ECONNRESET
    at exports._errnoException (util.js:859:11)
    at TLSWrap.onread (net.js:550:26)

seems to be race condition somewhere in tls, and it's hard to intercept

My workaround: I expect server to gracefully close connection, so I changed code to be like this:

//...
        } else if (this._command.cmd === state.QUIT) {
            var self = this;
            this._socket.on('end', function() {
            self.connected = false;
            if (self._command.callback) {
                self._command.callback.call(this, null);
            }
            });
        } else {
//...

Mail listener

Hi!

Is there anyway to create a mail listener that is always listening for new emails and fires an event when a new email is being received? Thank you so much!

ECONNRESET during fetch

Hi! First of all I would like to thank you for this pretty good and simple LIB.

I'm getting sometimes ECONNRESET exception due my poor network. And even if the requested code is wrapped by a try-catch block, it seems to crash my node app. I guess some actions are happening in a different thread inside the, for example, retrieve method. Would it be possible?

Error: Server Unavailable. 21

Hi, I am getting this error, is it due to my mail server is unavailable or is it a problem with the library connection?

Thanks

(node:15288) UnhandledPromiseRejectionWarning: Error: Server Unavailable. 21
at Client.onData (D:\00_PROYECTOS\03_raul\02_app\server\node_modules\yapople\lib\yapople.js:105:19)
at TLSSocket.emit (events.js:315:20)
at addChunk (_stream_readable.js:309:12)
at readableAddChunk (_stream_readable.js:284:9)
at TLSSocket.Readable.push (_stream_readable.js:223:10)
at TLSWrap.onStreamRead (internal/stream_base_commons.js:188:23)
(Use node --trace-warnings ... to show where the warning was created)
(node:15288) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:15288) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

[Browser] process.versions.node is undefined

Hello,

I would like to run yapople browser-side from a Cypress test (to receive an account activation message), but I get the process.versions.node is undefined error.

Thanks

EventEmitter leak

There seems to be an EventEmitter leak in the client code. If an error is thrown when logging in for example, things don't get cleaned up correctly.

I could be wrong but I don't see any calls to removeListener that balance the on calls that are made so this is probably the problem.

client.retreiveAll is returning a Buffer

var client = new Client({ hostname: 'pop.mail.ru', port: 995, tls: true, mailparser: true, username: 'username', password: 'password' }); client.connect(function() { client.retrieveAll(function(err, messages) { messages.forEach(function(message) { console.log(message.subject); }); client.quit(); }) })

Here the message inside the foreach is a Buffer and not an object and message.subject is throwing an exception

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.