mirror of
https://github.com/pimalaya/himalaya.git
synced 2026-06-16 20:57:53 +08:00
bump deps, make global config option repeatable
This commit is contained in:
+17
-20
@@ -25,17 +25,19 @@ pub struct Cli {
|
||||
#[command(subcommand)]
|
||||
pub command: Option<HimalayaCommand>,
|
||||
|
||||
/// Override the default configuration file path
|
||||
/// Override the default configuration file path.
|
||||
///
|
||||
/// The given path is shell-expanded then canonicalized (if
|
||||
/// applicable). If the path does not point to a valid file, the
|
||||
/// wizard will propose to assist you in the creation of the
|
||||
/// configuration file.
|
||||
/// The given paths are shell-expanded then canonicalized (if
|
||||
/// applicable). If the first path does not point to a valid file,
|
||||
/// the wizard will propose to assist you in the creation of the
|
||||
/// configuration file. Other paths are merged with the first one,
|
||||
/// which allows you to separate your public config from your
|
||||
/// private(s) one(s).
|
||||
#[arg(short, long = "config", global = true)]
|
||||
#[arg(value_name = "PATH", value_parser = config::path_parser)]
|
||||
pub config_path: Option<PathBuf>,
|
||||
pub config_paths: Vec<PathBuf>,
|
||||
|
||||
/// Customize the output format
|
||||
/// Customize the output format.
|
||||
///
|
||||
/// The output format determine how to display commands output to
|
||||
/// the terminal.
|
||||
@@ -116,39 +118,34 @@ pub enum HimalayaCommand {
|
||||
}
|
||||
|
||||
impl HimalayaCommand {
|
||||
#[allow(unused)]
|
||||
pub async fn execute(
|
||||
self,
|
||||
printer: &mut impl Printer,
|
||||
config_path: Option<&PathBuf>,
|
||||
) -> Result<()> {
|
||||
pub async fn execute(self, printer: &mut impl Printer, config_paths: &[PathBuf]) -> Result<()> {
|
||||
match self {
|
||||
Self::Account(cmd) => {
|
||||
let config = TomlConfig::from_some_path_or_default(config_path).await?;
|
||||
let config = TomlConfig::from_paths_or_default(config_paths).await?;
|
||||
cmd.execute(printer, &config).await
|
||||
}
|
||||
Self::Folder(cmd) => {
|
||||
let config = TomlConfig::from_some_path_or_default(config_path).await?;
|
||||
let config = TomlConfig::from_paths_or_default(config_paths).await?;
|
||||
cmd.execute(printer, &config).await
|
||||
}
|
||||
Self::Envelope(cmd) => {
|
||||
let config = TomlConfig::from_some_path_or_default(config_path).await?;
|
||||
let config = TomlConfig::from_paths_or_default(config_paths).await?;
|
||||
cmd.execute(printer, &config).await
|
||||
}
|
||||
Self::Flag(cmd) => {
|
||||
let config = TomlConfig::from_some_path_or_default(config_path).await?;
|
||||
let config = TomlConfig::from_paths_or_default(config_paths).await?;
|
||||
cmd.execute(printer, &config).await
|
||||
}
|
||||
Self::Message(cmd) => {
|
||||
let config = TomlConfig::from_some_path_or_default(config_path).await?;
|
||||
let config = TomlConfig::from_paths_or_default(config_paths).await?;
|
||||
cmd.execute(printer, &config).await
|
||||
}
|
||||
Self::Attachment(cmd) => {
|
||||
let config = TomlConfig::from_some_path_or_default(config_path).await?;
|
||||
let config = TomlConfig::from_paths_or_default(config_paths).await?;
|
||||
cmd.execute(printer, &config).await
|
||||
}
|
||||
Self::Template(cmd) => {
|
||||
let config = TomlConfig::from_some_path_or_default(config_path).await?;
|
||||
let config = TomlConfig::from_paths_or_default(config_paths).await?;
|
||||
cmd.execute(printer, &config).await
|
||||
}
|
||||
Self::Manual(cmd) => cmd.execute(printer).await,
|
||||
|
||||
+56
-26
@@ -1,21 +1,17 @@
|
||||
pub mod wizard;
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use anyhow::{anyhow, bail, Context, Result};
|
||||
use dirs::{config_dir, home_dir};
|
||||
use email::{
|
||||
account::config::AccountConfig, config::Config, envelope::config::EnvelopeConfig,
|
||||
flag::config::FlagConfig, folder::config::FolderConfig, message::config::MessageConfig,
|
||||
};
|
||||
|
||||
use log::debug;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_toml_merge::merge;
|
||||
use shellexpand_utils::{canonicalize, expand};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
use toml;
|
||||
use std::{collections::HashMap, fs, path::PathBuf, sync::Arc};
|
||||
use toml::{self, Value};
|
||||
|
||||
#[cfg(feature = "account-sync")]
|
||||
use crate::backend::BackendKind;
|
||||
@@ -34,14 +30,48 @@ pub struct TomlConfig {
|
||||
}
|
||||
|
||||
impl TomlConfig {
|
||||
/// Read and parse the TOML configuration at the given path.
|
||||
/// Read and parse the TOML configuration at the given paths.
|
||||
///
|
||||
/// 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:?}"))
|
||||
/// Returns an error if a configuration file cannot be read or if
|
||||
/// a content cannot be parsed.
|
||||
fn from_paths(paths: &[PathBuf]) -> Result<Self> {
|
||||
match paths.len() {
|
||||
0 => {
|
||||
// should never happen
|
||||
bail!("cannot read config file from empty paths");
|
||||
}
|
||||
1 => {
|
||||
let path = &paths[0];
|
||||
|
||||
let ref 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:?}"))
|
||||
}
|
||||
_ => {
|
||||
let path = &paths[0];
|
||||
|
||||
let mut merged_content = fs::read_to_string(path)
|
||||
.context(format!("cannot read config file at {path:?}"))?
|
||||
.parse::<Value>()?;
|
||||
|
||||
for path in &paths[1..] {
|
||||
match fs::read_to_string(path) {
|
||||
Ok(content) => {
|
||||
merged_content = merge(merged_content, content.parse()?).unwrap();
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("skipping subconfig file at {path:?}: {err}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
merged_content
|
||||
.try_into()
|
||||
.context(format!("cannot parse merged config file at {path:?}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create and save a TOML configuration using the wizard.
|
||||
@@ -51,7 +81,7 @@ impl TomlConfig {
|
||||
/// program stops.
|
||||
///
|
||||
/// NOTE: the wizard can only be used with interactive shells.
|
||||
async fn from_wizard(path: PathBuf) -> Result<Self> {
|
||||
async fn from_wizard(path: &PathBuf) -> Result<Self> {
|
||||
use dialoguer::Confirm;
|
||||
use std::process;
|
||||
|
||||
@@ -75,8 +105,8 @@ impl TomlConfig {
|
||||
/// 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,
|
||||
Some(path) => Self::from_paths(&[path]),
|
||||
None => Self::from_wizard(&Self::default_path()?).await,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,11 +122,11 @@ impl TomlConfig {
|
||||
/// 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,
|
||||
_ => Self::from_default_paths().await,
|
||||
pub async fn from_paths_or_default(paths: &[PathBuf]) -> Result<Self> {
|
||||
match paths.len() {
|
||||
0 => Self::from_default_paths().await,
|
||||
_ if paths[0].exists() => Self::from_paths(paths),
|
||||
_ => Self::from_wizard(&paths[0]).await,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,14 +187,14 @@ impl TomlConfig {
|
||||
if let Some(imap_config) = toml_account_config.imap.as_mut() {
|
||||
imap_config
|
||||
.auth
|
||||
.replace_undefined_keyring_entries(&account_name);
|
||||
.replace_undefined_keyring_entries(&account_name)?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "smtp")]
|
||||
if let Some(smtp_config) = toml_account_config.smtp.as_mut() {
|
||||
smtp_config
|
||||
.auth
|
||||
.replace_undefined_keyring_entries(&account_name);
|
||||
.replace_undefined_keyring_entries(&account_name)?;
|
||||
}
|
||||
|
||||
Ok((account_name, toml_account_config))
|
||||
|
||||
+11
-7
@@ -2,7 +2,7 @@ use anyhow::Result;
|
||||
use dialoguer::{Confirm, Input, Select};
|
||||
use shellexpand_utils::expand;
|
||||
use std::{fs, path::PathBuf, process};
|
||||
use toml_edit::{Document, Item};
|
||||
use toml_edit::{DocumentMut, Item};
|
||||
|
||||
use crate::{account, ui::THEME};
|
||||
|
||||
@@ -31,7 +31,7 @@ macro_rules! wizard_log {
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) async fn configure(path: PathBuf) -> Result<TomlConfig> {
|
||||
pub(crate) async fn configure(path: &PathBuf) -> Result<TomlConfig> {
|
||||
wizard_log!("Configuring your first account:");
|
||||
|
||||
let mut config = TomlConfig::default();
|
||||
@@ -103,7 +103,7 @@ pub(crate) async fn configure(path: PathBuf) -> Result<TomlConfig> {
|
||||
}
|
||||
|
||||
fn pretty_serialize(config: &TomlConfig) -> Result<String> {
|
||||
let mut doc: Document = toml::to_string(&config)?.parse()?;
|
||||
let mut doc: DocumentMut = toml::to_string(&config)?.parse()?;
|
||||
|
||||
doc.iter_mut().for_each(|(_, item)| {
|
||||
if let Some(item) = item.as_table_mut() {
|
||||
@@ -299,7 +299,9 @@ folder.sync.permissions.delete = true
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: ImapAuthConfig::Passwd(PasswdConfig(Secret::new_cmd("pass show test"))),
|
||||
auth: ImapAuthConfig::Passwd(PasswdConfig(Secret::new_command(
|
||||
"pass show test",
|
||||
))),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
@@ -330,7 +332,7 @@ imap.passwd.cmd = "pass show test"
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: ImapAuthConfig::Passwd(PasswdConfig(Secret::new_cmd(vec![
|
||||
auth: ImapAuthConfig::Passwd(PasswdConfig(Secret::new_command(vec![
|
||||
"pass show test",
|
||||
"tr -d '[:blank:]'",
|
||||
]))),
|
||||
@@ -424,7 +426,9 @@ maildir.root-dir = "/tmp/test"
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: SmtpAuthConfig::Passwd(PasswdConfig(Secret::new_cmd("pass show test"))),
|
||||
auth: SmtpAuthConfig::Passwd(PasswdConfig(Secret::new_command(
|
||||
"pass show test",
|
||||
))),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
@@ -455,7 +459,7 @@ smtp.passwd.cmd = "pass show test"
|
||||
host: "localhost".into(),
|
||||
port: 143,
|
||||
login: "test@localhost".into(),
|
||||
auth: SmtpAuthConfig::Passwd(PasswdConfig(Secret::new_cmd(vec![
|
||||
auth: SmtpAuthConfig::Passwd(PasswdConfig(Secret::new_command(vec![
|
||||
"pass show test",
|
||||
"tr -d '[:blank:]'",
|
||||
]))),
|
||||
|
||||
+18
-30
@@ -163,10 +163,10 @@ pub(crate) async fn configure(
|
||||
.with_prompt("IMAP OAuth 2.0 client secret")
|
||||
.interact()?;
|
||||
config.client_secret =
|
||||
Secret::new_keyring_entry(format!("{account_name}-imap-oauth2-client-secret"));
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-imap-oauth2-client-secret"))?;
|
||||
config
|
||||
.client_secret
|
||||
.set_keyring_entry_secret(&client_secret)
|
||||
.set_only_keyring(&client_secret)
|
||||
.await?;
|
||||
|
||||
let default_auth_url = autoconfig_oauth2
|
||||
@@ -278,19 +278,13 @@ pub(crate) async fn configure(
|
||||
.await?;
|
||||
|
||||
config.access_token =
|
||||
Secret::new_keyring_entry(format!("{account_name}-imap-oauth2-access-token"));
|
||||
config
|
||||
.access_token
|
||||
.set_keyring_entry_secret(access_token)
|
||||
.await?;
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-imap-oauth2-access-token"))?;
|
||||
config.access_token.set_only_keyring(access_token).await?;
|
||||
|
||||
if let Some(refresh_token) = &refresh_token {
|
||||
config.refresh_token =
|
||||
Secret::new_keyring_entry(format!("{account_name}-imap-oauth2-refresh-token"));
|
||||
config
|
||||
.refresh_token
|
||||
.set_keyring_entry_secret(refresh_token)
|
||||
.await?;
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-imap-oauth2-refresh-token"))?;
|
||||
config.refresh_token.set_only_keyring(refresh_token).await?;
|
||||
}
|
||||
|
||||
ImapAuthConfig::OAuth2(config)
|
||||
@@ -303,14 +297,14 @@ pub(crate) async fn configure(
|
||||
|
||||
let secret = match secret_idx {
|
||||
Some(idx) if SECRETS[idx] == KEYRING => {
|
||||
let secret = Secret::new_keyring_entry(format!("{account_name}-imap-passwd"));
|
||||
let secret = Secret::try_new_keyring_entry(format!("{account_name}-imap-passwd"))?;
|
||||
secret
|
||||
.set_keyring_entry_secret(prompt::passwd("IMAP password")?)
|
||||
.set_only_keyring(prompt::passwd("IMAP password")?)
|
||||
.await?;
|
||||
secret
|
||||
}
|
||||
Some(idx) if SECRETS[idx] == RAW => Secret::new_raw(prompt::passwd("IMAP password")?),
|
||||
Some(idx) if SECRETS[idx] == CMD => Secret::new_cmd(
|
||||
Some(idx) if SECRETS[idx] == CMD => Secret::new_command(
|
||||
Input::with_theme(&*THEME)
|
||||
.with_prompt("Shell command")
|
||||
.default(format!("pass show {account_name}-imap-passwd"))
|
||||
@@ -404,10 +398,10 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
.with_prompt("IMAP OAuth 2.0 client secret")
|
||||
.interact()?;
|
||||
config.client_secret =
|
||||
Secret::new_keyring_entry(format!("{account_name}-imap-oauth2-client-secret"));
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-imap-oauth2-client-secret"))?;
|
||||
config
|
||||
.client_secret
|
||||
.set_keyring_entry_secret(&client_secret)
|
||||
.set_only_keyring(&client_secret)
|
||||
.await?;
|
||||
|
||||
config.auth_url = Input::with_theme(&*THEME)
|
||||
@@ -500,19 +494,13 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
.await?;
|
||||
|
||||
config.access_token =
|
||||
Secret::new_keyring_entry(format!("{account_name}-imap-oauth2-access-token"));
|
||||
config
|
||||
.access_token
|
||||
.set_keyring_entry_secret(access_token)
|
||||
.await?;
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-imap-oauth2-access-token"))?;
|
||||
config.access_token.set_only_keyring(access_token).await?;
|
||||
|
||||
if let Some(refresh_token) = &refresh_token {
|
||||
config.refresh_token =
|
||||
Secret::new_keyring_entry(format!("{account_name}-imap-oauth2-refresh-token"));
|
||||
config
|
||||
.refresh_token
|
||||
.set_keyring_entry_secret(refresh_token)
|
||||
.await?;
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-imap-oauth2-refresh-token"))?;
|
||||
config.refresh_token.set_only_keyring(refresh_token).await?;
|
||||
}
|
||||
|
||||
ImapAuthConfig::OAuth2(config)
|
||||
@@ -525,14 +513,14 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
|
||||
let secret = match secret_idx {
|
||||
Some(idx) if SECRETS[idx] == KEYRING => {
|
||||
let secret = Secret::new_keyring_entry(format!("{account_name}-imap-passwd"));
|
||||
let secret = Secret::try_new_keyring_entry(format!("{account_name}-imap-passwd"))?;
|
||||
secret
|
||||
.set_keyring_entry_secret(prompt::passwd("IMAP password")?)
|
||||
.set_only_keyring(prompt::passwd("IMAP password")?)
|
||||
.await?;
|
||||
secret
|
||||
}
|
||||
Some(idx) if SECRETS[idx] == RAW => Secret::new_raw(prompt::passwd("IMAP password")?),
|
||||
Some(idx) if SECRETS[idx] == CMD => Secret::new_cmd(
|
||||
Some(idx) if SECRETS[idx] == CMD => Secret::new_command(
|
||||
Input::with_theme(&*THEME)
|
||||
.with_prompt("Shell command")
|
||||
.default(format!("pass show {account_name}-imap-passwd"))
|
||||
|
||||
+6
-5
@@ -22,10 +22,11 @@ async fn main() -> Result<()> {
|
||||
|
||||
// if the first argument starts by "mailto:", execute straight the
|
||||
// mailto message command
|
||||
if let Some(ref url) = std::env::args()
|
||||
let mailto = std::env::args()
|
||||
.nth(1)
|
||||
.filter(|arg| arg.starts_with("mailto:"))
|
||||
{
|
||||
.filter(|arg| arg.starts_with("mailto:"));
|
||||
|
||||
if let Some(ref url) = mailto {
|
||||
let mut printer = StdoutPrinter::default();
|
||||
let config = TomlConfig::from_default_paths().await?;
|
||||
|
||||
@@ -38,9 +39,9 @@ async fn main() -> Result<()> {
|
||||
let mut printer = StdoutPrinter::new(cli.output, cli.color);
|
||||
|
||||
match cli.command {
|
||||
Some(cmd) => cmd.execute(&mut printer, cli.config_path.as_ref()).await,
|
||||
Some(cmd) => cmd.execute(&mut printer, cli.config_paths.as_ref()).await,
|
||||
None => {
|
||||
let config = TomlConfig::from_some_path_or_default(cli.config_path.as_ref()).await?;
|
||||
let config = TomlConfig::from_paths_or_default(cli.config_paths.as_ref()).await?;
|
||||
ListEnvelopesCommand::default()
|
||||
.execute(&mut printer, &config)
|
||||
.await
|
||||
|
||||
+18
-30
@@ -163,10 +163,10 @@ pub(crate) async fn configure(
|
||||
.with_prompt("SMTP OAuth 2.0 client secret")
|
||||
.interact()?;
|
||||
config.client_secret =
|
||||
Secret::new_keyring_entry(format!("{account_name}-smtp-oauth2-client-secret"));
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-smtp-oauth2-client-secret"))?;
|
||||
config
|
||||
.client_secret
|
||||
.set_keyring_entry_secret(&client_secret)
|
||||
.set_only_keyring(&client_secret)
|
||||
.await?;
|
||||
|
||||
let default_auth_url = autoconfig_oauth2
|
||||
@@ -278,19 +278,13 @@ pub(crate) async fn configure(
|
||||
.await?;
|
||||
|
||||
config.access_token =
|
||||
Secret::new_keyring_entry(format!("{account_name}-smtp-oauth2-access-token"));
|
||||
config
|
||||
.access_token
|
||||
.set_keyring_entry_secret(access_token)
|
||||
.await?;
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-smtp-oauth2-access-token"))?;
|
||||
config.access_token.set_only_keyring(access_token).await?;
|
||||
|
||||
if let Some(refresh_token) = &refresh_token {
|
||||
config.refresh_token =
|
||||
Secret::new_keyring_entry(format!("{account_name}-smtp-oauth2-refresh-token"));
|
||||
config
|
||||
.refresh_token
|
||||
.set_keyring_entry_secret(refresh_token)
|
||||
.await?;
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-smtp-oauth2-refresh-token"))?;
|
||||
config.refresh_token.set_only_keyring(refresh_token).await?;
|
||||
}
|
||||
|
||||
SmtpAuthConfig::OAuth2(config)
|
||||
@@ -303,14 +297,14 @@ pub(crate) async fn configure(
|
||||
|
||||
let secret = match secret_idx {
|
||||
Some(idx) if SECRETS[idx] == KEYRING => {
|
||||
let secret = Secret::new_keyring_entry(format!("{account_name}-smtp-passwd"));
|
||||
let secret = Secret::try_new_keyring_entry(format!("{account_name}-smtp-passwd"))?;
|
||||
secret
|
||||
.set_keyring_entry_secret(prompt::passwd("SMTP password")?)
|
||||
.set_only_keyring(prompt::passwd("SMTP password")?)
|
||||
.await?;
|
||||
secret
|
||||
}
|
||||
Some(idx) if SECRETS[idx] == RAW => Secret::new_raw(prompt::passwd("SMTP password")?),
|
||||
Some(idx) if SECRETS[idx] == CMD => Secret::new_cmd(
|
||||
Some(idx) if SECRETS[idx] == CMD => Secret::new_command(
|
||||
Input::with_theme(&*THEME)
|
||||
.with_prompt("Shell command")
|
||||
.default(format!("pass show {account_name}-smtp-passwd"))
|
||||
@@ -403,10 +397,10 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
.with_prompt("SMTP OAuth 2.0 client secret")
|
||||
.interact()?;
|
||||
config.client_secret =
|
||||
Secret::new_keyring_entry(format!("{account_name}-smtp-oauth2-client-secret"));
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-smtp-oauth2-client-secret"))?;
|
||||
config
|
||||
.client_secret
|
||||
.set_keyring_entry_secret(&client_secret)
|
||||
.set_only_keyring(&client_secret)
|
||||
.await?;
|
||||
|
||||
config.auth_url = Input::with_theme(&*THEME)
|
||||
@@ -499,19 +493,13 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
.await?;
|
||||
|
||||
config.access_token =
|
||||
Secret::new_keyring_entry(format!("{account_name}-smtp-oauth2-access-token"));
|
||||
config
|
||||
.access_token
|
||||
.set_keyring_entry_secret(access_token)
|
||||
.await?;
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-smtp-oauth2-access-token"))?;
|
||||
config.access_token.set_only_keyring(access_token).await?;
|
||||
|
||||
if let Some(refresh_token) = &refresh_token {
|
||||
config.refresh_token =
|
||||
Secret::new_keyring_entry(format!("{account_name}-smtp-oauth2-refresh-token"));
|
||||
config
|
||||
.refresh_token
|
||||
.set_keyring_entry_secret(refresh_token)
|
||||
.await?;
|
||||
Secret::try_new_keyring_entry(format!("{account_name}-smtp-oauth2-refresh-token"))?;
|
||||
config.refresh_token.set_only_keyring(refresh_token).await?;
|
||||
}
|
||||
|
||||
SmtpAuthConfig::OAuth2(config)
|
||||
@@ -524,14 +512,14 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
|
||||
let secret = match secret_idx {
|
||||
Some(idx) if SECRETS[idx] == KEYRING => {
|
||||
let secret = Secret::new_keyring_entry(format!("{account_name}-smtp-passwd"));
|
||||
let secret = Secret::try_new_keyring_entry(format!("{account_name}-smtp-passwd"))?;
|
||||
secret
|
||||
.set_keyring_entry_secret(prompt::passwd("SMTP password")?)
|
||||
.set_only_keyring(prompt::passwd("SMTP password")?)
|
||||
.await?;
|
||||
secret
|
||||
}
|
||||
Some(idx) if SECRETS[idx] == RAW => Secret::new_raw(prompt::passwd("SMTP password")?),
|
||||
Some(idx) if SECRETS[idx] == CMD => Secret::new_cmd(
|
||||
Some(idx) if SECRETS[idx] == CMD => Secret::new_command(
|
||||
Input::with_theme(&*THEME)
|
||||
.with_prompt("Shell command")
|
||||
.default(format!("pass show {account_name}-smtp-passwd"))
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ use email::{
|
||||
};
|
||||
use log::debug;
|
||||
use mml::MmlCompilerBuilder;
|
||||
use process::SingleCmd;
|
||||
use process::SingleCommand;
|
||||
use std::{env, fs, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
@@ -25,7 +25,7 @@ pub async fn open_with_tpl(tpl: String) -> Result<String> {
|
||||
|
||||
debug!("open editor");
|
||||
let editor = env::var("EDITOR").context("cannot get editor from env var")?;
|
||||
SingleCmd::from(format!("{editor} {}", &path.to_string_lossy()))
|
||||
SingleCommand::from(format!("{editor} {}", &path.to_string_lossy()))
|
||||
.with_output_piped(false)
|
||||
.run()
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user