diff --git a/src/backend/config.rs b/src/backend/config.rs new file mode 100644 index 0000000..fb18479 --- /dev/null +++ b/src/backend/config.rs @@ -0,0 +1,19 @@ +#[cfg(feature = "imap-backend")] +use email::imap::ImapConfig; +#[cfg(feature = "notmuch-backend")] +use email::notmuch::NotmuchConfig; +#[cfg(feature = "smtp-sender")] +use email::smtp::SmtpConfig; +use email::{maildir::MaildirConfig, sendmail::SendmailConfig}; + +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum BackendConfig { + Maildir(MaildirConfig), + #[cfg(feature = "imap-backend")] + Imap(ImapConfig), + #[cfg(feature = "notmuch-backend")] + Notmuch(NotmuchConfig), + #[cfg(feature = "smtp-sender")] + Smtp(SmtpConfig), + Sendmail(SendmailConfig), +} diff --git a/src/backend.rs b/src/backend/mod.rs similarity index 97% rename from src/backend.rs rename to src/backend/mod.rs index e99f5bb..c92ddec 100644 --- a/src/backend.rs +++ b/src/backend/mod.rs @@ -1,3 +1,6 @@ +pub mod config; +pub(crate) mod wizard; + use anyhow::Result; use async_trait::async_trait; use std::ops::Deref; @@ -47,11 +50,9 @@ use serde::{Deserialize, Serialize}; use crate::{account::TomlAccountConfig, Envelopes, IdMapper}; -#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum BackendKind { - #[default] - None, Maildir, #[serde(skip_deserializing)] MaildirForSync, @@ -64,6 +65,24 @@ pub enum BackendKind { Sendmail, } +impl ToString for BackendKind { + fn to_string(&self) -> String { + let kind = match self { + Self::Maildir => "Maildir", + Self::MaildirForSync => "Maildir", + #[cfg(feature = "imap-backend")] + Self::Imap => "IMAP", + #[cfg(feature = "notmuch-backend")] + Self::Notmuch => "Notmuch", + #[cfg(feature = "smtp-sender")] + Self::Smtp => "SMTP", + Self::Sendmail => "Sendmail", + }; + + kind.to_string() + } +} + #[derive(Clone, Default)] pub struct BackendContextBuilder { maildir: Option, diff --git a/src/backend/wizard.rs b/src/backend/wizard.rs new file mode 100644 index 0000000..6d9ddca --- /dev/null +++ b/src/backend/wizard.rs @@ -0,0 +1,71 @@ +use anyhow::Result; +use dialoguer::Select; + +#[cfg(feature = "imap-backend")] +use crate::imap; +#[cfg(feature = "notmuch-backend")] +use crate::notmuch; +#[cfg(feature = "smtp-sender")] +use crate::smtp; +use crate::{config::wizard::THEME, maildir, sendmail}; + +use super::{config::BackendConfig, BackendKind}; + +const DEFAULT_BACKEND_KINDS: &[BackendKind] = &[ + BackendKind::Maildir, + #[cfg(feature = "imap-backend")] + BackendKind::Imap, + #[cfg(feature = "notmuch-backend")] + BackendKind::Notmuch, +]; + +const SEND_MESSAGE_BACKEND_KINDS: &[BackendKind] = &[ + BackendKind::Sendmail, + #[cfg(feature = "smtp-sender")] + BackendKind::Smtp, +]; + +pub(crate) async fn configure(account_name: &str, email: &str) -> Result> { + let kind = Select::with_theme(&*THEME) + .with_prompt("Default email backend") + .items(DEFAULT_BACKEND_KINDS) + .default(0) + .interact_opt()? + .and_then(|idx| DEFAULT_BACKEND_KINDS.get(idx).map(Clone::clone)); + + let config = match kind { + Some(kind) if kind == BackendKind::Maildir => Some(maildir::wizard::configure()?), + #[cfg(feature = "imap-backend")] + Some(kind) if kind == BackendKind::Imap => { + Some(imap::wizard::configure(account_name, email).await?) + } + #[cfg(feature = "notmuch-backend")] + Some(kind) if kind == BackendKind::Notmuch => Some(notmuch::wizard::configure()?), + _ => None, + }; + + Ok(config) +} + +pub(crate) async fn configure_sender( + account_name: &str, + email: &str, +) -> Result> { + let kind = Select::with_theme(&*THEME) + .with_prompt("Default email backend") + .items(SEND_MESSAGE_BACKEND_KINDS) + .default(0) + .interact_opt()? + .and_then(|idx| SEND_MESSAGE_BACKEND_KINDS.get(idx).map(Clone::clone)); + + let config = match kind { + Some(kind) if kind == BackendKind::Sendmail => Some(sendmail::wizard::configure()?), + #[cfg(feature = "smtp-sender")] + Some(kind) if kind == BackendKind::Smtp => { + Some(smtp::wizard::configure(account_name, email).await?) + } + _ => None, + }; + + Ok(config) +} diff --git a/src/config/config.rs b/src/config/config.rs index 9c618d7..574dad1 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -11,9 +11,13 @@ use email::{ config::Config, email::{EmailHooks, EmailTextPlainFormat}, }; -use log::{debug, trace}; use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, fs, path::PathBuf, process::exit}; +use std::{ + collections::HashMap, + fs, + path::{Path, PathBuf}, + process, +}; use toml; use crate::{ @@ -52,51 +56,95 @@ pub struct TomlConfig { } impl TomlConfig { - /// Tries to create a config from an optional path. - pub async fn from_maybe_path(path: Option<&str>) -> Result { - debug!("path: {:?}", path); - - let config = if let Some(path) = path.map(PathBuf::from).or_else(Self::path) { - let content = fs::read_to_string(path).context("cannot read config file")?; - toml::from_str(&content).context("cannot parse config file")? - } else { - wizard_warn!("Himalaya could not find an already existing configuration file."); - - if !Confirm::new() - .with_prompt(wizard_prompt!( - "Would you like to create one with the wizard?" - )) - .default(true) - .interact_opt()? - .unwrap_or_default() - { - exit(0); - } - - wizard::configure().await? - }; - - if config.accounts.is_empty() { - return Err(anyhow!("config file must contain at least one account")); - } - - trace!("config: {:#?}", config); - Ok(config) + /// Read and parse the TOML configuration at the given path. + /// + /// Returns an error if the configuration file cannot be read or + /// if its content cannot be parsed. + fn from_path(path: &Path) -> Result { + let content = + fs::read_to_string(path).context(format!("cannot read config file at {path:?}"))?; + toml::from_str(&content).context(format!("cannot parse config file at {path:?}")) } - /// Tries to return a config path from a few default settings. + /// Create and save a TOML configuration using the wizard. + /// + /// If the user accepts the confirmation, the wizard starts and + /// help him to create his configuration file. Otherwise the + /// program stops. + /// + /// NOTE: the wizard can only be used with interactive shells. + async fn from_wizard(path: PathBuf) -> Result { + wizard_warn!("Cannot find existing configuration at {path:?}."); + + let confirm = Confirm::new() + .with_prompt(wizard_prompt!( + "Would you like to create it with the wizard?" + )) + .default(true) + .interact_opt()? + .unwrap_or_default(); + + if !confirm { + process::exit(0); + } + + wizard::configure().await + } + + /// Read and parse the TOML configuration from default paths. + pub async fn from_default_paths() -> Result { + match Self::first_valid_default_path() { + Some(path) => Self::from_path(&path), + None => Self::from_wizard(Self::default_path()?).await, + } + } + + /// Read and parse the TOML configuration at the optional given + /// path. + /// + /// If the given path exists, then read and parse the TOML + /// configuration from it. + /// + /// If the given path does not exist, then create it using the + /// wizard. + /// + /// If no path is given, then either read and parse the TOML + /// configuration at the first valid default path, otherwise + /// create it using the wizard. wizard. + pub async fn from_some_path_or_default(path: Option>) -> Result { + match path.map(Into::into) { + Some(ref path) if path.exists() => Self::from_path(path), + Some(path) => Self::from_wizard(path).await, + None => match Self::first_valid_default_path() { + Some(path) => Self::from_path(&path), + None => Self::from_wizard(Self::default_path()?).await, + }, + } + } + + /// Get the default configuration path. + /// + /// Returns an error if the XDG configuration directory cannot be + /// found. + pub fn default_path() -> Result { + Ok(config_dir() + .ok_or(anyhow!("cannot get XDG config directory"))? + .join("himalaya") + .join("config.toml")) + } + + /// Get the first default configuration path that points to a + /// valid file. /// /// Tries paths in this order: /// - /// - `"$XDG_CONFIG_DIR/himalaya/config.toml"` (or equivalent to `$XDG_CONFIG_DIR` in other - /// OSes.) - /// - `"$HOME/.config/himalaya/config.toml"` - /// - `"$HOME/.himalayarc"` - /// - /// Returns `Some(path)` if the path exists, otherwise `None`. - pub fn path() -> Option { - config_dir() - .map(|p| p.join("himalaya").join("config.toml")) + /// - `$XDG_CONFIG_DIR/himalaya/config.toml` (or equivalent to + /// `$XDG_CONFIG_DIR` in other OSes.) + /// - `$HOME/.config/himalaya/config.toml` + /// - `$HOME/.himalayarc` + pub fn first_valid_default_path() -> Option { + Self::default_path() + .ok() .filter(|p| p.exists()) .or_else(|| home_dir().map(|p| p.join(".config").join("himalaya").join("config.toml"))) .filter(|p| p.exists()) @@ -104,6 +152,7 @@ impl TomlConfig { .filter(|p| p.exists()) } + /// Build account configurations from a given account name. pub fn into_account_configs( self, account_name: Option<&str>, @@ -232,7 +281,7 @@ mod tests { async fn make_config(config: &str) -> Result { let mut file = NamedTempFile::new().unwrap(); write!(file, "{}", config).unwrap(); - TomlConfig::from_maybe_path(file.into_temp_path().to_str()).await + TomlConfig::from_some_path_or_default(file.into_temp_path().to_str()).await } #[tokio::test] diff --git a/src/config/wizard.rs b/src/config/wizard.rs index f6add5e..f6b359e 100644 --- a/src/config/wizard.rs +++ b/src/config/wizard.rs @@ -57,7 +57,10 @@ pub(crate) async fn configure() -> Result { // accounts are setup, decide which will be the default. If no // accounts are setup, exit the process. let default_account = match config.accounts.len() { - 0 => process::exit(0), + 0 => { + wizard_warn!("No account configured, exiting."); + process::exit(0); + } 1 => Some(config.accounts.values_mut().next().unwrap()), _ => { let accounts = config.accounts.clone(); diff --git a/src/domain/account/wizard.rs b/src/domain/account/wizard.rs index 84ff44e..5096585 100644 --- a/src/domain/account/wizard.rs +++ b/src/domain/account/wizard.rs @@ -1,8 +1,12 @@ -use anyhow::{anyhow, Result}; +use anyhow::{bail, Result}; use dialoguer::Input; use email_address::EmailAddress; -use crate::config::wizard::THEME; +use crate::{ + backend::{self, config::BackendConfig, BackendKind}, + config::wizard::THEME, + message::config::{MessageConfig, MessageSendConfig}, +}; use super::TomlAccountConfig; @@ -20,7 +24,7 @@ pub(crate) async fn configure() -> Result> { if EmailAddress::is_valid(email) { Ok(()) } else { - Err(anyhow!("Invalid email address: {email}")) + bail!("Invalid email address: {email}") } }) .interact()?; @@ -31,9 +35,48 @@ pub(crate) async fn configure() -> Result> { .interact()?, ); - // config.backend = backend::wizard::configure(&account_name, &config.email).await?; + match backend::wizard::configure(&account_name, &config.email).await? { + Some(BackendConfig::Maildir(mdir_config)) => { + config.maildir = Some(mdir_config); + config.backend = Some(BackendKind::Maildir); + } + #[cfg(feature = "imap-backend")] + Some(BackendConfig::Imap(imap_config)) => { + config.imap = Some(imap_config); + config.backend = Some(BackendKind::Imap); + } + #[cfg(feature = "notmuch-backend")] + Some(BackendConfig::Notmuch(notmuch_config)) => { + config.notmuch = Some(notmuch_config); + config.backend = Some(BackendKind::Notmuch); + } + _ => (), + }; - // config.sender = sender::wizard::configure(&account_name, &config.email).await?; + match backend::wizard::configure_sender(&account_name, &config.email).await? { + Some(BackendConfig::Sendmail(sendmail_config)) => { + config.sendmail = Some(sendmail_config); + config.message = Some(MessageConfig { + send: Some(MessageSendConfig { + backend: Some(BackendKind::Sendmail), + ..Default::default() + }), + ..Default::default() + }); + } + #[cfg(feature = "smtp-sender")] + Some(BackendConfig::Smtp(smtp_config)) => { + config.smtp = Some(smtp_config); + config.message = Some(MessageConfig { + send: Some(MessageSendConfig { + backend: Some(BackendKind::Smtp), + ..Default::default() + }), + ..Default::default() + }); + } + _ => (), + }; Ok(Some((account_name, config))) } diff --git a/src/domain/backend/imap/mod.rs b/src/domain/backend/imap/mod.rs deleted file mode 100644 index b6c153f..0000000 --- a/src/domain/backend/imap/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod args; -// pub mod handlers; -// pub(crate) mod wizard; diff --git a/src/domain/backend/maildir/mod.rs b/src/domain/backend/maildir/mod.rs deleted file mode 100644 index d4b1a6e..0000000 --- a/src/domain/backend/maildir/mod.rs +++ /dev/null @@ -1 +0,0 @@ -// pub(crate) mod wizard; diff --git a/src/domain/backend/mod.rs b/src/domain/backend/mod.rs deleted file mode 100644 index b33f50e..0000000 --- a/src/domain/backend/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[cfg(feature = "imap-backend")] -pub mod imap; -pub mod maildir; -#[cfg(feature = "notmuch-backend")] -pub mod notmuch; -// pub(crate) mod wizard; diff --git a/src/domain/backend/wizard.rs b/src/domain/backend/wizard.rs deleted file mode 100644 index 47e84fe..0000000 --- a/src/domain/backend/wizard.rs +++ /dev/null @@ -1,44 +0,0 @@ -use anyhow::Result; -use dialoguer::Select; -use email::backend::BackendConfig; - -use crate::config::wizard::THEME; - -#[cfg(feature = "imap-backend")] -use super::imap; -use super::maildir; -#[cfg(feature = "notmuch-backend")] -use super::notmuch; - -#[cfg(feature = "imap-backend")] -const IMAP: &str = "IMAP"; -const MAILDIR: &str = "Maildir"; -#[cfg(feature = "notmuch-backend")] -const NOTMUCH: &str = "Notmuch"; -const NONE: &str = "None"; - -const BACKENDS: &[&str] = &[ - #[cfg(feature = "imap-backend")] - IMAP, - MAILDIR, - #[cfg(feature = "notmuch-backend")] - NOTMUCH, - NONE, -]; - -pub(crate) async fn configure(account_name: &str, email: &str) -> Result { - let backend = Select::with_theme(&*THEME) - .with_prompt("Email backend") - .items(BACKENDS) - .default(0) - .interact_opt()?; - - match backend { - #[cfg(feature = "imap-backend")] - Some(idx) if BACKENDS[idx] == IMAP => imap::wizard::configure(account_name, email).await, - Some(idx) if BACKENDS[idx] == MAILDIR => maildir::wizard::configure(), - #[cfg(feature = "notmuch-backend")] - Some(idx) if BACKENDS[idx] == NOTMUCH => notmuch::wizard::configure(), - _ => Ok(BackendConfig::None), - } -} diff --git a/src/domain/mod.rs b/src/domain/mod.rs index d9b40c6..50ca65a 100644 --- a/src/domain/mod.rs +++ b/src/domain/mod.rs @@ -1,14 +1,11 @@ pub mod account; -pub mod backend; pub mod email; pub mod envelope; pub mod flag; pub mod folder; -pub mod sender; pub mod tpl; pub use self::account::{args, handlers, Account, Accounts}; -pub use self::backend::*; pub use self::email::*; pub use self::envelope::*; pub use self::flag::*; diff --git a/src/domain/sender/mod.rs b/src/domain/sender/mod.rs deleted file mode 100644 index eab09f5..0000000 --- a/src/domain/sender/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod sendmail; -#[cfg(feature = "smtp-sender")] -pub mod smtp; -// pub(crate) mod wizard; diff --git a/src/domain/sender/sendmail/mod.rs b/src/domain/sender/sendmail/mod.rs deleted file mode 100644 index d4b1a6e..0000000 --- a/src/domain/sender/sendmail/mod.rs +++ /dev/null @@ -1 +0,0 @@ -// pub(crate) mod wizard; diff --git a/src/domain/sender/smtp/mod.rs b/src/domain/sender/smtp/mod.rs deleted file mode 100644 index d4b1a6e..0000000 --- a/src/domain/sender/smtp/mod.rs +++ /dev/null @@ -1 +0,0 @@ -// pub(crate) mod wizard; diff --git a/src/domain/sender/wizard.rs b/src/domain/sender/wizard.rs deleted file mode 100644 index bb4b9d6..0000000 --- a/src/domain/sender/wizard.rs +++ /dev/null @@ -1,35 +0,0 @@ -use anyhow::Result; -use dialoguer::Select; - -use crate::config::wizard::THEME; - -use super::sendmail; -#[cfg(feature = "smtp-sender")] -use super::smtp; - -#[cfg(feature = "smtp-sender")] -const SMTP: &str = "SMTP"; -const SENDMAIL: &str = "Sendmail"; -const NONE: &str = "None"; - -const SENDERS: &[&str] = &[ - #[cfg(feature = "smtp-sender")] - SMTP, - SENDMAIL, - NONE, -]; - -pub(crate) async fn configure(account_name: &str, email: &str) -> Result { - let sender = Select::with_theme(&*THEME) - .with_prompt("Email sender") - .items(SENDERS) - .default(0) - .interact_opt()?; - - match sender { - #[cfg(feature = "smtp-sender")] - Some(n) if SENDERS[n] == SMTP => smtp::wizard::configure(account_name, email).await, - Some(n) if SENDERS[n] == SENDMAIL => sendmail::wizard::configure(), - _ => Ok(SenderConfig::None), - } -} diff --git a/src/domain/backend/imap/args.rs b/src/imap/args.rs similarity index 100% rename from src/domain/backend/imap/args.rs rename to src/imap/args.rs diff --git a/src/domain/backend/imap/handlers.rs b/src/imap/handlers.rs similarity index 100% rename from src/domain/backend/imap/handlers.rs rename to src/imap/handlers.rs diff --git a/src/imap/mod.rs b/src/imap/mod.rs new file mode 100644 index 0000000..7a553c7 --- /dev/null +++ b/src/imap/mod.rs @@ -0,0 +1,3 @@ +// pub mod args; +// pub mod handlers; +pub(crate) mod wizard; diff --git a/src/domain/backend/imap/wizard.rs b/src/imap/wizard.rs similarity index 99% rename from src/domain/backend/imap/wizard.rs rename to src/imap/wizard.rs index 1322517..7ea750e 100644 --- a/src/domain/backend/imap/wizard.rs +++ b/src/imap/wizard.rs @@ -2,12 +2,13 @@ use anyhow::Result; use dialoguer::{Confirm, Input, Password, Select}; use email::{ account::{OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig}, - backend::{BackendConfig, ImapAuthConfig, ImapConfig}, + imap::{ImapAuthConfig, ImapConfig}, }; use oauth::v2_0::{AuthorizationCodeGrant, Client}; use secret::Secret; use crate::{ + backend::config::BackendConfig, config::wizard::{prompt_passwd, THEME}, wizard_log, wizard_prompt, }; diff --git a/src/lib.rs b/src/lib.rs index d1b00f6..f37795c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,9 +3,17 @@ pub mod cache; pub mod compl; pub mod config; pub mod domain; +#[cfg(feature = "imap-backend")] +pub mod imap; +pub mod maildir; pub mod man; +#[cfg(feature = "notmuch-backend")] +pub mod notmuch; pub mod output; pub mod printer; +pub mod sendmail; +#[cfg(feature = "smtp-sender")] +pub mod smtp; pub mod ui; pub use cache::IdMapper; diff --git a/src/domain/backend/notmuch/mod.rs b/src/maildir/mod.rs similarity index 100% rename from src/domain/backend/notmuch/mod.rs rename to src/maildir/mod.rs diff --git a/src/domain/backend/maildir/wizard.rs b/src/maildir/wizard.rs similarity index 82% rename from src/domain/backend/maildir/wizard.rs rename to src/maildir/wizard.rs index 9dd96bb..04a1e03 100644 --- a/src/domain/backend/maildir/wizard.rs +++ b/src/maildir/wizard.rs @@ -1,9 +1,9 @@ use anyhow::Result; use dialoguer::Input; use dirs::home_dir; -use email::backend::{BackendConfig, MaildirConfig}; +use email::maildir::MaildirConfig; -use crate::config::wizard::THEME; +use crate::{backend::config::BackendConfig, config::wizard::THEME}; pub(crate) fn configure() -> Result { let mut config = MaildirConfig::default(); diff --git a/src/main.rs b/src/main.rs index 18213e2..59df0cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,8 +5,6 @@ use log::{debug, warn}; use std::env; use url::Url; -#[cfg(feature = "imap-backend")] -use himalaya::imap; use himalaya::{ account, backend::{Backend, BackendBuilder}, @@ -18,7 +16,7 @@ use himalaya::{ }; fn create_app() -> Command { - let app = Command::new(env!("CARGO_PKG_NAME")) + Command::new(env!("CARGO_PKG_NAME")) .version(env!("CARGO_PKG_VERSION")) .about(env!("CARGO_PKG_DESCRIPTION")) .author(env!("CARGO_PKG_AUTHORS")) @@ -33,12 +31,7 @@ fn create_app() -> Command { .subcommand(man::args::subcmd()) .subcommand(account::args::subcmd()) .subcommand(folder::args::subcmd()) - .subcommands(email::args::subcmds()); - - #[cfg(feature = "imap-backend")] - let app = app.subcommands(imap::args::subcmds()); - - app + .subcommands(email::args::subcmds()) } #[allow(clippy::single_match)] @@ -57,7 +50,7 @@ async fn main() -> Result<()> { let raw_args: Vec = env::args().collect(); if raw_args.len() > 1 && raw_args[1].starts_with("mailto:") { let url = Url::parse(&raw_args[1])?; - let (toml_account_config, account_config) = TomlConfig::from_maybe_path(None) + let (toml_account_config, account_config) = TomlConfig::from_default_paths() .await? .into_account_configs(None, false)?; let backend_builder = @@ -88,12 +81,12 @@ async fn main() -> Result<()> { _ => (), } - let maybe_config_path = config::args::parse_arg(&m); - let maybe_account_name = account::args::parse_arg(&m); + let some_config_path = config::args::parse_arg(&m); + let some_account_name = account::args::parse_arg(&m); let disable_cache = cache::args::parse_disable_cache_flag(&m); let folder = folder::args::parse_source_arg(&m); - let toml_config = TomlConfig::from_maybe_path(maybe_config_path).await?; + let toml_config = TomlConfig::from_some_path_or_default(some_config_path).await?; let mut printer = StdoutPrinter::try_from(&m)?; @@ -122,13 +115,13 @@ async fn main() -> Result<()> { Some(account::args::Cmd::List(max_width)) => { let (_, account_config) = toml_config .clone() - .into_account_configs(maybe_account_name, disable_cache)?; + .into_account_configs(some_account_name, disable_cache)?; return account::handlers::list(max_width, &account_config, &toml_config, &mut printer); } Some(account::args::Cmd::Sync(strategy, dry_run)) => { let (toml_account_config, account_config) = toml_config .clone() - .into_account_configs(maybe_account_name, true)?; + .into_account_configs(some_account_name, true)?; let backend_builder = BackendBuilder::new(toml_account_config, account_config.clone(), false).await?; let sync_builder = AccountSyncBuilder::new(backend_builder.into()) @@ -140,7 +133,7 @@ async fn main() -> Result<()> { Some(account::args::Cmd::Configure(reset)) => { let (_, account_config) = toml_config .clone() - .into_account_configs(maybe_account_name, disable_cache)?; + .into_account_configs(some_account_name, disable_cache)?; return account::handlers::configure(&account_config, reset).await; } _ => (), @@ -148,7 +141,7 @@ async fn main() -> Result<()> { let (toml_account_config, account_config) = toml_config .clone() - .into_account_configs(maybe_account_name, disable_cache)?; + .into_account_configs(some_account_name, disable_cache)?; // checks folder commands match folder::args::matches(&m)? { diff --git a/src/notmuch/mod.rs b/src/notmuch/mod.rs new file mode 100644 index 0000000..73818b4 --- /dev/null +++ b/src/notmuch/mod.rs @@ -0,0 +1 @@ +pub(crate) mod wizard; diff --git a/src/domain/backend/notmuch/wizard.rs b/src/notmuch/wizard.rs similarity index 100% rename from src/domain/backend/notmuch/wizard.rs rename to src/notmuch/wizard.rs diff --git a/src/sendmail/mod.rs b/src/sendmail/mod.rs new file mode 100644 index 0000000..73818b4 --- /dev/null +++ b/src/sendmail/mod.rs @@ -0,0 +1 @@ +pub(crate) mod wizard; diff --git a/src/domain/sender/sendmail/wizard.rs b/src/sendmail/wizard.rs similarity index 60% rename from src/domain/sender/sendmail/wizard.rs rename to src/sendmail/wizard.rs index 0297ea5..e2a2896 100644 --- a/src/domain/sender/sendmail/wizard.rs +++ b/src/sendmail/wizard.rs @@ -1,10 +1,10 @@ use anyhow::Result; use dialoguer::Input; -use email::sender::{SenderConfig, SendmailConfig}; +use email::sendmail::SendmailConfig; -use crate::config::wizard::THEME; +use crate::{backend::config::BackendConfig, config::wizard::THEME}; -pub(crate) fn configure() -> Result { +pub(crate) fn configure() -> Result { let mut config = SendmailConfig::default(); config.cmd = Input::with_theme(&*THEME) @@ -13,5 +13,5 @@ pub(crate) fn configure() -> Result { .interact()? .into(); - Ok(SenderConfig::Sendmail(config)) + Ok(BackendConfig::Sendmail(config)) } diff --git a/src/smtp/mod.rs b/src/smtp/mod.rs new file mode 100644 index 0000000..73818b4 --- /dev/null +++ b/src/smtp/mod.rs @@ -0,0 +1 @@ +pub(crate) mod wizard; diff --git a/src/domain/sender/smtp/wizard.rs b/src/smtp/wizard.rs similarity index 98% rename from src/domain/sender/smtp/wizard.rs rename to src/smtp/wizard.rs index 423f155..6dab9cf 100644 --- a/src/domain/sender/smtp/wizard.rs +++ b/src/smtp/wizard.rs @@ -2,12 +2,13 @@ use anyhow::Result; use dialoguer::{Confirm, Input, Select}; use email::{ account::{OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig}, - sender::{SenderConfig, SmtpAuthConfig, SmtpConfig}, + smtp::{SmtpAuthConfig, SmtpConfig}, }; use oauth::v2_0::{AuthorizationCodeGrant, Client}; use secret::Secret; use crate::{ + backend::config::BackendConfig, config::wizard::{prompt_passwd, THEME}, wizard_log, wizard_prompt, }; @@ -30,7 +31,7 @@ const KEYRING: &str = "Ask the password, then save it in my system's global keyr const RAW: &str = "Ask the password, then save it in the configuration file (not safe)"; const CMD: &str = "Use a shell command that exposes the password"; -pub(crate) async fn configure(account_name: &str, email: &str) -> Result { +pub(crate) async fn configure(account_name: &str, email: &str) -> Result { let mut config = SmtpConfig::default(); config.host = Input::with_theme(&*THEME) @@ -218,5 +219,5 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result SmtpAuthConfig::default(), }; - Ok(SenderConfig::Smtp(config)) + Ok(BackendConfig::Smtp(config)) }