emailjs / emailjs-imap-client

Low-level JS IMAP client for all your IMAP needs.
MIT License
552 stars 123 forks source link

Stop condition for arriving packets is not sufficient. #267

Open maksimlya opened 6 months ago

maksimlya commented 6 months ago

Hi, I've been using this library for last few years, tho recently(as users amount is growing) we are getting complains from users on production that app is getting stuck sometimes. Debugging it further, I noticed that in some rare conditions (and most likely bad network / background app freeze), the socket just hangs up and timeout is not thrown.

Debugging further, I saw that we recognize 'stop' condition by having '\n'(LINE_FEED) sign as last character on last line of the packet. While it forks for 99% of cases, I will provide example of how this can be broken.

Let's take for example this packet that arrived as whole:

[_onData]* SEARCH 6669\r\nW96 OK SEARCH completed (Success)\r\n

We have 2 lines here, the '_iterateIncomingBuffer' function will go through them and check. It does then notices that last line has '\n' as last character, and it will clear the '_socketTimeoutTimer' . Result will then return and everything works correctly.

Now, it is not given that IMAP server always returns whole response like that (I saw in my logs), and sometimes it can arrive as 2 separate packets:

[_onData]* SEARCH 6669\r\n W96 OK SEARCH completed (Success)\r\n

In that case, '_iterateIncomingBuffer' function will clear the socket timeout after first line, but since the 'completed' arrives right after it, the overall result will work as before without us noticing anything.

Issue is actually happening in 3rd case:

[_onData]* SEARCH 6669\r\n

Where for some reason, either socket died or app got frozen or for whatever else reason, but we did not get the last packet from the server. In this case, '_socketTimeoutTimer' is cleared because we think that we got last packet, but it will hang forever and not being released.

Is there any way to address this, or am I doing something wrong?