DEV Community

Cover image for Reading email data with Node.Js
Olumide Akinremi
Olumide Akinremi

Posted on

Reading email data with Node.Js

Have you ever thought of reading the data of your emails and making decisions like marking it as read or do whatever you choose? Perhaps you are working on a project that requires you to read users emails and then save the data to your database.

Enough of the talking, let's get to work……

First, open a connection to the email server using a protocol (SMTP, IMAP, POP) to read email(s) from the email service. The email service can be Gmail, yahoo, outlook. e.t.c.

This tutorial uses Imap to read emails and will be using two packages to get the magic started.

  1. imap: this helps us connect to the email server and retrieve emails as a stream

  2. mailparser: we are going to use this to parse the stream data into a readable format.

The first step is to run the following command to set up a project and install the necessary packages.

mkdir imap-client
npm init -y 
touch index.js
yarn add imap mailparser
Enter fullscreen mode Exit fullscreen mode

Secondly, we need to add our email credentials to our index.js file.

const Imap = require('imap');
const {simpleParser} = require('mailparser');
const imapConfig = {
  user: 'youremail@gmail.com',
  password: 'secret',
  host: 'imap.gmail.com',
  port: 993,
  tls: true,
};
Enter fullscreen mode Exit fullscreen mode

Next, we write a script in the index.js file to read the email and then parse it to get the sender, subject and body.

const getEmails = () => {
  try {
    const imap = new Imap(imapConfig);
    imap.once('ready', () => {
      imap.openBox('INBOX', false, () => {
        imap.search(['UNSEEN', ['SINCE', new Date()]], (err, results) => {
          const f = imap.fetch(results, {bodies: ''});
          f.on('message', msg => {
            msg.on('body', stream => {
              simpleParser(stream, async (err, parsed) => {
                // const {from, subject, textAsHtml, text} = parsed;
                console.log(parsed);
                /* Make API call to save the data
                   Save the retrieved data into a database.
                   E.t.c
                */
              });
            });
            msg.once('attributes', attrs => {
              const {uid} = attrs;
              imap.addFlags(uid, ['\\Seen'], () => {
                // Mark the email as read after reading it
                console.log('Marked as read!');
              });
            });
          });
          f.once('error', ex => {
            return Promise.reject(ex);
          });
          f.once('end', () => {
            console.log('Done fetching all messages!');
            imap.end();
          });
        });
      });
    });

    imap.once('error', err => {
      console.log(err);
    });

    imap.once('end', () => {
      console.log('Connection ended');
    });

    imap.connect();
  } catch (ex) {
    console.log('an error occurred');
  }
};

getEmails();

Enter fullscreen mode Exit fullscreen mode

Lastly, run and don't forget to turn of "less secure app" for gmail

node index.js
Enter fullscreen mode Exit fullscreen mode

Let's do a bit of explanation.

imap.search(['UNSEEN', ['SINCE', new Date()]], (err, results) => {}
Enter fullscreen mode Exit fullscreen mode

The above function goes through your mailbox and gets all the unseen/unread email for today. You have the liberty of changing the date filter to whatever date you want. Also, you can change the ‘SINCE’ attribute to ‘BEFORE’, ‘ON’. e.t.c.

You can change the ‘UNSEEN’ attribute to something like ‘ALL’, ‘NEW’. e.t.c.

simpleParser(stream, async (err, parsed) => {}
Enter fullscreen mode Exit fullscreen mode

The simpleParser function returns a parsed data which contains details of the received email like (from, subject, textAsHtml, text) e.t.c.

imap.addFlags(uid, ['\\Seen'], () => {}
Enter fullscreen mode Exit fullscreen mode

You can also decide to add a flag to the read email like marking it as seen, read.

Thats's All!!!

The entire course code can be viewed here

References
https://www.npmjs.com/package/imap
https://www.npmjs.com/package/mailparser

Top comments (16)

Collapse
 
surya63572659 profile image
Surya

Throwing error if there are no unseen mails, and by that my app is crashing,how to fix or handle that error,pls let me know

Collapse
 
akinmyde profile image
Olumide Akinremi

Hey Surya, I saw your email and I believed my recommended solution works

Collapse
 
arbaz2002 profile image
Arbaz Khan

i need the solution too for this sir

Collapse
 
arbaz2002 profile image
Arbaz Khan

I am also facing the same problem how to solve it ???

Collapse
 
akinmyde profile image
Olumide Akinremi

Hello Arbaz,

You can use try/catch or .catch to handle errors. See the attached some code snippets that can help you handle errors.

Image description

Image description

Thread Thread
 
arbaz2002 profile image
Arbaz Khan

thank you sir how we will fetch the attachments from the email sir can you share this to me plz?????

Thread Thread
 
akinmyde profile image
Olumide Akinremi

You can get the attachment from the "parsed" object.

example is:

const {from, subject, textAsHtml, text, attachments} = parsed; 
Enter fullscreen mode Exit fullscreen mode

Check the mailparser documentation for more information

Thread Thread
 
arbaz2002 profile image
Arbaz Khan

thank you so much sir

Thread Thread
 
akinmyde profile image
Olumide Akinremi

You are welcome sir

Collapse
 
selvamramasamy profile image
selvamramasamy

I am following the same code. Login is happening and connection also established but after some request connection is not establishing and it says authentication error even username and password is correct.

I know after some request imap is blocked the connection temporary. How to fix this? is there any way to open connection always without login each time?

Collapse
 
akinmyde profile image
Olumide Akinremi

I believe it is possible. You can explore several options in the "connection instance methods". Check the imap documentation for more details (npmjs.com/package/imap).

You should look for specific options like: "Keep Alive". You can also explore auto-reconnecting in cases where your connection fails due to error.

I hope this helps.

Collapse
 
qaproengineer profile image
QAProEngineer

As today, the less app secure has been deprecated and then the script will literally fail. However there is an alternative way to set less secure app by creating app password in google mailbox using 2FA. worked for me !!

Collapse
 
vikram125609 profile image
Vikram Singh Dewda

giving an error of self signed certificate

Collapse
 
kotran88 profile image
kotran88

is it still working?
I got error

Error: self signed certificate
so I tried with Htts

then have another error
Error: Invalid credentials (Failure)
has something to do with
OAuth2?

Collapse
 
qaproengineer profile image
QAProEngineer

Google has deprecated "less secure app" for the security reason, there is an alternative way to login with less secure app by creating app password in your 2FA

Collapse
 
vvvutov profile image
VVVutov

Not working. I am also getting the self signed sertificate error. I think it has something to do with Google not allowing "less secure apps" anymore.