fuckkk i have to take my parser apart now
This commit is contained in:
parent
4c989e0991
commit
da7df7dfb3
7 changed files with 107 additions and 24 deletions
|
@ -1,5 +1,4 @@
|
|||
use anyhow::Result;
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
use crate::command::Command;
|
||||
use crate::response::{Response, ResponseDone, Status};
|
||||
|
|
|
@ -223,6 +223,7 @@ where
|
|||
}
|
||||
|
||||
len = read_fut => {
|
||||
trace!("read line {:?}", next_line);
|
||||
// res should not be None here
|
||||
let resp = parse_response(next_line)?;
|
||||
|
||||
|
|
|
@ -39,17 +39,13 @@ mod inner;
|
|||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use futures::{
|
||||
future::{self, Either, FutureExt},
|
||||
stream::StreamExt,
|
||||
};
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_rustls::{
|
||||
client::TlsStream, rustls::ClientConfig as RustlsConfig, webpki::DNSNameRef, TlsConnector,
|
||||
};
|
||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||
|
||||
use crate::command::Command;
|
||||
use crate::command::{Command, FetchItems, SearchCriteria};
|
||||
use crate::response::{MailboxData, Response, ResponseData, ResponseDone};
|
||||
|
||||
pub use self::inner::{Client, ResponseStream};
|
||||
|
@ -176,12 +172,11 @@ impl ClientAuthenticated {
|
|||
let cmd = Command::Select {
|
||||
mailbox: mailbox.as_ref().to_owned(),
|
||||
};
|
||||
let mut stream = self.execute(cmd).await?;
|
||||
// let (resp, mut st) = self.execute(cmd).await?;
|
||||
debug!("execute called returned...");
|
||||
debug!("ST: {:?}", stream.next().await);
|
||||
// let resp = resp.await?;
|
||||
// debug!("select response: {:?}", resp);
|
||||
let stream = self.execute(cmd).await?;
|
||||
let (done, data) = stream.wait().await?;
|
||||
for resp in data {
|
||||
debug!("execute called returned: {:?}", resp);
|
||||
}
|
||||
|
||||
// nuke the capabilities cache
|
||||
self.nuke_capabilities();
|
||||
|
@ -189,6 +184,37 @@ impl ClientAuthenticated {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Runs the SEARCH command
|
||||
pub async fn uid_search(&mut self) -> Result<Vec<u32>> {
|
||||
let cmd = Command::UidSearch {
|
||||
criteria: SearchCriteria::All,
|
||||
};
|
||||
let stream = self.execute(cmd).await?;
|
||||
let (_, data) = stream.wait().await?;
|
||||
for resp in data {
|
||||
if let Response::MailboxData(MailboxData::Search(uids)) = resp {
|
||||
return Ok(uids);
|
||||
}
|
||||
}
|
||||
bail!("could not find the SEARCH response")
|
||||
}
|
||||
|
||||
/// Runs the UID FETCH command
|
||||
pub async fn uid_fetch(&mut self, uids: &[u32]) -> Result<()> {
|
||||
let cmd = Command::UidFetch {
|
||||
uids: uids.to_vec(),
|
||||
items: FetchItems::All,
|
||||
};
|
||||
debug!("uid fetch: {}", cmd);
|
||||
let stream = self.execute(cmd).await?;
|
||||
let (done, data) = stream.wait().await?;
|
||||
debug!("done: {:?} {:?}", done, data);
|
||||
for resp in data {
|
||||
debug!("uid fetch: {:?}", resp);
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
/// Runs the IDLE command
|
||||
#[cfg(feature = "rfc2177-idle")]
|
||||
pub async fn idle(&mut self) -> Result<ResponseStream> {
|
||||
|
|
|
@ -16,6 +16,17 @@ pub enum Command {
|
|||
reference: String,
|
||||
mailbox: String,
|
||||
},
|
||||
Search {
|
||||
criteria: SearchCriteria,
|
||||
},
|
||||
UidSearch {
|
||||
criteria: SearchCriteria,
|
||||
},
|
||||
UidFetch {
|
||||
// TODO: do sequence-set
|
||||
uids: Vec<u32>,
|
||||
items: FetchItems,
|
||||
},
|
||||
|
||||
#[cfg(feature = "rfc2177-idle")]
|
||||
Idle,
|
||||
|
@ -25,14 +36,8 @@ impl fmt::Debug for Command {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use Command::*;
|
||||
match self {
|
||||
Capability => write!(f, "CAPABILITY"),
|
||||
Starttls => write!(f, "STARTTLS"),
|
||||
Login { .. } => write!(f, "LOGIN"),
|
||||
Select { mailbox } => write!(f, "SELECT {}", mailbox),
|
||||
List { reference, mailbox } => write!(f, "LIST {:?} {:?}", reference, mailbox),
|
||||
|
||||
#[cfg(feature = "rfc2177-idle")]
|
||||
Idle => write!(f, "IDLE"),
|
||||
_ => <Self as fmt::Display>::fmt(self, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +50,53 @@ impl fmt::Display for Command {
|
|||
Starttls => write!(f, "STARTTLS"),
|
||||
Login { username, password } => write!(f, "LOGIN {:?} {:?}", username, password),
|
||||
Select { mailbox } => write!(f, "SELECT {}", mailbox),
|
||||
Search { criteria } => write!(f, "SEARCH {}", criteria),
|
||||
UidSearch { criteria } => write!(f, "UID SEARCH {}", criteria),
|
||||
List { reference, mailbox } => write!(f, "LIST {:?} {:?}", reference, mailbox),
|
||||
UidFetch { uids, items } => write!(
|
||||
f,
|
||||
"UID FETCH {} {}",
|
||||
uids.iter()
|
||||
.map(|s| s.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(","),
|
||||
items
|
||||
),
|
||||
|
||||
#[cfg(feature = "rfc2177-idle")]
|
||||
Idle => write!(f, "IDLE"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum SearchCriteria {
|
||||
All,
|
||||
}
|
||||
|
||||
impl fmt::Display for SearchCriteria {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use SearchCriteria::*;
|
||||
match self {
|
||||
All => write!(f, "ALL"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum FetchItems {
|
||||
All,
|
||||
Fast,
|
||||
Full,
|
||||
}
|
||||
|
||||
impl fmt::Display for FetchItems {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use FetchItems::*;
|
||||
match self {
|
||||
All => write!(f, "ALL"),
|
||||
Fast => write!(f, "FAST"),
|
||||
Full => write!(f, "FULL"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,6 +152,7 @@ fn build_msg_att_static(pair: Pair<Rule>) -> AttributeValue {
|
|||
index: None,
|
||||
data: None,
|
||||
},
|
||||
Rule::msg_att_static_uid => AttributeValue::Uid(build_number(unwrap1(unwrap1(pair)))),
|
||||
_ => unreachable!("{:#?}", pair),
|
||||
}
|
||||
}
|
||||
|
@ -313,6 +314,10 @@ fn build_mailbox_data(pair: Pair<Rule>) -> MailboxData {
|
|||
name,
|
||||
}
|
||||
}
|
||||
Rule::mailbox_data_search => {
|
||||
let uids = pair.into_inner().map(build_number).collect();
|
||||
MailboxData::Search(uids)
|
||||
}
|
||||
_ => unreachable!("{:#?}", pair),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,11 +64,12 @@ header_fld_name = { astring }
|
|||
header_list = { "(" ~ header_fld_name ~ (sp ~ header_fld_name)* ~ ")" }
|
||||
list_wildcards = @{ "%" | "*" }
|
||||
mailbox = { ^"INBOX" | astring }
|
||||
mailbox_data = { mailbox_data_flags | mailbox_data_list | (^"LSUB" ~ sp ~ mailbox_list) | (^"SEARCH" ~ (sp ~ nz_number)*) | (^"STATUS" ~ sp ~ mailbox ~ sp ~ ^"(" ~ status_att_list? ~ ^")") | mailbox_data_exists | mailbox_data_recent }
|
||||
mailbox_data = { mailbox_data_flags | mailbox_data_list | (^"LSUB" ~ sp ~ mailbox_list) | mailbox_data_search | (^"STATUS" ~ sp ~ mailbox ~ sp ~ ^"(" ~ status_att_list? ~ ^")") | mailbox_data_exists | mailbox_data_recent }
|
||||
mailbox_data_exists = { number ~ sp ~ ^"EXISTS" }
|
||||
mailbox_data_flags = { ^"FLAGS" ~ sp ~ flag_list }
|
||||
mailbox_data_list = { ^"LIST" ~ sp ~ mailbox_list }
|
||||
mailbox_data_recent = { number ~ sp ~ ^"RECENT" }
|
||||
mailbox_data_search = { ^"SEARCH" ~ (sp ~ nz_number)* }
|
||||
mailbox_list = { mailbox_list_flags ~ sp ~ mailbox_list_string ~ sp ~ mailbox }
|
||||
mailbox_list_flags = { "(" ~ mbx_list_flags* ~ ")" }
|
||||
mailbox_list_string = { dquote ~ quoted_char ~ dquote | nil }
|
||||
|
@ -85,11 +86,12 @@ message_data_fetch = { ^"FETCH" ~ sp ~ msg_att }
|
|||
msg_att = { "(" ~ msg_att_dyn_or_stat ~ (sp ~ msg_att_dyn_or_stat)* ~ ")" }
|
||||
msg_att_dyn_or_stat = { msg_att_dynamic | msg_att_static }
|
||||
msg_att_dynamic = { ^"FLAGS" ~ sp ~ "(" ~ (flag_fetch ~ (sp ~ flag_fetch)*)? ~ ")" }
|
||||
msg_att_static = { msg_att_static_envelope | msg_att_static_internaldate | (^"RFC822" ~ (^".HEADER" | ^".TEXT") ~ sp ~ nstring) | msg_att_static_rfc822_size | msg_att_static_body | (^"BODY" ~ section ~ ("<" ~ number ~ ">")? ~ sp ~ nstring) | (^"UID" ~ sp ~ uniqueid) }
|
||||
msg_att_static = { msg_att_static_envelope | msg_att_static_internaldate | (^"RFC822" ~ (^".HEADER" | ^".TEXT") ~ sp ~ nstring) | msg_att_static_rfc822_size | msg_att_static_body | (^"BODY" ~ section ~ ("<" ~ number ~ ">")? ~ sp ~ nstring) | msg_att_static_uid }
|
||||
msg_att_static_body = { ^"BODY" ~ ^"STRUCTURE"? ~ sp ~ body }
|
||||
msg_att_static_envelope = { ^"ENVELOPE" ~ sp ~ envelope }
|
||||
msg_att_static_internaldate = { ^"INTERNALDATE" ~ sp ~ date_time }
|
||||
msg_att_static_rfc822_size = { ^"RFC822.SIZE" ~ sp ~ number }
|
||||
msg_att_static_uid = { ^"UID" ~ sp ~ uniqueid }
|
||||
nil = { ^"NIL" }
|
||||
nstring = { string | nil }
|
||||
number = @{ digit{1,} }
|
||||
|
|
|
@ -135,16 +135,18 @@ async fn imap_main(acct: MailAccountConfig, mail2ui_tx: UnboundedSender<MailEven
|
|||
authed.select("INBOX").await?;
|
||||
|
||||
loop {
|
||||
debug!("listing all mailboxes...");
|
||||
let folder_list = authed.list().await?;
|
||||
debug!("mailbox list: {:?}", folder_list);
|
||||
let _ = mail2ui_tx.send(MailEvent::FolderList(folder_list));
|
||||
|
||||
let message_list = authed.uid_search().await?;
|
||||
authed.uid_fetch(&message_list).await?;
|
||||
|
||||
let mut idle_stream = authed.idle().await?;
|
||||
|
||||
loop {
|
||||
idle_stream.next().await;
|
||||
debug!("got an event");
|
||||
let evt = idle_stream.next().await;
|
||||
debug!("got an event: {:?}", evt);
|
||||
|
||||
if false {
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue