Search code examples
javascriptnode.jsgmailimapgmail-imap

Get list of all unread emails and log email sender and subject of that email using imap and node


I am trying to use imap and node to get all of the unread emails from an email and log the email sender and the subject. I am trying to run the following code:

var imap = new Imap({

    user: Email,
    password: Password,
    host: 'imap.gmail.com',
    port: 993,
    tls: true
});

function openInbox(cb) {
    imap.openBox('INBOX', true, cb);
}

openInbox(function(err, box) {
    if (err) throw err;
    var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM)','TEXT'] });
    f.on('message', function(msg, seqno) {
        console.log('Message #%d', seqno);
        var prefix = '(#' + seqno + ') ';
        msg.on('body', function(stream, info) {
            if (info.which === 'TEXT')
                console.log(prefix + 'Body [%s] found, %d total bytes', 
                inspect(info.which), info.size);
                var buffer = '', count = 0;
                stream.on('data', function(chunk) {
                    count += chunk.length;
                    buffer += chunk.toString('utf8');
                    if (info.which === 'TEXT')
                        console.log(prefix + 'Body [%s] (%d/%d)', 
                         inspect(info.which), count, info.size);
                });
                stream.once('end', function() {
                    if (info.which !== 'TEXT')
                        console.log(prefix + 'Parsed header: %s', 
                        inspect(Imap.parseHeader(buffer)));
                    else
                        console.log(prefix + 'Body [%s] Finished', 
                        inspect(info.which));
                });
        });
        msg.once('attributes', function(attrs) {
            console.log(prefix + 'Attributes: %s', inspect(attrs, false, 8));
        });
        msg.once('end', function() {
            console.log(prefix + 'Finished');
        });
    });
    f.once('error', function(err) {
        console.log('Fetch error: ' + err);
    });
    f.once('end', function() {
        console.log('Done fetching all messages!');
        imap.end();
    });
});

When I run this code I am getting the following error:

Uncaught Error: Not authenticated
    at Connection.openBox

What does this error mean? I made sure to enable Less secure app access on every gmail account I am trying to access. I would appreciate anyones help


Solution

  • Assuming you are using the node-imap module, you aren't calling it correctly.

    This error happens if you try to call openBox before your connection is set up. (That is, that you are connected and authenticated, and ready to open a mailbox).

    You need to do two things:

    1. Add a top level call to imap.connect()
    2. Wrap most of your current openInbox call inside of a call to imap.once() like this:
    imap.once('ready', function() {
      openInbox(function(err, box) {
        ...
      });
    });
    

    I'd recommend you start with the exact example in their documentation until you are confident you have it set up right and working, so you can separate out the code issues from the issues with gmail authentication.

    Beyond that, as you note, Gmail is pretty fickle about how you are using low security apps. It probably makes sense to use a normal client to prove that you've gotten the low security app setting enabled, you've proceessed any unlock captchas, etc, that you need to do. See the full list. In particular, you may need to approve one of the logins manually in the security console before it starts to work.

    FWIW, the error you get if you're connected, but not authenticating because Gmail doesn't like the login is different, it looks more like this:

    { Error: Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)
        at Connection._resTagged (/.../lib/Connection.js:1502:11)
        at Parser.<anonymous> (/.../lib/Connection.js:194:10)