diff options
author | Quentin Dufour <quentin@deuxfleurs.fr> | 2022-06-15 18:40:39 +0200 |
---|---|---|
committer | Quentin Dufour <quentin@deuxfleurs.fr> | 2022-06-15 18:40:39 +0200 |
commit | 6b5b53916efb4897643172fdf461291b4effcf48 (patch) | |
tree | 9030270809e8b2fd56bc91b19d82915ea8c85641 /src/server.rs | |
parent | 2bbcb119c437a3d8ba5d747f76898faa5ad32d93 (diff) | |
parent | 0700e27127e4644dbd323b9a22d994209143fa2a (diff) | |
download | aerogramme-6b5b53916efb4897643172fdf461291b4effcf48.tar.gz aerogramme-6b5b53916efb4897643172fdf461291b4effcf48.zip |
Add LMTP support
Diffstat (limited to 'src/server.rs')
-rw-r--r-- | src/server.rs | 107 |
1 files changed, 87 insertions, 20 deletions
diff --git a/src/server.rs b/src/server.rs index 365bc0f..3abdfd1 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,40 +1,107 @@ -use anyhow::Result; use std::sync::Arc; -use crate::config::*; -use crate::mailstore; -use crate::service; + use boitalettres::server::accept::addr::AddrIncoming; +use boitalettres::server::accept::addr::AddrStream; use boitalettres::server::Server as ImapServer; +use anyhow::{bail, Result}; +use futures::{try_join, StreamExt}; +use log::*; +use rusoto_signature::Region; +use tokio::sync::watch; +use tower::Service; + +use crate::mailstore; +use crate::service; +use crate::lmtp::*; +use crate::config::*; +use crate::login::{ldap_provider::*, static_provider::*, *}; +use crate::mailbox::Mailbox; + pub struct Server { - pub incoming: AddrIncoming, - pub mailstore: Arc<mailstore::Mailstore>, + lmtp_server: Option<Arc<LmtpServer>>, + imap_server: ImapServer<AddrIncoming, service::Instance>, } + impl Server { pub async fn new(config: Config) -> Result<Self> { + let lmtp_config = config.lmtp.clone(); //@FIXME + let login = authenticator(config)?; + + let lmtp = lmtp_config.map(|cfg| LmtpServer::new(cfg, login.clone())); + + let incoming = AddrIncoming::new("127.0.0.1:4567").await?; + let imap = ImapServer::new(incoming).serve(service::Instance::new(login.clone())); + Ok(Self { - incoming: AddrIncoming::new("127.0.0.1:4567").await?, - mailstore: mailstore::Mailstore::new(config)?, + lmtp_server: lmtp, + imap_server: imap, }) } - pub async fn run(self: Self) -> Result<()> { - tracing::info!("Starting server on {:#}", self.incoming.local_addr); - /*let creds = self - .mailstore - .login_provider - .login("quentin", "poupou") - .await?;*/ - //let mut mailbox = Mailbox::new(&creds, "TestMailbox".to_string()).await?; - //mailbox.test().await?; + pub async fn run(self) -> Result<()> { + //tracing::info!("Starting server on {:#}", self.imap.incoming.local_addr); + tracing::info!("Starting Aerogramme..."); + + let (exit_signal, provoke_exit) = watch_ctrl_c(); + let exit_on_err = move |err: anyhow::Error| { + error!("Error: {}", err); + let _ = provoke_exit.send(true); + }; + + + try_join!(async { + match self.lmtp_server.as_ref() { + None => Ok(()), + Some(s) => s.run(exit_signal.clone()).await, + } + }, + //@FIXME handle ctrl + c + async { + self.imap_server.await?; + Ok(()) + } + )?; - let server = - ImapServer::new(self.incoming).serve(service::Instance::new(self.mailstore.clone())); - let _ = server.await?; Ok(()) } } + +fn authenticator(config: Config) -> Result<Arc<dyn LoginProvider + Send + Sync>> { + let s3_region = Region::Custom { + name: config.aws_region.clone(), + endpoint: config.s3_endpoint, + }; + let k2v_region = Region::Custom { + name: config.aws_region, + endpoint: config.k2v_endpoint, + }; + + let lp: Arc<dyn LoginProvider + Send + Sync> = match (config.login_static, config.login_ldap) { + (Some(st), None) => Arc::new(StaticLoginProvider::new(st, k2v_region, s3_region)?), + (None, Some(ld)) => Arc::new(LdapLoginProvider::new(ld, k2v_region, s3_region)?), + (Some(_), Some(_)) => { + bail!("A single login provider must be set up in config file") + } + (None, None) => bail!("No login provider is set up in config file"), + }; + Ok(lp) +} + +pub fn watch_ctrl_c() -> (watch::Receiver<bool>, Arc<watch::Sender<bool>>) { + let (send_cancel, watch_cancel) = watch::channel(false); + let send_cancel = Arc::new(send_cancel); + let send_cancel_2 = send_cancel.clone(); + tokio::spawn(async move { + tokio::signal::ctrl_c() + .await + .expect("failed to install CTRL+C signal handler"); + info!("Received CTRL+C, shutting down."); + send_cancel.send(true).unwrap(); + }); + (watch_cancel, send_cancel_2) +} |