Can not insert from NPM package


#1

I am using the imap-simple NPM package to check emails, and I am having trouble getting the insert to work properly.

I have already read through this page: https://guide.meteor.com/using-npm-packages.html#async-callbacks - and I have tried the suggestions but none of them are working!

I’ve also simplified the code a bit just to try to get it working, but still have no luck.

The problem should be very easy to reproduce - meteor npm install imap-simple, throw the above code on the server, add some email credentials, and call the method.

Here is my code:

var imaps = require('imap-simple');
var config = {
    imap: {
        user: '<removed>',
        password: '<removed>',
        host: 'imap.gmail.com',
        port: 993,
        tls: true,
        authTimeout: 3000
    }
};

Meteor.methods({

    api_connectEmail: function () {
        console.log('Received call to connect email');

        imaps.connect(config).then(function (connection) {

            return connection.openBox('INBOX').then(function () {
                var searchCriteria = [
                    'UNSEEN'
                ];

                var fetchOptions = {
                    bodies: ['HEADER', 'TEXT'],
                    markSeen: true
                };

                return connection.search(searchCriteria, fetchOptions).then(function (results) {
                    results.map(function (res) {

                        var subject = res.parts.filter(function (part) {return part.which === 'HEADER';})[0].body.subject[0];
                        console.log("Subject: " + subject);

                        // insert
                        var attributes = {
                            subject: subject
                        };
                        console.log("Attempting to insert to collection...");
                        var newData = TempEmailCollection.insert(attributes);
                        console.log("New Database Entry ID: " + newData);

                    });
                });
            });
        })
    }
});

The console.log with the subject is working. The insert is not working. No error. No console.log post insert. Nothing.

I’ve tried both strategies recommended in the guide. Neither work.

Any assistance would be greatly appreciated… been working on this since yesterday and already late for deadline…


#2

Strange part, if I console.log (“TempEmailCollection”), I can see a response. So this IS seeing the collection! Yet if I try to insert in to the collection , it is NOT working.

Is there noone that can assist with this? I posted here & stack overflow, more than twice at each, and absolutely no responses. Am I really the only one that encountered this type of error?

It’s not even giving an error, so I don’t even know what else I can do at this point. This feature needs completion and I have gotten absolutely 0 work done for the last 2 days… Just getting very frustrated at this point.


#3

Are you using Meteor’s baked-in Promises or a third-party Promise library (like Bluebird)?


#4

Only Meteors.

As an update, I’ve added some error logging, and on the outer-most promise it generates an error of:

I20160728-20:23:11.767(-7)? Attempting to insert to collection…
I20160728-20:23:11.768(-7)? Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.

I’ve tried to wrap the promises by both functions as described in the Guide, but had no luck. I’m not sure if it requires a different process with how it returns data from nested promises? But I’ve tried wrapping each and have had no luck so far.

Any idea where I have went wrong?


#5

Hmm. I’ve never had a problem mixing Meteor Promises with sync-style MongoDB methods. It’s probably something obvious I’m missing, but I’m just about to go away for the weekend, so unable to give this the attention it deserves. You could try wrapping the async Mongo method in a Promise - maybe something like:

const insertWithPromise = (attributes) => {
  return new Promise((resolve, reject) => {
    TempEmailCollection.insert(attributes, (err, res) => {
      if (err) reject('Something went wrong');
      resolve(res);
    });
  });
};

and declaring your method as an async function (async api_connectEmail() {...). Then connect your Promises with await, but it feels messy.

Maybe someone else has a better idea.