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 anyhow::Result;
|
||||||
use futures::stream::StreamExt;
|
|
||||||
|
|
||||||
use crate::command::Command;
|
use crate::command::Command;
|
||||||
use crate::response::{Response, ResponseDone, Status};
|
use crate::response::{Response, ResponseDone, Status};
|
||||||
|
|
|
@ -223,6 +223,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
len = read_fut => {
|
len = read_fut => {
|
||||||
|
trace!("read line {:?}", next_line);
|
||||||
// res should not be None here
|
// res should not be None here
|
||||||
let resp = parse_response(next_line)?;
|
let resp = parse_response(next_line)?;
|
||||||
|
|
||||||
|
|
|
@ -39,17 +39,13 @@ mod inner;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use futures::{
|
|
||||||
future::{self, Either, FutureExt},
|
|
||||||
stream::StreamExt,
|
|
||||||
};
|
|
||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio_rustls::{
|
use tokio_rustls::{
|
||||||
client::TlsStream, rustls::ClientConfig as RustlsConfig, webpki::DNSNameRef, TlsConnector,
|
client::TlsStream, rustls::ClientConfig as RustlsConfig, webpki::DNSNameRef, TlsConnector,
|
||||||
};
|
};
|
||||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||||
|
|
||||||
use crate::command::Command;
|
use crate::command::{Command, FetchItems, SearchCriteria};
|
||||||
use crate::response::{MailboxData, Response, ResponseData, ResponseDone};
|
use crate::response::{MailboxData, Response, ResponseData, ResponseDone};
|
||||||
|
|
||||||
pub use self::inner::{Client, ResponseStream};
|
pub use self::inner::{Client, ResponseStream};
|
||||||
|
@ -176,12 +172,11 @@ impl ClientAuthenticated {
|
||||||
let cmd = Command::Select {
|
let cmd = Command::Select {
|
||||||
mailbox: mailbox.as_ref().to_owned(),
|
mailbox: mailbox.as_ref().to_owned(),
|
||||||
};
|
};
|
||||||
let mut stream = self.execute(cmd).await?;
|
let stream = self.execute(cmd).await?;
|
||||||
// let (resp, mut st) = self.execute(cmd).await?;
|
let (done, data) = stream.wait().await?;
|
||||||
debug!("execute called returned...");
|
for resp in data {
|
||||||
debug!("ST: {:?}", stream.next().await);
|
debug!("execute called returned: {:?}", resp);
|
||||||
// let resp = resp.await?;
|
}
|
||||||
// debug!("select response: {:?}", resp);
|
|
||||||
|
|
||||||
// nuke the capabilities cache
|
// nuke the capabilities cache
|
||||||
self.nuke_capabilities();
|
self.nuke_capabilities();
|
||||||
|
@ -189,6 +184,37 @@ impl ClientAuthenticated {
|
||||||
Ok(())
|
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
|
/// Runs the IDLE command
|
||||||
#[cfg(feature = "rfc2177-idle")]
|
#[cfg(feature = "rfc2177-idle")]
|
||||||
pub async fn idle(&mut self) -> Result<ResponseStream> {
|
pub async fn idle(&mut self) -> Result<ResponseStream> {
|
||||||
|
|
|
@ -16,6 +16,17 @@ pub enum Command {
|
||||||
reference: String,
|
reference: String,
|
||||||
mailbox: String,
|
mailbox: String,
|
||||||
},
|
},
|
||||||
|
Search {
|
||||||
|
criteria: SearchCriteria,
|
||||||
|
},
|
||||||
|
UidSearch {
|
||||||
|
criteria: SearchCriteria,
|
||||||
|
},
|
||||||
|
UidFetch {
|
||||||
|
// TODO: do sequence-set
|
||||||
|
uids: Vec<u32>,
|
||||||
|
items: FetchItems,
|
||||||
|
},
|
||||||
|
|
||||||
#[cfg(feature = "rfc2177-idle")]
|
#[cfg(feature = "rfc2177-idle")]
|
||||||
Idle,
|
Idle,
|
||||||
|
@ -25,14 +36,8 @@ impl fmt::Debug for Command {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
use Command::*;
|
use Command::*;
|
||||||
match self {
|
match self {
|
||||||
Capability => write!(f, "CAPABILITY"),
|
|
||||||
Starttls => write!(f, "STARTTLS"),
|
|
||||||
Login { .. } => write!(f, "LOGIN"),
|
Login { .. } => write!(f, "LOGIN"),
|
||||||
Select { mailbox } => write!(f, "SELECT {}", mailbox),
|
_ => <Self as fmt::Display>::fmt(self, f),
|
||||||
List { reference, mailbox } => write!(f, "LIST {:?} {:?}", reference, mailbox),
|
|
||||||
|
|
||||||
#[cfg(feature = "rfc2177-idle")]
|
|
||||||
Idle => write!(f, "IDLE"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,10 +50,53 @@ impl fmt::Display for Command {
|
||||||
Starttls => write!(f, "STARTTLS"),
|
Starttls => write!(f, "STARTTLS"),
|
||||||
Login { username, password } => write!(f, "LOGIN {:?} {:?}", username, password),
|
Login { username, password } => write!(f, "LOGIN {:?} {:?}", username, password),
|
||||||
Select { mailbox } => write!(f, "SELECT {}", mailbox),
|
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),
|
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")]
|
#[cfg(feature = "rfc2177-idle")]
|
||||||
Idle => write!(f, "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,
|
index: None,
|
||||||
data: None,
|
data: None,
|
||||||
},
|
},
|
||||||
|
Rule::msg_att_static_uid => AttributeValue::Uid(build_number(unwrap1(unwrap1(pair)))),
|
||||||
_ => unreachable!("{:#?}", pair),
|
_ => unreachable!("{:#?}", pair),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,6 +314,10 @@ fn build_mailbox_data(pair: Pair<Rule>) -> MailboxData {
|
||||||
name,
|
name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Rule::mailbox_data_search => {
|
||||||
|
let uids = pair.into_inner().map(build_number).collect();
|
||||||
|
MailboxData::Search(uids)
|
||||||
|
}
|
||||||
_ => unreachable!("{:#?}", pair),
|
_ => unreachable!("{:#?}", pair),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,11 +64,12 @@ header_fld_name = { astring }
|
||||||
header_list = { "(" ~ header_fld_name ~ (sp ~ header_fld_name)* ~ ")" }
|
header_list = { "(" ~ header_fld_name ~ (sp ~ header_fld_name)* ~ ")" }
|
||||||
list_wildcards = @{ "%" | "*" }
|
list_wildcards = @{ "%" | "*" }
|
||||||
mailbox = { ^"INBOX" | astring }
|
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_exists = { number ~ sp ~ ^"EXISTS" }
|
||||||
mailbox_data_flags = { ^"FLAGS" ~ sp ~ flag_list }
|
mailbox_data_flags = { ^"FLAGS" ~ sp ~ flag_list }
|
||||||
mailbox_data_list = { ^"LIST" ~ sp ~ mailbox_list }
|
mailbox_data_list = { ^"LIST" ~ sp ~ mailbox_list }
|
||||||
mailbox_data_recent = { number ~ sp ~ ^"RECENT" }
|
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 = { mailbox_list_flags ~ sp ~ mailbox_list_string ~ sp ~ mailbox }
|
||||||
mailbox_list_flags = { "(" ~ mbx_list_flags* ~ ")" }
|
mailbox_list_flags = { "(" ~ mbx_list_flags* ~ ")" }
|
||||||
mailbox_list_string = { dquote ~ quoted_char ~ dquote | nil }
|
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 = { "(" ~ msg_att_dyn_or_stat ~ (sp ~ msg_att_dyn_or_stat)* ~ ")" }
|
||||||
msg_att_dyn_or_stat = { msg_att_dynamic | msg_att_static }
|
msg_att_dyn_or_stat = { msg_att_dynamic | msg_att_static }
|
||||||
msg_att_dynamic = { ^"FLAGS" ~ sp ~ "(" ~ (flag_fetch ~ (sp ~ flag_fetch)*)? ~ ")" }
|
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_body = { ^"BODY" ~ ^"STRUCTURE"? ~ sp ~ body }
|
||||||
msg_att_static_envelope = { ^"ENVELOPE" ~ sp ~ envelope }
|
msg_att_static_envelope = { ^"ENVELOPE" ~ sp ~ envelope }
|
||||||
msg_att_static_internaldate = { ^"INTERNALDATE" ~ sp ~ date_time }
|
msg_att_static_internaldate = { ^"INTERNALDATE" ~ sp ~ date_time }
|
||||||
msg_att_static_rfc822_size = { ^"RFC822.SIZE" ~ sp ~ number }
|
msg_att_static_rfc822_size = { ^"RFC822.SIZE" ~ sp ~ number }
|
||||||
|
msg_att_static_uid = { ^"UID" ~ sp ~ uniqueid }
|
||||||
nil = { ^"NIL" }
|
nil = { ^"NIL" }
|
||||||
nstring = { string | nil }
|
nstring = { string | nil }
|
||||||
number = @{ digit{1,} }
|
number = @{ digit{1,} }
|
||||||
|
|
|
@ -135,16 +135,18 @@ async fn imap_main(acct: MailAccountConfig, mail2ui_tx: UnboundedSender<MailEven
|
||||||
authed.select("INBOX").await?;
|
authed.select("INBOX").await?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
debug!("listing all mailboxes...");
|
|
||||||
let folder_list = authed.list().await?;
|
let folder_list = authed.list().await?;
|
||||||
debug!("mailbox list: {:?}", folder_list);
|
debug!("mailbox list: {:?}", folder_list);
|
||||||
let _ = mail2ui_tx.send(MailEvent::FolderList(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?;
|
let mut idle_stream = authed.idle().await?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
idle_stream.next().await;
|
let evt = idle_stream.next().await;
|
||||||
debug!("got an event");
|
debug!("got an event: {:?}", evt);
|
||||||
|
|
||||||
if false {
|
if false {
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue