Implement imap-flow #34
7 changed files with 58 additions and 56 deletions
|
@ -1,8 +1,7 @@
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use boitalettres::proto::{res::body::Data as Body, Request, Response};
|
use imap_codec::imap_types::command::{Command, CommandBody};
|
||||||
use imap_codec::types::command::CommandBody;
|
use imap_codec::imap_types::core::AString;
|
||||||
use imap_codec::types::core::AString;
|
use imap_codec::imap_types::response::{Capability, Data, Status, CommandContinuationRequest};
|
||||||
use imap_codec::types::response::{Capability, Data, Status};
|
|
||||||
|
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
use crate::login::ArcLoginProvider;
|
use crate::login::ArcLoginProvider;
|
||||||
|
@ -11,12 +10,12 @@ use crate::mail::user::User;
|
||||||
//--- dispatching
|
//--- dispatching
|
||||||
|
|
||||||
pub struct AnonymousContext<'a> {
|
pub struct AnonymousContext<'a> {
|
||||||
pub req: &'a Request,
|
pub req: &'a Command<'static>,
|
||||||
pub login_provider: Option<&'a ArcLoginProvider>,
|
pub login_provider: Option<&'a ArcLoginProvider>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn dispatch(ctx: AnonymousContext<'_>) -> Result<(Response, flow::Transition)> {
|
pub async fn dispatch(ctx: AnonymousContext<'_>) -> Result<(Status, flow::Transition)> {
|
||||||
match &ctx.req.command.body {
|
match &ctx.req.body {
|
||||||
CommandBody::Noop => Ok((Response::ok("Noop completed.")?, flow::Transition::None)),
|
CommandBody::Noop => Ok((Response::ok("Noop completed.")?, flow::Transition::None)),
|
||||||
CommandBody::Capability => ctx.capability().await,
|
CommandBody::Capability => ctx.capability().await,
|
||||||
CommandBody::Logout => ctx.logout().await,
|
CommandBody::Logout => ctx.logout().await,
|
||||||
|
@ -31,7 +30,7 @@ pub async fn dispatch(ctx: AnonymousContext<'_>) -> Result<(Response, flow::Tran
|
||||||
//--- Command controllers, private
|
//--- Command controllers, private
|
||||||
|
|
||||||
impl<'a> AnonymousContext<'a> {
|
impl<'a> AnonymousContext<'a> {
|
||||||
async fn capability(self) -> Result<(Response, flow::Transition)> {
|
async fn capability(self) -> Result<(Status, flow::Transition)> {
|
||||||
let capabilities = vec![Capability::Imap4Rev1, Capability::Idle];
|
let capabilities = vec![Capability::Imap4Rev1, Capability::Idle];
|
||||||
let res = Response::ok("Server capabilities")?.with_body(Data::Capability(capabilities));
|
let res = Response::ok("Server capabilities")?.with_body(Data::Capability(capabilities));
|
||||||
Ok((res, flow::Transition::None))
|
Ok((res, flow::Transition::None))
|
||||||
|
@ -41,7 +40,7 @@ impl<'a> AnonymousContext<'a> {
|
||||||
self,
|
self,
|
||||||
username: &AString,
|
username: &AString,
|
||||||
password: &AString,
|
password: &AString,
|
||||||
) -> Result<(Response, flow::Transition)> {
|
) -> Result<(Status, flow::Transition)> {
|
||||||
let (u, p) = (
|
let (u, p) = (
|
||||||
String::try_from(username.clone())?,
|
String::try_from(username.clone())?,
|
||||||
String::try_from(password.clone())?,
|
String::try_from(password.clone())?,
|
||||||
|
@ -81,7 +80,7 @@ impl<'a> AnonymousContext<'a> {
|
||||||
// C: 10 logout
|
// C: 10 logout
|
||||||
// S: * BYE Logging out
|
// S: * BYE Logging out
|
||||||
// S: 10 OK Logout completed.
|
// S: 10 OK Logout completed.
|
||||||
async fn logout(self) -> Result<(Response, flow::Transition)> {
|
async fn logout(self) -> Result<(Status, flow::Transition)> {
|
||||||
// @FIXME we should implement From<Vec<Status>> and From<Vec<ImapStatus>> in
|
// @FIXME we should implement From<Vec<Status>> and From<Vec<ImapStatus>> in
|
||||||
// boitalettres/src/proto/res/body.rs
|
// boitalettres/src/proto/res/body.rs
|
||||||
Ok((
|
Ok((
|
||||||
|
|
|
@ -4,12 +4,12 @@ use std::sync::Arc;
|
||||||
use anyhow::{anyhow, bail, Result};
|
use anyhow::{anyhow, bail, Result};
|
||||||
use boitalettres::proto::res::body::Data as Body;
|
use boitalettres::proto::res::body::Data as Body;
|
||||||
use boitalettres::proto::{Request, Response};
|
use boitalettres::proto::{Request, Response};
|
||||||
use imap_codec::types::command::{CommandBody, StatusAttribute};
|
use imap_codec::imap_types::command::{CommandBody, StatusAttribute};
|
||||||
use imap_codec::types::core::NonZeroBytes;
|
use imap_codec::imap_types::core::NonZeroBytes;
|
||||||
use imap_codec::types::datetime::MyDateTime;
|
use imap_codec::imap_types::datetime::MyDateTime;
|
||||||
use imap_codec::types::flag::{Flag, FlagNameAttribute};
|
use imap_codec::imap_types::flag::{Flag, FlagNameAttribute};
|
||||||
use imap_codec::types::mailbox::{ListMailbox, Mailbox as MailboxCodec};
|
use imap_codec::imap_types::mailbox::{ListMailbox, Mailbox as MailboxCodec};
|
||||||
use imap_codec::types::response::{Code, Data, StatusAttributeValue};
|
use imap_codec::imap_types::response::{Code, Data, StatusAttributeValue};
|
||||||
|
|
||||||
use crate::imap::command::anonymous;
|
use crate::imap::command::anonymous;
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
|
|
|
@ -3,14 +3,14 @@ use std::sync::Arc;
|
||||||
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, SearchKey};
|
use imap_codec::imap_types::command::{CommandBody, SearchKey};
|
||||||
use imap_codec::types::core::{Charset, NonZeroBytes};
|
use imap_codec::imap_types::core::{Charset, NonZeroBytes};
|
||||||
use imap_codec::types::datetime::MyDateTime;
|
use imap_codec::imap_types::datetime::MyDateTime;
|
||||||
use imap_codec::types::fetch_attributes::MacroOrFetchAttributes;
|
use imap_codec::imap_types::fetch_attributes::MacroOrFetchAttributes;
|
||||||
use imap_codec::types::flag::Flag;
|
use imap_codec::imap_types::flag::Flag;
|
||||||
use imap_codec::types::mailbox::Mailbox as MailboxCodec;
|
use imap_codec::imap_types::mailbox::Mailbox as MailboxCodec;
|
||||||
use imap_codec::types::response::Code;
|
use imap_codec::imap_types::response::Code;
|
||||||
use imap_codec::types::sequence::SequenceSet;
|
use imap_codec::imap_types::sequence::SequenceSet;
|
||||||
|
|
||||||
use crate::imap::command::authenticated;
|
use crate::imap::command::authenticated;
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
|
|
|
@ -3,11 +3,11 @@ use std::sync::Arc;
|
||||||
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::imap_types::command::CommandBody;
|
||||||
use imap_codec::types::flag::{Flag, StoreResponse, StoreType};
|
use imap_codec::imap_types::flag::{Flag, StoreResponse, StoreType};
|
||||||
use imap_codec::types::mailbox::Mailbox as MailboxCodec;
|
use imap_codec::imap_types::mailbox::Mailbox as MailboxCodec;
|
||||||
use imap_codec::types::response::Code;
|
use imap_codec::imap_types::response::Code;
|
||||||
use imap_codec::types::sequence::SequenceSet;
|
use imap_codec::imap_types::sequence::SequenceSet;
|
||||||
|
|
||||||
use crate::imap::command::examined;
|
use crate::imap::command::examined;
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
|
|
|
@ -9,17 +9,17 @@ use chrono::{Offset, TimeZone, Utc};
|
||||||
|
|
||||||
use futures::stream::{FuturesOrdered, StreamExt};
|
use futures::stream::{FuturesOrdered, StreamExt};
|
||||||
|
|
||||||
use imap_codec::types::address::Address;
|
use imap_codec::imap_types::address::Address;
|
||||||
use imap_codec::types::body::{BasicFields, Body as FetchBody, BodyStructure, SpecificFields};
|
use imap_codec::imap_types::body::{BasicFields, Body as FetchBody, BodyStructure, SpecificFields};
|
||||||
use imap_codec::types::core::{AString, Atom, IString, NString};
|
use imap_codec::imap_types::core::{AString, Atom, IString, NString};
|
||||||
use imap_codec::types::datetime::MyDateTime;
|
use imap_codec::imap_types::datetime::MyDateTime;
|
||||||
use imap_codec::types::envelope::Envelope;
|
use imap_codec::imap_types::envelope::Envelope;
|
||||||
use imap_codec::types::fetch_attributes::{
|
use imap_codec::imap_types::fetch_attributes::{
|
||||||
FetchAttribute, MacroOrFetchAttributes, Section as FetchSection,
|
FetchAttribute, MacroOrFetchAttributes, Section as FetchSection,
|
||||||
};
|
};
|
||||||
use imap_codec::types::flag::{Flag, StoreResponse, StoreType};
|
use imap_codec::imap_types::flag::{Flag, StoreResponse, StoreType};
|
||||||
use imap_codec::types::response::{Code, Data, MessageAttribute, Status};
|
use imap_codec::imap_types::response::{Code, Data, MessageAttribute, Status};
|
||||||
use imap_codec::types::sequence::{self, SequenceSet};
|
use imap_codec::imap_types::sequence::{self, SequenceSet};
|
||||||
|
|
||||||
use eml_codec::{
|
use eml_codec::{
|
||||||
header, imf, mime,
|
header, imf, mime,
|
||||||
|
@ -1246,7 +1246,7 @@ mod tests {
|
||||||
use crate::cryptoblob;
|
use crate::cryptoblob;
|
||||||
use crate::mail::unique_ident;
|
use crate::mail::unique_ident;
|
||||||
use imap_codec::codec::Encode;
|
use imap_codec::codec::Encode;
|
||||||
use imap_codec::types::fetch_attributes::Section;
|
use imap_codec::imap_types::fetch_attributes::Section;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -6,45 +6,45 @@ mod session;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use boitalettres::errors::Error as BalError;
|
//use boitalettres::errors::Error as BalError;
|
||||||
use boitalettres::proto::{Request, Response};
|
//use boitalettres::proto::{Request, Response};
|
||||||
use boitalettres::server::accept::addr::AddrIncoming;
|
//use boitalettres::server::accept::addr::AddrIncoming;
|
||||||
use boitalettres::server::accept::addr::AddrStream;
|
//use boitalettres::server::accept::addr::AddrStream;
|
||||||
use boitalettres::server::Server as ImapServer;
|
//use boitalettres::server::Server as ImapServer;
|
||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
use futures::future::FutureExt;
|
use futures::future::FutureExt;
|
||||||
use tokio::sync::watch;
|
use tokio::sync::watch;
|
||||||
use tower::Service;
|
|
||||||
|
|
||||||
use crate::config::ImapConfig;
|
use crate::config::ImapConfig;
|
||||||
use crate::login::ArcLoginProvider;
|
use crate::login::ArcLoginProvider;
|
||||||
|
|
||||||
/// Server is a thin wrapper to register our Services in BàL
|
/// Server is a thin wrapper to register our Services in BàL
|
||||||
pub struct Server(ImapServer<AddrIncoming, Instance>);
|
pub struct Server{}
|
||||||
|
|
||||||
pub async fn new(config: ImapConfig, login: ArcLoginProvider) -> Result<Server> {
|
pub async fn new(config: ImapConfig, login: ArcLoginProvider) -> Result<Server> {
|
||||||
//@FIXME add a configuration parameter
|
unimplemented!();
|
||||||
let incoming = AddrIncoming::new(config.bind_addr).await?;
|
/* let incoming = AddrIncoming::new(config.bind_addr).await?;
|
||||||
tracing::info!("IMAP activated, will listen on {:#}", incoming.local_addr);
|
tracing::info!("IMAP activated, will listen on {:#}", incoming.local_addr);
|
||||||
|
|
||||||
let imap = ImapServer::new(incoming).serve(Instance::new(login.clone()));
|
let imap = ImapServer::new(incoming).serve(Instance::new(login.clone()));
|
||||||
Ok(Server(imap))
|
Ok(Server(imap))*/
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
pub async fn run(self, mut must_exit: watch::Receiver<bool>) -> Result<()> {
|
pub async fn run(self, mut must_exit: watch::Receiver<bool>) -> Result<()> {
|
||||||
tracing::info!("IMAP started!");
|
tracing::info!("IMAP started!");
|
||||||
tokio::select! {
|
unimplemented!();
|
||||||
|
/*tokio::select! {
|
||||||
s = self.0 => s?,
|
s = self.0 => s?,
|
||||||
_ = must_exit.changed() => tracing::info!("Stopped IMAP server"),
|
_ = must_exit.changed() => tracing::info!("Stopped IMAP server"),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---
|
//---
|
||||||
|
/*
|
||||||
/// Instance is the main Tokio Tower service that we register in BàL.
|
/// Instance is the main Tokio Tower service that we register in BàL.
|
||||||
/// It receives new connection demands and spawn a dedicated service.
|
/// It receives new connection demands and spawn a dedicated service.
|
||||||
struct Instance {
|
struct Instance {
|
||||||
|
@ -103,3 +103,4 @@ impl Service<Request> for Connection {
|
||||||
self.session.process(req)
|
self.session.process(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use boitalettres::errors::Error as BalError;
|
//use boitalettres::errors::Error as BalError;
|
||||||
use boitalettres::proto::{Request, Response};
|
//use boitalettres::proto::{Request, Response};
|
||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
use futures::future::FutureExt;
|
use futures::future::FutureExt;
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ use crate::imap::command::{anonymous, authenticated, examined, selected};
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
use crate::login::ArcLoginProvider;
|
use crate::login::ArcLoginProvider;
|
||||||
|
|
||||||
|
/*
|
||||||
/* This constant configures backpressure in the system,
|
/* This constant configures backpressure in the system,
|
||||||
* or more specifically, how many pipelined messages are allowed
|
* or more specifically, how many pipelined messages are allowed
|
||||||
* before refusing them
|
* before refusing them
|
||||||
|
@ -69,9 +70,9 @@ impl Manager {
|
||||||
.boxed()
|
.boxed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
//-----
|
//-----
|
||||||
|
/*
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
rx: mpsc::Receiver<Message>,
|
rx: mpsc::Receiver<Message>,
|
||||||
|
|
||||||
|
@ -178,3 +179,4 @@ impl Instance {
|
||||||
tracing::debug!("exiting runner");
|
tracing::debug!("exiting runner");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
Loading…
Reference in a new issue