#![allow(dead_code)]
use std::io::{Read, Write};
use io_imap::{
codec::fragmentizer::Fragmentizer,
coroutine::*,
rfc3501::{greeting::*, login::*, logout::*, select::*},
};
use pimalaya_stream::{std::stream::StreamStd, tls::Tls};
const FRAGMENTIZER_MAX_MESSAGE_SIZE: u32 = 100 * 1024 * 1024;
pub fn run_imaps(host: &str, port: u16, username: &str, password: &str) {
let _ = env_logger::try_init();
let stream = StreamStd::connect_tls(host, port, &Tls::default()).expect("TLS connect");
run(stream, username, password)
}
pub fn run_imap(host: &str, port: u16, username: &str, password: &str) {
let _ = env_logger::try_init();
let stream = StreamStd::connect_tcp(host, port).expect("TCP connect");
run(stream, username, password)
}
fn run(mut stream: impl Read + Write, username: &str, password: &str) {
let mut buf = [0u8; 16 * 1024];
let mut fragmentizer = Fragmentizer::new(FRAGMENTIZER_MAX_MESSAGE_SIZE);
let mut coroutine = ImapGreetingGet::new(ImapGreetingGetOptions {
ensure_capabilities: true,
});
let mut arg: Option<&[u8]> = None;
loop {
match coroutine.resume(&mut fragmentizer, arg.take()) {
ImapCoroutineState::Complete(Ok(_)) => break,
ImapCoroutineState::Complete(Err(err)) => panic!("GREETING: {err}"),
ImapCoroutineState::Yielded(ImapYield::WantsRead) => {
let n = stream.read(&mut buf).expect("greeting read");
arg = Some(&buf[..n]);
}
ImapCoroutineState::Yielded(ImapYield::WantsWrite(bytes)) => {
stream.write_all(&bytes).expect("greeting write");
arg = None;
}
}
}
let opts = ImapLoginOptions {
ensure_capabilities: true,
auto_id: None,
};
let mut coroutine = ImapLogin::new(username, password, opts).expect("valid credentials");
let mut arg: Option<&[u8]> = None;
loop {
match coroutine.resume(&mut fragmentizer, arg.take()) {
ImapCoroutineState::Complete(Ok(_)) => break,
ImapCoroutineState::Complete(Err(err)) => panic!("LOGIN: {err}"),
ImapCoroutineState::Yielded(ImapYield::WantsRead) => {
let n = stream.read(&mut buf).expect("login read");
arg = Some(&buf[..n]);
}
ImapCoroutineState::Yielded(ImapYield::WantsWrite(bytes)) => {
stream.write_all(&bytes).expect("login write");
arg = None;
}
}
}
let mut coroutine = ImapMailboxSelect::new(
"INBOX".try_into().unwrap(),
ImapMailboxSelectOptions::default(),
);
let mut arg: Option<&[u8]> = None;
loop {
match coroutine.resume(&mut fragmentizer, arg.take()) {
ImapCoroutineState::Complete(Ok(_)) => break,
ImapCoroutineState::Complete(Err(err)) => panic!("SELECT: {err:?}"),
ImapCoroutineState::Yielded(ImapYield::WantsRead) => {
let n = stream.read(&mut buf).expect("select read");
arg = Some(&buf[..n]);
}
ImapCoroutineState::Yielded(ImapYield::WantsWrite(bytes)) => {
stream.write_all(&bytes).expect("select write");
arg = None;
}
}
}
let mut coroutine = ImapLogout::new();
let mut arg: Option<&[u8]> = None;
loop {
match coroutine.resume(&mut fragmentizer, arg.take()) {
ImapCoroutineState::Complete(Ok(())) => break,
ImapCoroutineState::Complete(Err(err)) => panic!("LOGOUT: {err}"),
ImapCoroutineState::Yielded(ImapYield::WantsRead) => {
let n = stream.read(&mut buf).expect("logout read");
arg = Some(&buf[..n]);
}
ImapCoroutineState::Yielded(ImapYield::WantsWrite(bytes)) => {
stream.write_all(&bytes).expect("logout write");
arg = None;
}
}
}
}