4

When I try to retrieve emails through imap with the code below(using an async function), I get the following console output/error:

Inbox: undefined

/Users/mainuser/node_modules/imap/lib/Connection.js:432 cb(err, self._box); ^ TypeError: cb is not a function

var Imap = require('imap');
var inspect = require('util').inspect;

var imap = new Imap({
  user: '[email protected]',
  password: 'mymailpassword',
  host: 'imap.mail.com',
  port: 993,
  tls: true
});

const openInbox = async () => {
  try {
    const inbox = await imap.openBox('INBOX', true)
    return inbox
  }catch(error){
    console.log("Error: "+ error)
  }
}

imap.once('ready', () => {
  console.log('ready')
  openInbox()
   .then(inbox => console.log('Inbox: ' + inbox))
});

imap.connect()

However, I can open the inbox and output the inbox Object using nested callbacks as shown below:

imap.once('ready', () => {
  imap.openBox('INBOX', true, (err, inbox) => {
    console.log('Inbox: ' + inbox)
  });
});

imap.connect()
3
  • Apparently the imap library does not support promises Commented Nov 9, 2019 at 11:04
  • You’re right, it doesn’t. Just looking for a way to promising the library now, any ideas? I’ve tried using bluebird promisifyall, no dice. You can see the comments under the answer below. Thanks Commented Nov 9, 2019 at 13:39
  • Update: The imap-simple library was published in Apr 2020. It has promises built in, and IMO makes async functions much simpler. npmjs.com/package/imap-simple Commented Jul 19, 2020 at 18:16

1 Answer 1

5

If you prefer to work with promises you should either write a custom wrapper around imap.openBox or wrap it with Node.js built-in util.promisify function:

const Imap = require('imap');
const promisify = require('util').promisify;

const imap = new Imap({
  user: '[email protected]',
  password: 'mymailpassword',
  host: 'imap.mail.com',
  port: 993,
  tls: true
});

const openBox = promisify(imap.openBox.bind(imap));

imap.once('ready', () => {
  console.log('ready')
  openBox('INBOX', true)
    .then(inbox => console.log(inbox))
    .catch(err => {
      console.log(err)
    })
});

imap.connect()

In order to promisify the entire API, try to wrap the imap instance in Bluebird.promisifyAll. Note the promisified methods are available with Async prefix:

const bluebird = require('bluebird');
const Imap = require('imap');

const imap = bluebird.promisifyAll(new Imap({
    user: '[email protected]',
    password: 'mymailpassword',
    host: 'imap.mail.com',
    port: 993,
    tls: true
}));

imap.once('ready', () => {
  console.log('ready')
  imap.openBoxAsync('INBOX', true)
    .then(inbox => console.log(inbox))
    .catch(err => {
      console.log(err)
    })
});

imap.connect()
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks. I was hoping that I could work with Asyn / Await functions. Never the less, this brings me closer to the solution. After I promisified imap.openbox by doing this:const openBox = promisify(imap.openBox.bind(imap)); I'm able to now successfully log the inbox object. The only question now is: how can I Promisify the ENTIRE imap API?
Hi @LoupG, you can try to use Bluebird.promisifyAll to promisify the entire API. I have updated the answer
Hi, I had tried that before put up my comment response to your answer, I guess I should have said so. Have you tried it? If it worked for you, can you put the code up as part of the answer. Thanks in advance
Yes, it worked for me. I have added the code that leverages bluebird.promisifyAll to the answer
Thanks a lot, I had not realized that the promisify library renames the methods my appending promisify to the method name!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.