#![feature(async_fn_in_trait)]
mod timestamp;
mod bayou;
mod config;
mod cryptoblob;
mod imap;
mod k2v_util;
mod lmtp;
mod login;
mod mail;
mod server;
mod storage;
use std::path::PathBuf;
use anyhow::Result;
use clap::{Parser, Subcommand};
use config::*;
use server::Server;
#[derive(Parser, Debug)]
#[clap(author, version, about, long_about = None)]
struct Args {
#[clap(subcommand)]
command: Command,
}
#[derive(Subcommand, Debug)]
enum Command {
/// Runs the IMAP+LMTP server daemon
Server {
#[clap(short, long, env = "CONFIG_FILE", default_value = "aerogramme.toml")]
config_file: PathBuf,
},
Test,
}
#[derive(Parser, Debug)]
struct UserSecretsArgs {
/// User secret
#[clap(short = 'U', long, env = "USER_SECRET")]
user_secret: String,
/// Alternate user secrets (comma-separated list of strings)
#[clap(long, env = "ALTERNATE_USER_SECRETS", default_value = "")]
alternate_user_secrets: String,
}
#[tokio::main]
async fn main() -> Result<()> {
if std::env::var("RUST_LOG").is_err() {
std::env::set_var("RUST_LOG", "main=info,aerogramme=info,k2v_client=info")
}
// Abort on panic (same behavior as in Go)
std::panic::set_hook(Box::new(|panic_info| {
eprintln!("{}", panic_info);
eprintln!("{:?}", backtrace::Backtrace::new());
std::process::abort();
}));
tracing_subscriber::fmt::init();
let args = Args::parse();
match args.command {
Command::Server { config_file } => {
let config = read_config(config_file)?;
let server = Server::new(config).await?;
server.run().await?;
}
Command::Test => {
use std::collections::HashMap;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
println!("--- message pack ---\n{:?}\n--- end ---\n", rmp_serde::to_vec(&Config {
lmtp: None,
imap: Some(ImapConfig { bind_addr: SocketAddr::new(IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)), 8080) }),
login_ldap: None,
login_static: Some(HashMap::from([
("alice".into(), LoginStaticUser {
password: "hash".into(),
user_secret: "hello".into(),
alternate_user_secrets: vec![],
email_addresses: vec![],
master_key: None,
secret_key: None,
storage: StaticStorage::Garage(StaticGarageConfig {
s3_endpoint: "http://".into(),
k2v_endpoint: "http://".into(),
aws_region: "garage".into(),
aws_access_key_id: "GK...".into(),
aws_secret_access_key: "xxx".into(),
bucket: "aerogramme".into(),
}),
})
])),
}).unwrap());
}
}
Ok(())
}