[Question] Way to readline from underlying stream
qsdgy opened this issue · comments
I'm trying to perform an IMAP4 ID extension command manually.
command and response sequence would be like this:
C: a2 ID NIL
S: * ID ("name" "Coremail Imap" "vendor" "Mailtech" "TransID" "I186cXsAACfQ+GDj71IA")
S: a2 OK ID completed
code like this:
// by Client::login()
type ImapSession = imap::Session<native_tls::TlsStream<std::net::TcpStream>>;
pub fn id(s: &mut ImapSession) -> Result<(), Box<dyn std::error::Error>> {
let id = "ID NIL";
// Err(Parse(Invalid([...])))
// [...] is [u8] of * ID ("name" "Coremail Imap" "vendor" "Mailtech" "TransID" "I186cXsAACfQ+GDj71IA")
let res = s.run(id);
// panicked at 'assertion failed: `(left == right)` src\client.rs:1335:25
let res2 = s.run("NOOP");
Ok(())
}
failing to parse * ID ("name" "Coremail Imap" "vendor" "Mailtech" "TransID" "I186cXsAACfQ+GDj71IA")
can be ignored,
but tagged a2 OK ID completed
is left in the stream, and following commands will panic immediately as assertion failed.
sequence of crate's view:
C: a2 ID NIL
S: * ID ("name" "Coremail Imap" "vendor" "Mailtech" "TransID" "I186cXsAACfQ+GDj71IA")
C: a3 NOOP
S: a2 OK ID completed
So am I missing anything to get workaround to this?
Ah, no, there isn't currently a way to get at the raw connection. Client
and Session
do both deref to the public (but #[doc(hidden)]
) [Connection
type](https://github.com/jonhoo/rust-imap/blob/b656618987ccd2843cf0090fcfa5d498b07d991c/src/client.rs#L130], which does have a readline
method, though it's currently pub(crate)
. I think there's a decent argument for exposing a decent low-level interface for manually implementing commands the way you want to do here, so if you want to take a stab at contributing that, that'd be awesome! The main thing to keep an eye out for is to get tagging right, so that if you manually run a command, it'll get a distinct tag from any other commands (see self.tag
). @mordak may also be able to point you in the right direction.