jonhoo / rust-imap

IMAP client library for Rust
Apache License 2.0
477 stars 80 forks source link

Trouble getting IDLE example to work #271

Closed vsl-iil closed 11 months ago

vsl-iil commented 12 months ago

I'm using v.3.0.0-alpha.11 and the IDLE example doesn't really work. The only two things I changed were the timeout and max responses:

0a1
> use std::time::Duration;
33c34
<         default_value = "5"
---
>         default_value = "1"
64c65,66
<     let idle_result = imap.idle().wait_while(|response| {
---
>     let dur = Duration::from_secs(60);
>     let idle_result = imap.idle().timeout(dur).wait_while(|response| {

However, even though I set the default max_responses value to 1, it just doesn't stop after the first timeout. It isn't printing out the "IDLE response" from the closure either and I don't think it even reaches any closure code whatsoever. Am I doing something wrong?

Here's the debug log:

C: a2 SELECT "INBOX"
S: * FLAGS (\Answered \Flagged \Deleted \Draft \Seen)
S: * 467 EXISTS
S: * 0 RECENT
S: * OK [UNSEEN 467]
S: * OK [UIDVALIDITY 1410186773]
S: * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft)]
S: * OK [UIDNEXT 21043]
S: a2 OK [READ-WRITE] SELECT completed
C: a3 IDLE
S: + idling
C: DONE
S: a3 OK IDLE done
C: a4 IDLE
S: + idling
^C

P.S. The server has IDLE capability:

C: a3 CAPABILITY
S: * CAPABILITY IMAP4rev1 ID XLIST UIDPLUS UNSELECT MOVE LIST-STATUS IDLE
S: a3 OK CAPABILITY completed
jonhoo commented 11 months ago

Iiinteresting. @mordak and @mredaelli did much of the work on the latest iteration of IDLE support, perhaps either of them has some insights that could be helpful here?

mordak commented 11 months ago

The example works for me. I can let the idle.rs example run on my computer and generate events using another mail client (ie: delete a message, flag a message, etc.) and the closure runs. After the max_responses is reached then the example exits.

I think this is simply confusion about what should be happening. max_responses is counting the number of mailbox events received from the server while IDLE. In the output shown, it doesn't look like anything is happening in the mailbox. So after the timeout is reached, the client ends the IDLE and then restarts it. This is by design.

The purpose of wait_while() is to simply loop forever until told to stop (by returning false in the closure). The timeout value is not meant to indicate when the client should stop IDLE and return control to the program, it is meant to indicate when to refresh the IDLE, which is a recommendation from the RFC, and is documented in the module:

https://docs.rs/imap/3.0.0-alpha.11/imap/extensions/idle/struct.Handle.html

Note that the server MAY consider a client inactive if it has an IDLE command running, and if such a server has an inactivity timeout it MAY log the client off implicitly at the end of its timeout period. Because of that, clients using IDLE are advised to terminate the IDLE and re-issue it at least every 29 minutes to avoid being logged off.

I think you might want to disable keepalive:

https://docs.rs/imap/3.0.0-alpha.11/imap/extensions/idle/struct.Handle.html#method.keepalive

Does this help?

vsl-iil commented 11 months ago

I see. Yes, it seems that I got a bit confused about what the function is supposed to do. Thank you for clearing this up for me!