postalsys / imapflow

IMAP Client library for EmailEngine Email API (https://emailengine.app)
https://imapflow.com
Other
350 stars 59 forks source link

How to delete messages By UID? #206

Closed killghost closed 2 months ago

killghost commented 2 months ago

for await (let message of client.fetch('1:*', { envelope: true, uid: true })) { console.log(${message.uid}: ${message.envelope.subject});

            if (message.uid==245507)
            {
                messages.push(message);
                try {
                    await client.messageDelete("245507", {uid: true})
                    //await client.messageDelete('100', { uid: true });
                } catch (error) {
                    console.log(error);
                }

                break;
            }               
        }

Can I Use messageDelete to Delete Email?

Remscar commented 2 months ago

It appears you are unable to make any sort of mailbox interaction until you have finished fetching messages with client.fetch (ie draining the async generator.)

This seems to be a pretty existential bug and makes using the library difficult. The source of this issue comes from the .trySend() internal function in the client; https://github.com/postalsys/imapflow/blob/5f257a36a290fc193738605a2ab5b22af106b0e3/lib/imap-flow.js#L413

If you start fetching messages with .fetch the currentRequest will still be the FETCH request, and trying to do other requests inside a for loop and blocking that loop will cause a dead lock.

You will either need to drain the generator and then do operations on what you got (such as deleting) or you could try to queue up any operations as promises and don't await them until after you have finished iterating all the messages from fetch.

andris9 commented 2 months ago

@Remscar Yes, you are correct. However, the issue is not the trySend method but the fact that there is only a single TCP connection, and all IMAP commands must be sent serially. As ImapFlow is still processing the FETCH command inside the async generator loop, any additional command will be queued for processing after FETCH. But FETCH can not be completed due to the await waiting until the issued command inside the loop is completed, and you end up in a deadlock.

Remscar commented 2 months ago

@Remscar Yes, you are correct. However, the issue is not the trySend method but the fact that there is only a single TCP connection, and all IMAP commands must be sent serially. As ImapFlow is still processing the FETCH command inside the async generator loop, any additional command will be queued for processing after FETCH. But FETCH can not be completed due to the await waiting until the issued command inside the loop is completed, and you end up in a deadlock.

That's some really great context, didn't know about the IMAP serial command requirement, thanks for the explanation!