work on prototypes
This commit is contained in:
parent
1bc109df72
commit
8b7eb1ca91
8 changed files with 50 additions and 27 deletions
|
@ -1,12 +1,12 @@
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use boitalettres::proto::{res::body::Data as Body, Request, Response};
|
use boitalettres::proto::{res::body::Data as Body, Request, Response};
|
||||||
use imap_codec::types::command::CommandBody;
|
use imap_codec::types::command::CommandBody;
|
||||||
use imap_codec::types::core::{AString};
|
use imap_codec::types::core::AString;
|
||||||
use imap_codec::types::response::{Capability, Data, Status};
|
use imap_codec::types::response::{Capability, Data, Status};
|
||||||
|
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
use crate::mail::user::User;
|
|
||||||
use crate::login::ArcLoginProvider;
|
use crate::login::ArcLoginProvider;
|
||||||
|
use crate::mail::user::User;
|
||||||
|
|
||||||
//--- dispatching
|
//--- dispatching
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ impl<'a> AuthenticatedContext<'a> {
|
||||||
async fn select(self, mailbox: &MailboxCodec) -> Result<(Response, flow::Transition)> {
|
async fn select(self, mailbox: &MailboxCodec) -> Result<(Response, flow::Transition)> {
|
||||||
let name = String::try_from(mailbox.clone())?;
|
let name = String::try_from(mailbox.clone())?;
|
||||||
|
|
||||||
let mut mb = self.user.open_mailbox(name.clone())?;
|
let mut mb = self.user.open_mailbox(name)?;
|
||||||
tracing::info!(username=%self.user.username, mailbox=%name, "mailbox.selected");
|
tracing::info!(username=%self.user.username, mailbox=%name, "mailbox.selected");
|
||||||
|
|
||||||
let sum = mb.summary().await?;
|
let sum = mb.summary().await?;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use anyhow::{Result};
|
use anyhow::Result;
|
||||||
use boitalettres::proto::Request;
|
use boitalettres::proto::Request;
|
||||||
use boitalettres::proto::Response;
|
use boitalettres::proto::Response;
|
||||||
use imap_codec::types::command::CommandBody;
|
use imap_codec::types::command::CommandBody;
|
||||||
|
|
|
@ -4,7 +4,6 @@ use std::fmt;
|
||||||
use crate::mail::mailbox::Mailbox;
|
use crate::mail::mailbox::Mailbox;
|
||||||
use crate::mail::user::User;
|
use crate::mail::user::User;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
ForbiddenTransition,
|
ForbiddenTransition,
|
||||||
|
|
|
@ -2,14 +2,14 @@ use std::collections::HashMap;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::{pin::Pin, sync::Arc};
|
use std::{pin::Pin, sync::Arc};
|
||||||
|
|
||||||
use anyhow::{Result};
|
use anyhow::Result;
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use duplexify::Duplex;
|
use duplexify::Duplex;
|
||||||
use futures::{io, AsyncRead, AsyncReadExt, AsyncWrite};
|
use futures::{io, AsyncRead, AsyncReadExt, AsyncWrite};
|
||||||
use futures::{stream, stream::FuturesUnordered, StreamExt};
|
use futures::{stream, stream::FuturesUnordered, StreamExt};
|
||||||
use log::*;
|
use log::*;
|
||||||
use rusoto_s3::{PutObjectRequest, S3};
|
use rusoto_s3::{PutObjectRequest, S3};
|
||||||
use tokio::net::{TcpListener};
|
use tokio::net::TcpListener;
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use tokio::sync::watch;
|
use tokio::sync::watch;
|
||||||
use tokio_util::compat::*;
|
use tokio_util::compat::*;
|
||||||
|
|
|
@ -19,6 +19,7 @@ pub struct Summary<'a> {
|
||||||
pub flags: FlagIter<'a>,
|
pub flags: FlagIter<'a>,
|
||||||
pub unseen: Option<&'a ImapUid>,
|
pub unseen: Option<&'a ImapUid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Summary<'_> {
|
impl std::fmt::Display for Summary<'_> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
|
@ -44,14 +45,14 @@ pub struct Mailbox {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mailbox {
|
impl Mailbox {
|
||||||
pub(super) fn new(creds: &Credentials, name: String) -> Result<Self> {
|
pub(super) fn new(creds: &Credentials, name: &str) -> Result<Self> {
|
||||||
let index_path = format!("index/{}", name);
|
let index_path = format!("index/{}", name);
|
||||||
let mail_path = format!("mail/{}", name);
|
let mail_path = format!("mail/{}", name);
|
||||||
let uid_index = Bayou::<UidIndex>::new(creds, index_path)?;
|
let uid_index = Bayou::<UidIndex>::new(creds, index_path)?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
bucket: creds.bucket().to_string(),
|
bucket: creds.bucket().to_string(),
|
||||||
name,
|
name: name.to_string(), // TODO: don't use name field if possible, use mail_path instead
|
||||||
key: creds.keys.master.clone(),
|
key: creds.keys.master.clone(),
|
||||||
k2v: creds.k2v_client()?,
|
k2v: creds.k2v_client()?,
|
||||||
s3: creds.s3_client()?,
|
s3: creds.s3_client()?,
|
||||||
|
@ -60,7 +61,7 @@ impl Mailbox {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a summary of the mailbox, useful for the SELECT command for example
|
/// Get a summary of the mailbox, useful for the SELECT command for example
|
||||||
pub async fn summary(&mut self) -> Result<Summary> {
|
pub async fn summary(&mut self) -> Result<Summary> {
|
||||||
self.uid_index.sync().await?;
|
self.uid_index.sync().await?;
|
||||||
let state = self.uid_index.state();
|
let state = self.uid_index.state();
|
||||||
|
@ -85,34 +86,36 @@ impl Mailbox {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert an email in the mailbox
|
/// Insert an email in the mailbox
|
||||||
pub async fn append(&mut self, _msg: IMF) -> Result<()> {
|
pub async fn append(&mut self, _msg: IMF) -> Result<()> {
|
||||||
Ok(())
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy an email from an external to this mailbox
|
/// Copy an email from an other Mailbox to this mailbox
|
||||||
// @FIXME is it needed or could we implement it with append?
|
/// (use this when possible, as it allows for a certain number of storage optimizations)
|
||||||
pub async fn copy(&mut self, _mailbox: String, _uid: ImapUid) -> Result<()> {
|
pub async fn copy(&mut self, _from: &Mailbox, _uid: ImapUid) -> Result<()> {
|
||||||
Ok(())
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete all emails with the \Delete flag in the mailbox
|
/// Delete all emails with the \Delete flag in the mailbox
|
||||||
// Can be called by CLOSE and EXPUNGE
|
/// Can be called by CLOSE and EXPUNGE
|
||||||
// @FIXME do we want to implement this feature or a simpler "delete" command
|
/// @FIXME do we want to implement this feature or a simpler "delete" command
|
||||||
// The controller could then "fetch \Delete" and call delete on each email?
|
/// The controller could then "fetch \Delete" and call delete on each email?
|
||||||
pub async fn expunge(&mut self) -> Result<()> {
|
pub async fn expunge(&mut self) -> Result<()> {
|
||||||
Ok(())
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update flags of a range of emails
|
/// Update flags of a range of emails
|
||||||
pub async fn store(&mut self) -> Result<()> {
|
pub async fn store(&mut self) -> Result<()> {
|
||||||
Ok(())
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fetch(&mut self) -> Result<()> {
|
pub async fn fetch(&mut self) -> Result<()> {
|
||||||
Ok(())
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----
|
||||||
|
|
||||||
pub async fn test(&mut self) -> Result<()> {
|
pub async fn test(&mut self) -> Result<()> {
|
||||||
self.uid_index.sync().await?;
|
self.uid_index.sync().await?;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
pub mod mail_ident;
|
pub mod mail_ident;
|
||||||
pub mod user;
|
|
||||||
pub mod mailbox;
|
pub mod mailbox;
|
||||||
mod uidindex;
|
mod uidindex;
|
||||||
|
pub mod user;
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,28 @@ impl User {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_mailbox(&self, name: String) -> Result<Mailbox> {
|
/// Lists user's available mailboxes
|
||||||
Mailbox::new(&self.creds, name)
|
pub fn list_mailboxes(&self) -> Result<Vec<String>> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Opens an existing mailbox given its IMAP name.
|
||||||
|
pub fn open_mailbox(&self, name: &str) -> Result<Option<Mailbox>> {
|
||||||
|
Mailbox::new(&self.creds, name).map(Some)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new mailbox in the user's IMAP namespace.
|
||||||
|
pub fn create_mailbox(&self, name: &str) -> Result<()> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes a mailbox in the user's IMAP namespace.
|
||||||
|
pub fn delete_mailbox(&self, name: &str) -> Result<()> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Renames a mailbox in the user's IMAP namespace.
|
||||||
|
pub fn rename_mailbox(&self, old_name: &str, new_name: &str) -> Result<()> {
|
||||||
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue