The big caveat here: the programmer is responsible for tracking idle state (Mail::IMAPClient doesn't do that for you right now).
With that in mind...
Here's the docs for idle_data():
[snip]
Usage:
# an optional timeout in seconds may be specified
$imap->idle_data( [$timeout] )
...
The B<idle_data> method can be used to accept any unsolicited mailbox
update messages that have been sent by the server during an L</idle>
command. This method does not send any commands to the server, it
simply looks for and optionally waits for data from the server and
returns that data to the caller.
[snip]
Your second call in the example code is:
barfts("Attempting improper idle_data() when not in IDLE...\n");
$msgref = $imap->idle_data($tag) or diets("? idle_data() failed: $@\n");
14:31:53 : Case 1: ...
14:31:57 : Attempting improper idle_data() when not in IDLE...
14:32:01 : idle_data() did not return undef, data follows:
14:32:01 : end data from idle_data()
Show quoted textObservation> An empty array(ref) was returned.
Important: the docs say you must call this *during* an idle. By
calling it when you're not in an idle, you're in an invalid use case.
Regardless, let's continue...
Issue #1 - You're calling idle_data with $tag as an argument and *not*
a timeout value. Perhaps that ends up "working" but that $tag is
probably not the $timeout most would want to use.
Issue #2 - While you think you should get an undef back, the empty
array is perfectly valid. Why?
a. Invalid use case (as already mentioned)
b. Even if you ignore reason a., you're still connected to the server
and the client hasn't received any unsolicited data. An empty
array(ref) is expected.
Then to address the done() concern from case 1:
Code:
# Try done() when the server is not in IDLE. On my setup with my
# server, this blocks for 600 seconds.
14:32:01 : Attempting improper done() when not in IDLE...
14:32:01 : ? improper done() failed: DONE BAD Error in IMAP command : Unknown command.
It doesn't block for me on 3.38 or 3.39 (upcoming), maybe check the
version you're using? If not upgrade, if so please provide debug
output.
As far as case 2 goes, the library doesn't track IDLE state. It's up
to the programmer to track the client state and do the right thing.
I'll consider patches that come with good test cases. I'm not yet
convinced it's the right thing to do to have Mail::IMAPClient do, but
I haven't thought about it a lot and I'm willing to listen to good
arguments.
I'll also note that the docs (for idle) seem to cover this although
I'm sure that having to wait for the idle to end seems annoying (again
I'm willing to consider patches if you feel there's a simple/graceful
way to handle this):
The method L</idle_data> may be used once B<idle> has been successful.
However, no mailbox operations may be called until the B<idle> command
has been terminated by calling L</done>. Failure to do so will result
in an error and the idle command will typically be terminated by the
server.
Marking as "Rejected" for now, but we can reopen if you feel the docs
are missing something or if there's an interest in contributing code
to change behavior.