diff options
Diffstat (limited to 'src/command.rs')
-rw-r--r-- | src/command.rs | 79 |
1 files changed, 48 insertions, 31 deletions
diff --git a/src/command.rs b/src/command.rs index 0b576b2..4391b39 100644 --- a/src/command.rs +++ b/src/command.rs @@ -1,5 +1,6 @@ -use boitalettres::errors::Error as BalError; +use anyhow::Result; use boitalettres::proto::{Request, Response}; +use boitalettres::errors::Error as BalError; use imap_codec::types::core::{Tag, AString}; use imap_codec::types::response::{Capability, Data}; use imap_codec::types::mailbox::{Mailbox as MailboxCodec, ListMailbox}; @@ -20,7 +21,7 @@ impl<'a> Command<'a> { Self { tag, session } } - pub async fn capability(&self) -> Result<Response, BalError> { + pub async fn capability(&self) -> Result<Response> { let capabilities = vec![Capability::Imap4Rev1, Capability::Idle]; let body = vec![Data::Capability(capabilities)]; let r = Response::ok("Pre-login capabilities listed, post-login capabilities have more.")? @@ -28,52 +29,68 @@ impl<'a> Command<'a> { Ok(r) } - pub async fn login(&mut self, username: AString, password: AString) -> Result<Response, BalError> { - let (u, p) = match (String::try_from(username), String::try_from(password)) { - (Ok(u), Ok(p)) => (u, p), - _ => return Response::bad("Invalid characters"), - }; + pub async fn login(&mut self, username: AString, password: AString) -> Result<Response> { + let (u, p) = (String::try_from(username)?, String::try_from(password)?); + tracing::info!(user = %u, "command.login"); - tracing::debug!(user = %u, "command.login"); let creds = match self.session.mailstore.login_provider.login(&u, &p).await { - Err(_) => return Response::no("[AUTHENTICATIONFAILED] Authentication failed."), + Err(_) => return Ok(Response::no("[AUTHENTICATIONFAILED] Authentication failed.")?), Ok(c) => c, }; - self.session.creds = Some(creds); - self.session.username = Some(u.clone()); + self.session.user = Some(session::User { creds, name: u.clone(), }); tracing::info!(username=%u, "connected"); - Response::ok("Logged in") + Ok(Response::ok("Logged in")?) } - pub async fn lsub(&self, reference: MailboxCodec, mailbox_wildcard: ListMailbox) -> Result<Response, BalError> { - Response::bad("Not implemented") + pub async fn lsub(&self, reference: MailboxCodec, mailbox_wildcard: ListMailbox) -> Result<Response> { + Ok(Response::bad("Not implemented")?) } - pub async fn list(&self, reference: MailboxCodec, mailbox_wildcard: ListMailbox) -> Result<Response, BalError> { - Response::bad("Not implemented") + pub async fn list(&self, reference: MailboxCodec, mailbox_wildcard: ListMailbox) -> Result<Response> { + Ok(Response::bad("Not implemented")?) } - pub async fn select(&mut self, mailbox: MailboxCodec) -> Result<Response, BalError> { - let (name, creds) = match (String::try_from(mailbox), self.session.creds.as_ref()) { - (Ok(n), Some(c)) => (n, c), - (_, None) => return Response::no("You must be connected to use SELECT"), - (Err(e), _) => { - tracing::warn!("Unable to decode mailbox name: {:#?}", e); - return Response::bad("Unable to decode mailbox name") - }, + /* + * TRACE BEGIN --- + + + Example: C: A142 SELECT INBOX + S: * 172 EXISTS + S: * 1 RECENT + S: * OK [UNSEEN 12] Message 12 is first unseen + S: * OK [UIDVALIDITY 3857529045] UIDs valid + S: * OK [UIDNEXT 4392] Predicted next UID + S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) + S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited + S: A142 OK [READ-WRITE] SELECT completed + + * TRACE END --- + */ + pub async fn select(&mut self, mailbox: MailboxCodec) -> Result<Response> { + let name = String::try_from(mailbox)?; + let user = match self.session.user.as_ref() { + Some(u) => u, + _ => return Ok(Response::no("You must be connected to use SELECT")?), }; - let mb = Mailbox::new(creds, name.clone()).unwrap(); - self.session.selected = Some(mb); - let user = self.session.username.as_ref().unwrap(); + let mut mb = Mailbox::new(&user.creds, name.clone())?; + tracing::info!(username=%user.name, mailbox=%name, "mailbox.selected"); + + let sum = mb.summary().await?; + tracing::trace!(summary=%sum, "mailbox.summary"); - tracing::info!(username=%user, mailbox=%name, "mailbox-selected"); - Response::bad("Not implemented") + let body = vec![ + Data::Exists(sum.exists.try_into()?), + Data::Recent(0), + ]; + + self.session.selected = Some(mb); + Ok(Response::ok("[READ-WRITE] Select completed")?.with_body(body)) } - pub async fn fetch(&self, sequence_set: SequenceSet, attributes: MacroOrFetchAttributes, uid: bool) -> Result<Response, BalError> { - Response::bad("Not implemented") + pub async fn fetch(&self, sequence_set: SequenceSet, attributes: MacroOrFetchAttributes, uid: bool) -> Result<Response> { + Ok(Response::bad("Not implemented")?) } } |