Browserbox (emailjs.org's IMAP client) does not currently support streaming data from FETCH requests. We need to add support for that to allow us to download large messages and attachments without OOMing. This is a followup to bug 885110.
I left streaming intentionally out of Broswerbox because I wasn't able to figure out how to handle back-pressure correctly (processing the responses might be slower than the speed of incoming data). To solve this I figured that I could use standard IMAP commands: * Instead of FETCHing 1:*, I'd FETCH numbered ranges 1:100, 101:200 etc. If I do not include potentially large responses like BODY in this call, I should be on the safe side. If I need the BODY I'll make a separate FETCH * Instead of FETCHing entire BODY, I'd FETCH the RFC822.SIZE first (FETCH 1:100 RFC822.SIZE) and then use this information to FETCH larger messages in partials. Eg. if a message exceeds 1 kB then FETCH 123 BODY<0.1024> to get the first chunk, FETCH 123 BODY<1024.2048> for the second chunk etc. As an additional optimization, if the messages are small I could FETCH these all at once (FETCH 1:3,4,6,9:12 BODY), no need to FETCH these one by one. This would give the option to handle the processing speed as needed – if processing current data takes time, then I do not request any additional data from the server until the processing is completed.
Body-wise, WHATWG streams (https://github.com/whatwg/streams) will support backpressure and TCPSocket will be updated to have those. Until TCPSocket has those, I suppose the body-fetching mechanism could map backpressure signals to smarts about doing chunked/byte-range fetches. Depending on how much work it is... at least on the Moz side it might make more sense for us to just get TCPSocket updated to support backpressure. In particular, since we have to support POP3 (via TCPSocket) which does not support byte-range fetches, back-pressure is way better for us.
Without proper TCP streams you're out of luck if you need to support POP3. If I had to work with POP3 right now (which I do not), I'd probably accept only the first 100kB or so of the RETR response from the TCP and send anything that follows to /dev/null. Hopefully the fetched part contains the most important stuff like headers and text body. I'd show a button "load entire message" next to the message preview and only then if the use clicks on it, I'd re-fetch the message and hope that it fits into memory. I wouldn't save on data traffic because the message would be fully streamed on the first request already but I'd skip memory issues until the user specifically requests for it. Obviously if streams support would land in TCPSocket, it would make things so much easier.