cargo fmt
This commit is contained in:
parent
ac974184de
commit
cea27474f9
7 changed files with 174 additions and 113 deletions
|
@ -1,5 +1,4 @@
|
||||||
|
use anyhow::{Error, Result};
|
||||||
use anyhow::{Result, Error};
|
|
||||||
use boitalettres::proto::Response;
|
use boitalettres::proto::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;
|
||||||
|
@ -14,7 +13,11 @@ pub async fn dispatch<'a>(ctx: InnerContext<'a>) -> Result<(Response, flow::Tran
|
||||||
match &ctx.req.body {
|
match &ctx.req.body {
|
||||||
CommandBody::Capability => capability(ctx).await,
|
CommandBody::Capability => capability(ctx).await,
|
||||||
CommandBody::Login { username, password } => login(ctx, username, password).await,
|
CommandBody::Login { username, password } => login(ctx, username, password).await,
|
||||||
_ => Status::no(Some(ctx.req.tag.clone()), None, "This command is not available in the ANONYMOUS state.")
|
_ => Status::no(
|
||||||
|
Some(ctx.req.tag.clone()),
|
||||||
|
None,
|
||||||
|
"This command is not available in the ANONYMOUS state.",
|
||||||
|
)
|
||||||
.map(|s| (vec![ImapRes::Status(s)], flow::Transition::No))
|
.map(|s| (vec![ImapRes::Status(s)], flow::Transition::No))
|
||||||
.map_err(Error::msg),
|
.map_err(Error::msg),
|
||||||
}
|
}
|
||||||
|
@ -34,17 +37,27 @@ async fn capability<'a>(ctx: InnerContext<'a>) -> Result<(Response, flow::Transi
|
||||||
Ok((res, flow::Transition::No))
|
Ok((res, flow::Transition::No))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn login<'a>(ctx: InnerContext<'a>, username: &AString, password: &AString) -> Result<(Response, flow::Transition)> {
|
async fn login<'a>(
|
||||||
let (u, p) = (String::try_from(username.clone())?, String::try_from(password.clone())?);
|
ctx: InnerContext<'a>,
|
||||||
|
username: &AString,
|
||||||
|
password: &AString,
|
||||||
|
) -> Result<(Response, flow::Transition)> {
|
||||||
|
let (u, p) = (
|
||||||
|
String::try_from(username.clone())?,
|
||||||
|
String::try_from(password.clone())?,
|
||||||
|
);
|
||||||
tracing::info!(user = %u, "command.login");
|
tracing::info!(user = %u, "command.login");
|
||||||
|
|
||||||
let creds = match ctx.login.login(&u, &p).await {
|
let creds = match ctx.login.login(&u, &p).await {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::debug!(error=%e, "authentication failed");
|
tracing::debug!(error=%e, "authentication failed");
|
||||||
return Ok((vec![ImapRes::Status(
|
return Ok((
|
||||||
|
vec![ImapRes::Status(
|
||||||
Status::no(Some(ctx.req.tag.clone()), None, "Authentication failed")
|
Status::no(Some(ctx.req.tag.clone()), None, "Authentication failed")
|
||||||
.map_err(Error::msg)?,
|
.map_err(Error::msg)?,
|
||||||
)], flow::Transition::No));
|
)],
|
||||||
|
flow::Transition::No,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
};
|
};
|
||||||
|
@ -56,10 +69,13 @@ async fn login<'a>(ctx: InnerContext<'a>, username: &AString, password: &AString
|
||||||
let tr = flow::Transition::Authenticate(user);
|
let tr = flow::Transition::Authenticate(user);
|
||||||
|
|
||||||
tracing::info!(username=%u, "connected");
|
tracing::info!(username=%u, "connected");
|
||||||
Ok((vec![
|
Ok((
|
||||||
|
vec![
|
||||||
//@FIXME we could send a capability status here too
|
//@FIXME we could send a capability status here too
|
||||||
ImapRes::Status(
|
ImapRes::Status(
|
||||||
Status::ok(Some(ctx.req.tag.clone()), None, "completed").map_err(Error::msg)?,
|
Status::ok(Some(ctx.req.tag.clone()), None, "completed").map_err(Error::msg)?,
|
||||||
),
|
),
|
||||||
], tr))
|
],
|
||||||
|
tr,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
|
use anyhow::{anyhow, Error, Result};
|
||||||
use anyhow::{Result, Error, anyhow};
|
|
||||||
use boitalettres::proto::Response;
|
use boitalettres::proto::Response;
|
||||||
use imap_codec::types::command::CommandBody;
|
use imap_codec::types::command::CommandBody;
|
||||||
use imap_codec::types::core::Tag;
|
use imap_codec::types::core::Tag;
|
||||||
|
@ -7,16 +6,29 @@ use imap_codec::types::mailbox::{ListMailbox, Mailbox as MailboxCodec};
|
||||||
use imap_codec::types::response::{Code, Data, Response as ImapRes, Status};
|
use imap_codec::types::response::{Code, Data, Response as ImapRes, Status};
|
||||||
|
|
||||||
use crate::imap::command::anonymous;
|
use crate::imap::command::anonymous;
|
||||||
use crate::imap::session::InnerContext;
|
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
|
use crate::imap::session::InnerContext;
|
||||||
use crate::mailbox::Mailbox;
|
use crate::mailbox::Mailbox;
|
||||||
|
|
||||||
pub async fn dispatch<'a>(inner: InnerContext<'a>, user: &'a flow::User) -> Result<(Response, flow::Transition)> {
|
pub async fn dispatch<'a>(
|
||||||
let ctx = StateContext { user, tag: &inner.req.tag, inner };
|
inner: InnerContext<'a>,
|
||||||
|
user: &'a flow::User,
|
||||||
|
) -> Result<(Response, flow::Transition)> {
|
||||||
|
let ctx = StateContext {
|
||||||
|
user,
|
||||||
|
tag: &inner.req.tag,
|
||||||
|
inner,
|
||||||
|
};
|
||||||
|
|
||||||
match &ctx.inner.req.body {
|
match &ctx.inner.req.body {
|
||||||
CommandBody::Lsub { reference, mailbox_wildcard, } => ctx.lsub(reference, mailbox_wildcard).await,
|
CommandBody::Lsub {
|
||||||
CommandBody::List { reference, mailbox_wildcard, } => ctx.list(reference, mailbox_wildcard).await,
|
reference,
|
||||||
|
mailbox_wildcard,
|
||||||
|
} => ctx.lsub(reference, mailbox_wildcard).await,
|
||||||
|
CommandBody::List {
|
||||||
|
reference,
|
||||||
|
mailbox_wildcard,
|
||||||
|
} => ctx.list(reference, mailbox_wildcard).await,
|
||||||
CommandBody::Select { mailbox } => ctx.select(mailbox).await,
|
CommandBody::Select { mailbox } => ctx.select(mailbox).await,
|
||||||
_ => anonymous::dispatch(ctx.inner).await,
|
_ => anonymous::dispatch(ctx.inner).await,
|
||||||
}
|
}
|
||||||
|
@ -24,7 +36,6 @@ pub async fn dispatch<'a>(inner: InnerContext<'a>, user: &'a flow::User) -> Resu
|
||||||
|
|
||||||
// --- PRIVATE ---
|
// --- PRIVATE ---
|
||||||
|
|
||||||
|
|
||||||
struct StateContext<'a> {
|
struct StateContext<'a> {
|
||||||
inner: InnerContext<'a>,
|
inner: InnerContext<'a>,
|
||||||
user: &'a flow::User,
|
user: &'a flow::User,
|
||||||
|
@ -37,9 +48,12 @@ impl<'a> StateContext<'a> {
|
||||||
reference: &MailboxCodec,
|
reference: &MailboxCodec,
|
||||||
mailbox_wildcard: &ListMailbox,
|
mailbox_wildcard: &ListMailbox,
|
||||||
) -> Result<(Response, flow::Transition)> {
|
) -> Result<(Response, flow::Transition)> {
|
||||||
Ok((vec![ImapRes::Status(
|
Ok((
|
||||||
|
vec![ImapRes::Status(
|
||||||
Status::bad(Some(self.tag.clone()), None, "Not implemented").map_err(Error::msg)?,
|
Status::bad(Some(self.tag.clone()), None, "Not implemented").map_err(Error::msg)?,
|
||||||
)], flow::Transition::No))
|
)],
|
||||||
|
flow::Transition::No,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn list(
|
async fn list(
|
||||||
|
@ -47,9 +61,12 @@ impl<'a> StateContext<'a> {
|
||||||
reference: &MailboxCodec,
|
reference: &MailboxCodec,
|
||||||
mailbox_wildcard: &ListMailbox,
|
mailbox_wildcard: &ListMailbox,
|
||||||
) -> Result<(Response, flow::Transition)> {
|
) -> Result<(Response, flow::Transition)> {
|
||||||
Ok((vec![
|
Ok((
|
||||||
ImapRes::Status(Status::bad(Some(self.tag.clone()), None, "Not implemented").map_err(Error::msg)?),
|
vec![ImapRes::Status(
|
||||||
], flow::Transition::No))
|
Status::bad(Some(self.tag.clone()), None, "Not implemented").map_err(Error::msg)?,
|
||||||
|
)],
|
||||||
|
flow::Transition::No,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -74,7 +91,6 @@ impl<'a> StateContext<'a> {
|
||||||
let mut mb = Mailbox::new(&self.user.creds, name.clone())?;
|
let mut mb = Mailbox::new(&self.user.creds, name.clone())?;
|
||||||
tracing::info!(username=%self.user.name, mailbox=%name, "mailbox.selected");
|
tracing::info!(username=%self.user.name, mailbox=%name, "mailbox.selected");
|
||||||
|
|
||||||
|
|
||||||
let sum = mb.summary().await?;
|
let sum = mb.summary().await?;
|
||||||
tracing::trace!(summary=%sum, "mailbox.summary");
|
tracing::trace!(summary=%sum, "mailbox.summary");
|
||||||
|
|
||||||
|
@ -82,21 +98,34 @@ impl<'a> StateContext<'a> {
|
||||||
|
|
||||||
let tr = flow::Transition::Select(mb);
|
let tr = flow::Transition::Select(mb);
|
||||||
|
|
||||||
let r_unseen = Status::ok(None, Some(Code::Unseen(std::num::NonZeroU32::new(1).ok_or(anyhow!("Invalid message identifier"))?)), "First unseen UID").map_err(Error::msg)?;
|
let r_unseen = Status::ok(
|
||||||
|
None,
|
||||||
|
Some(Code::Unseen(
|
||||||
|
std::num::NonZeroU32::new(1).ok_or(anyhow!("Invalid message identifier"))?,
|
||||||
|
)),
|
||||||
|
"First unseen UID",
|
||||||
|
)
|
||||||
|
.map_err(Error::msg)?;
|
||||||
//let r_permanentflags = Status::ok(None, Some(Code::
|
//let r_permanentflags = Status::ok(None, Some(Code::
|
||||||
|
|
||||||
Ok((vec![
|
Ok((
|
||||||
|
vec![
|
||||||
ImapRes::Data(Data::Exists(0)),
|
ImapRes::Data(Data::Exists(0)),
|
||||||
ImapRes::Data(Data::Recent(0)),
|
ImapRes::Data(Data::Recent(0)),
|
||||||
ImapRes::Data(Data::Flags(vec![])),
|
ImapRes::Data(Data::Flags(vec![])),
|
||||||
/*ImapRes::Status(),
|
/*ImapRes::Status(),
|
||||||
ImapRes::Status(),
|
ImapRes::Status(),
|
||||||
ImapRes::Status(),*/
|
ImapRes::Status(),*/
|
||||||
ImapRes::Status(Status::ok(
|
ImapRes::Status(
|
||||||
|
Status::ok(
|
||||||
Some(self.tag.clone()),
|
Some(self.tag.clone()),
|
||||||
Some(Code::ReadWrite),
|
Some(Code::ReadWrite),
|
||||||
"Select completed",
|
"Select completed",
|
||||||
).map_err(Error::msg)?),
|
)
|
||||||
], tr))
|
.map_err(Error::msg)?,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
tr,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
|
use anyhow::{Error, Result};
|
||||||
use anyhow::{Result, Error};
|
|
||||||
use boitalettres::proto::Response;
|
use boitalettres::proto::Response;
|
||||||
use imap_codec::types::command::CommandBody;
|
use imap_codec::types::command::CommandBody;
|
||||||
use imap_codec::types::core::Tag;
|
use imap_codec::types::core::Tag;
|
||||||
|
@ -8,21 +7,32 @@ use imap_codec::types::response::{Response as ImapRes, Status};
|
||||||
use imap_codec::types::sequence::SequenceSet;
|
use imap_codec::types::sequence::SequenceSet;
|
||||||
|
|
||||||
use crate::imap::command::authenticated;
|
use crate::imap::command::authenticated;
|
||||||
use crate::imap::session::InnerContext;
|
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
|
use crate::imap::session::InnerContext;
|
||||||
use crate::mailbox::Mailbox;
|
use crate::mailbox::Mailbox;
|
||||||
|
|
||||||
|
pub async fn dispatch<'a>(
|
||||||
pub async fn dispatch<'a>(inner: InnerContext<'a>, user: &'a flow::User, mailbox: &'a Mailbox) -> Result<(Response, flow::Transition)> {
|
inner: InnerContext<'a>,
|
||||||
let ctx = StateContext { tag: &inner.req.tag, inner, user, mailbox };
|
user: &'a flow::User,
|
||||||
|
mailbox: &'a Mailbox,
|
||||||
|
) -> Result<(Response, flow::Transition)> {
|
||||||
|
let ctx = StateContext {
|
||||||
|
tag: &inner.req.tag,
|
||||||
|
inner,
|
||||||
|
user,
|
||||||
|
mailbox,
|
||||||
|
};
|
||||||
|
|
||||||
match &ctx.inner.req.body {
|
match &ctx.inner.req.body {
|
||||||
CommandBody::Fetch { sequence_set, attributes, uid, } => ctx.fetch(sequence_set, attributes, uid).await,
|
CommandBody::Fetch {
|
||||||
|
sequence_set,
|
||||||
|
attributes,
|
||||||
|
uid,
|
||||||
|
} => ctx.fetch(sequence_set, attributes, uid).await,
|
||||||
_ => authenticated::dispatch(ctx.inner, user).await,
|
_ => authenticated::dispatch(ctx.inner, user).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- PRIVATE ---
|
// --- PRIVATE ---
|
||||||
|
|
||||||
struct StateContext<'a> {
|
struct StateContext<'a> {
|
||||||
|
@ -32,7 +42,6 @@ struct StateContext<'a> {
|
||||||
tag: &'a Tag,
|
tag: &'a Tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> StateContext<'a> {
|
impl<'a> StateContext<'a> {
|
||||||
pub async fn fetch(
|
pub async fn fetch(
|
||||||
&self,
|
&self,
|
||||||
|
@ -40,8 +49,11 @@ impl<'a> StateContext<'a> {
|
||||||
attributes: &MacroOrFetchAttributes,
|
attributes: &MacroOrFetchAttributes,
|
||||||
uid: &bool,
|
uid: &bool,
|
||||||
) -> Result<(Response, flow::Transition)> {
|
) -> Result<(Response, flow::Transition)> {
|
||||||
Ok((vec![
|
Ok((
|
||||||
ImapRes::Status(Status::bad(Some(self.tag.clone()), None, "Not implemented").map_err(Error::msg)?),
|
vec![ImapRes::Status(
|
||||||
], flow::Transition::No))
|
Status::bad(Some(self.tag.clone()), None, "Not implemented").map_err(Error::msg)?,
|
||||||
|
)],
|
||||||
|
flow::Transition::No,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::fmt;
|
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
use crate::login::Credentials;
|
use crate::login::Credentials;
|
||||||
use crate::mailbox::Mailbox;
|
use crate::mailbox::Mailbox;
|
||||||
|
@ -18,14 +18,13 @@ impl fmt::Display for Error {
|
||||||
write!(f, "Forbidden Transition")
|
write!(f, "Forbidden Transition")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl StdError for Error { }
|
impl StdError for Error {}
|
||||||
|
|
||||||
|
|
||||||
pub enum State {
|
pub enum State {
|
||||||
NotAuthenticated,
|
NotAuthenticated,
|
||||||
Authenticated(User),
|
Authenticated(User),
|
||||||
Selected(User, Mailbox),
|
Selected(User, Mailbox),
|
||||||
Logout
|
Logout,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Transition {
|
pub enum Transition {
|
||||||
|
@ -50,4 +49,3 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
mod session;
|
|
||||||
mod flow;
|
|
||||||
mod command;
|
mod command;
|
||||||
|
mod flow;
|
||||||
|
mod session;
|
||||||
|
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
|
@ -15,16 +15,12 @@ use futures::future::FutureExt;
|
||||||
use tokio::sync::watch;
|
use tokio::sync::watch;
|
||||||
use tower::Service;
|
use tower::Service;
|
||||||
|
|
||||||
use crate::login::ArcLoginProvider;
|
|
||||||
use crate::config::ImapConfig;
|
use crate::config::ImapConfig;
|
||||||
|
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(ImapServer<AddrIncoming, Instance>);
|
||||||
pub async fn new(
|
pub async fn new(config: ImapConfig, login: ArcLoginProvider) -> Result<Server> {
|
||||||
config: ImapConfig,
|
|
||||||
login: ArcLoginProvider,
|
|
||||||
) -> Result<Server> {
|
|
||||||
|
|
||||||
//@FIXME add a configuration parameter
|
//@FIXME add a configuration parameter
|
||||||
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);
|
||||||
|
|
|
@ -7,7 +7,7 @@ use imap_codec::types::response::{Response as ImapRes, Status};
|
||||||
use tokio::sync::mpsc::error::TrySendError;
|
use tokio::sync::mpsc::error::TrySendError;
|
||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
use crate::imap::command::{anonymous,authenticated,selected};
|
use crate::imap::command::{anonymous, authenticated, selected};
|
||||||
use crate::imap::flow;
|
use crate::imap::flow;
|
||||||
use crate::login::ArcLoginProvider;
|
use crate::login::ArcLoginProvider;
|
||||||
|
|
||||||
|
@ -98,10 +98,7 @@ pub struct Instance {
|
||||||
pub state: flow::State,
|
pub state: flow::State,
|
||||||
}
|
}
|
||||||
impl Instance {
|
impl Instance {
|
||||||
fn new(
|
fn new(login_provider: ArcLoginProvider, rx: mpsc::Receiver<Message>) -> Self {
|
||||||
login_provider: ArcLoginProvider,
|
|
||||||
rx: mpsc::Receiver<Message>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
login_provider,
|
login_provider,
|
||||||
rx,
|
rx,
|
||||||
|
@ -118,7 +115,11 @@ impl Instance {
|
||||||
tracing::debug!("starting runner");
|
tracing::debug!("starting runner");
|
||||||
|
|
||||||
while let Some(msg) = self.rx.recv().await {
|
while let Some(msg) = self.rx.recv().await {
|
||||||
let ctx = InnerContext { req: &msg.req, state: &self.state, login: &self.login_provider };
|
let ctx = InnerContext {
|
||||||
|
req: &msg.req,
|
||||||
|
state: &self.state,
|
||||||
|
login: &self.login_provider,
|
||||||
|
};
|
||||||
|
|
||||||
// Command behavior is modulated by the state.
|
// Command behavior is modulated by the state.
|
||||||
// To prevent state error, we handle the same command in separate code path depending
|
// To prevent state error, we handle the same command in separate code path depending
|
||||||
|
@ -126,8 +127,14 @@ impl Instance {
|
||||||
let ctrl = match &self.state {
|
let ctrl = match &self.state {
|
||||||
flow::State::NotAuthenticated => anonymous::dispatch(ctx).await,
|
flow::State::NotAuthenticated => anonymous::dispatch(ctx).await,
|
||||||
flow::State::Authenticated(user) => authenticated::dispatch(ctx, user).await,
|
flow::State::Authenticated(user) => authenticated::dispatch(ctx, user).await,
|
||||||
flow::State::Selected(user, mailbox) => selected::dispatch(ctx, user, mailbox).await,
|
flow::State::Selected(user, mailbox) => {
|
||||||
_ => Status::bad(Some(ctx.req.tag.clone()), None, "No commands are allowed in the LOGOUT state.")
|
selected::dispatch(ctx, user, mailbox).await
|
||||||
|
}
|
||||||
|
_ => Status::bad(
|
||||||
|
Some(ctx.req.tag.clone()),
|
||||||
|
None,
|
||||||
|
"No commands are allowed in the LOGOUT state.",
|
||||||
|
)
|
||||||
.map(|s| (vec![ImapRes::Status(s)], flow::Transition::No))
|
.map(|s| (vec![ImapRes::Status(s)], flow::Transition::No))
|
||||||
.map_err(Error::msg),
|
.map_err(Error::msg),
|
||||||
};
|
};
|
||||||
|
@ -138,7 +145,7 @@ impl Instance {
|
||||||
//@FIXME unwrap
|
//@FIXME unwrap
|
||||||
self.state = self.state.apply(tr).unwrap();
|
self.state = self.state.apply(tr).unwrap();
|
||||||
Ok(res)
|
Ok(res)
|
||||||
},
|
}
|
||||||
// Cast from anyhow::Error to Bal::Error
|
// Cast from anyhow::Error to Bal::Error
|
||||||
// @FIXME proper error handling would be great
|
// @FIXME proper error handling would be great
|
||||||
Err(e) => match e.downcast::<BalError>() {
|
Err(e) => match e.downcast::<BalError>() {
|
||||||
|
@ -149,7 +156,7 @@ impl Instance {
|
||||||
.map(|s| vec![ImapRes::Status(s)])
|
.map(|s| vec![ImapRes::Status(s)])
|
||||||
.map_err(|e| BalError::Text(e.to_string()))
|
.map_err(|e| BalError::Text(e.to_string()))
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
//@FIXME I think we should quit this thread on error and having our manager watch it,
|
//@FIXME I think we should quit this thread on error and having our manager watch it,
|
||||||
|
@ -161,5 +168,5 @@ impl Instance {
|
||||||
|
|
||||||
//@FIXME add more info about the runner
|
//@FIXME add more info about the runner
|
||||||
tracing::debug!("exiting runner");
|
tracing::debug!("exiting runner");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,10 @@ use rusoto_signature::Region;
|
||||||
use tokio::sync::watch;
|
use tokio::sync::watch;
|
||||||
|
|
||||||
use crate::config::*;
|
use crate::config::*;
|
||||||
use crate::lmtp::*;
|
|
||||||
use crate::login::{ldap_provider::*, static_provider::*, *};
|
|
||||||
use crate::imap;
|
use crate::imap;
|
||||||
|
use crate::lmtp::*;
|
||||||
use crate::login::ArcLoginProvider;
|
use crate::login::ArcLoginProvider;
|
||||||
|
use crate::login::{ldap_provider::*, static_provider::*, *};
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
lmtp_server: Option<Arc<LmtpServer>>,
|
lmtp_server: Option<Arc<LmtpServer>>,
|
||||||
|
@ -27,7 +27,10 @@ impl Server {
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self { lmtp_server, imap_server })
|
Ok(Self {
|
||||||
|
lmtp_server,
|
||||||
|
imap_server,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run(self) -> Result<()> {
|
pub async fn run(self) -> Result<()> {
|
||||||
|
|
Loading…
Reference in a new issue