mirror of
https://github.com/soywod/himalaya.git
synced 2024-11-25 12:30:22 +00:00
fix wizard
This commit is contained in:
parent
f24a0475cc
commit
c54ada730b
29 changed files with 292 additions and 177 deletions
19
src/backend/config.rs
Normal file
19
src/backend/config.rs
Normal file
|
@ -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),
|
||||
}
|
|
@ -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<MaildirSessionBuilder>,
|
71
src/backend/wizard.rs
Normal file
71
src/backend/wizard.rs
Normal file
|
@ -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<Option<BackendConfig>> {
|
||||
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<Option<BackendConfig>> {
|
||||
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)
|
||||
}
|
|
@ -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<Self> {
|
||||
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<Self> {
|
||||
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<Self> {
|
||||
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<Self> {
|
||||
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<impl Into<PathBuf>>) -> Result<Self> {
|
||||
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<PathBuf> {
|
||||
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<PathBuf> {
|
||||
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<PathBuf> {
|
||||
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<TomlConfig> {
|
||||
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]
|
||||
|
|
|
@ -57,7 +57,10 @@ pub(crate) async fn configure() -> Result<TomlConfig> {
|
|||
// 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();
|
||||
|
|
|
@ -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<Option<(String, TomlAccountConfig)>> {
|
|||
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<Option<(String, TomlAccountConfig)>> {
|
|||
.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)))
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
pub mod args;
|
||||
// pub mod handlers;
|
||||
// pub(crate) mod wizard;
|
|
@ -1 +0,0 @@
|
|||
// pub(crate) mod wizard;
|
|
@ -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;
|
|
@ -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<BackendConfig> {
|
||||
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),
|
||||
}
|
||||
}
|
|
@ -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::*;
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
pub mod sendmail;
|
||||
#[cfg(feature = "smtp-sender")]
|
||||
pub mod smtp;
|
||||
// pub(crate) mod wizard;
|
|
@ -1 +0,0 @@
|
|||
// pub(crate) mod wizard;
|
|
@ -1 +0,0 @@
|
|||
// pub(crate) mod wizard;
|
|
@ -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<SenderConfig> {
|
||||
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),
|
||||
}
|
||||
}
|
3
src/imap/mod.rs
Normal file
3
src/imap/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
// pub mod args;
|
||||
// pub mod handlers;
|
||||
pub(crate) mod wizard;
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
|
|
|
@ -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<BackendConfig> {
|
||||
let mut config = MaildirConfig::default();
|
27
src/main.rs
27
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<String> = 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)? {
|
||||
|
|
1
src/notmuch/mod.rs
Normal file
1
src/notmuch/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub(crate) mod wizard;
|
1
src/sendmail/mod.rs
Normal file
1
src/sendmail/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub(crate) mod wizard;
|
|
@ -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<SenderConfig> {
|
||||
pub(crate) fn configure() -> Result<BackendConfig> {
|
||||
let mut config = SendmailConfig::default();
|
||||
|
||||
config.cmd = Input::with_theme(&*THEME)
|
||||
|
@ -13,5 +13,5 @@ pub(crate) fn configure() -> Result<SenderConfig> {
|
|||
.interact()?
|
||||
.into();
|
||||
|
||||
Ok(SenderConfig::Sendmail(config))
|
||||
Ok(BackendConfig::Sendmail(config))
|
||||
}
|
1
src/smtp/mod.rs
Normal file
1
src/smtp/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub(crate) mod wizard;
|
|
@ -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<SenderConfig> {
|
||||
pub(crate) async fn configure(account_name: &str, email: &str) -> Result<BackendConfig> {
|
||||
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<SenderC
|
|||
_ => SmtpAuthConfig::default(),
|
||||
};
|
||||
|
||||
Ok(SenderConfig::Smtp(config))
|
||||
Ok(BackendConfig::Smtp(config))
|
||||
}
|
Loading…
Reference in a new issue