Moving only working once #309

Closed
engram-design opened this Issue Oct 5, 2013 · 4 comments

Comments

Projects
None yet
2 participants

Related to #300 but essentially a different issue.

Moving messages works fine - but only once! For instance, using the below simple code:

var imap = new require('imap')({
    user: 'data@domain.com.au',
    password: 'password',
    host: 'outlook.office365.com',
    port: 993,
    tls: true,
    tlsOptions: { rejectUnauthorized: false },
    debug: console.log
});

imap.once('ready', function() {
    imap.openBox('TOMOVE', false, function(err, box) {
        searchForNewEmail(box); // initial search/process of data
    });
});

imap.connect(); // connect to imap

function searchForNewEmail(box) {
    imap.search(['ALL'], function(err, results) {
        var f = imap.fetch(results, { bodies: '1', struct: true });

        f.on('message', function(msg, seqno) {
            msg.on('body', function(stream, info) {
                var buffer = '';
                stream.on('data', function(chunk) { buffer += chunk.toString('utf8'); });

                stream.once('end', function() {
                    imap.move(info.seqno, 'MOVED', function(err) {
                        if (err) { console.log(err); }
                    });
                });
            });
        });
    });
}

I've already created the folders TOMOVE and MOVED. Running the code, everything runs as expected (see debug output below).

https://gist.github.com/engram-design/696eaca9a148577ce426

Then, moving the message back from MOVED and TOMOVE and running it again - it refuses to move the message (see debug output below).

https://gist.github.com/engram-design/3a705f292f4ea40e0fe4

Owner

mscdex commented Oct 6, 2013

It looks like you're using the wrong UID in the second example (it should be 2 instead of 1). UIDs are only valid within a mailbox. Once messages are copied/moved/etc to a different mailbox, the UIDs for those messages change in the destination mailbox. This is to avoid collisions where a UID from the source mailbox may already be used by another message in the destination mailbox.

Yeah, understand that, but that shouldn't happen if I disconnect from the server and restart the script after the move? Shouldn't that re-search the mailbox and pickup the new UID?

Owner

mscdex commented Oct 6, 2013

Correct.

To make sure the correct UID is used, either change this:

imap.move(info.seqno, 'MOVED', function(err) {

to this:

imap.seq.move(info.seqno, 'MOVED', function(err) {

OR if you want to keep using the UID for moving, change searchForNewEmail:

function searchForNewEmail(box) {
    imap.search(['ALL'], function(err, results) {
        var f = imap.fetch(results, { bodies: '1', struct: true });

        f.on('message', function(msg, seqno) {
            var uid;
            msg.on('body', function(stream, info) {
                var buffer = '';
                stream.on('data', function(chunk) {
                  buffer += chunk.toString('utf8');
                });

                stream.once('end', function() {
                    // do something with 'buffer'
                });
            });
            msg.once('attributes', function(attrs) {
              uid = attrs.uid;
            });
            msg.once('end', function() {
                imap.move(uid, 'MOVED', function(err, code) {
                    // As of node-imap 11b37fcd, you can get the UID of the
                    // moved message in the destination mailbox from `code`:
                    //   if (code.key === 'COPYUID' && code.val[2])
                    //     var newUID = code.val[2];
                    if (err) { console.log(err); }
                });
            });
        });
    });
}

or if you want to be more efficient, move the messages all at once instead of one at a time:

function searchForNewEmail(box) {
    imap.search(['ALL'], function(err, results) {
        var f = imap.fetch(results, { bodies: '1', struct: true });

        f.on('message', function(msg, seqno) {
            msg.on('body', function(stream, info) {
                var buffer = '';
                stream.on('data', function(chunk) {
                  buffer += chunk.toString('utf8');
                });

                stream.once('end', function() {
                    // do something with 'buffer'
                });
            });
        });
        f.once('end', function() {
            imap.move(results, 'MOVED', function(err, code) {
                // As of node-imap 11b37fcd, you can get the UIDs of the
                // moved messages in the destination mailbox from `code`:
                //   if (code.key === 'COPYUID' && code.val[2])
                //     var newUIDs = code.val[2];
                if (err) { console.log(err); }
            });
        });
    });
}

Aha - I see! using imap.seq.move() got it working great. I think I got a bit messed up with sequence numbers and UID's. Thank you so much for your help!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment