make secrets have default implem

Secrets use by default the keyring, and the entry is based on the name
of the current account to avoid conflicts.
This commit is contained in:
Clément DOUIN 2023-05-07 20:52:13 +02:00
parent 728f2555d7
commit 441ce40e09
No known key found for this signature in database
GPG key ID: 353E4A18EE0FAB72
7 changed files with 202 additions and 188 deletions

10
Cargo.lock generated
View file

@ -2101,7 +2101,7 @@ dependencies = [
[[package]] [[package]]
name = "pimalaya-email" name = "pimalaya-email"
version = "0.7.1" version = "0.7.1"
source = "git+https://git.sr.ht/~soywod/pimalaya#5474a733194623c74665c8d37066974cf3fe4477" source = "git+https://git.sr.ht/~soywod/pimalaya#524f8049566845369f55300a20843c48dfe7a620"
dependencies = [ dependencies = [
"ammonia", "ammonia",
"chrono", "chrono",
@ -2142,7 +2142,7 @@ dependencies = [
[[package]] [[package]]
name = "pimalaya-keyring" name = "pimalaya-keyring"
version = "0.0.1" version = "0.0.1"
source = "git+https://git.sr.ht/~soywod/pimalaya#5474a733194623c74665c8d37066974cf3fe4477" source = "git+https://git.sr.ht/~soywod/pimalaya#524f8049566845369f55300a20843c48dfe7a620"
dependencies = [ dependencies = [
"keyring", "keyring",
"log", "log",
@ -2152,7 +2152,7 @@ dependencies = [
[[package]] [[package]]
name = "pimalaya-oauth2" name = "pimalaya-oauth2"
version = "0.0.1" version = "0.0.1"
source = "git+https://git.sr.ht/~soywod/pimalaya#5474a733194623c74665c8d37066974cf3fe4477" source = "git+https://git.sr.ht/~soywod/pimalaya#524f8049566845369f55300a20843c48dfe7a620"
dependencies = [ dependencies = [
"log", "log",
"oauth2", "oauth2",
@ -2164,7 +2164,7 @@ dependencies = [
[[package]] [[package]]
name = "pimalaya-process" name = "pimalaya-process"
version = "0.0.1" version = "0.0.1"
source = "git+https://git.sr.ht/~soywod/pimalaya#5474a733194623c74665c8d37066974cf3fe4477" source = "git+https://git.sr.ht/~soywod/pimalaya#524f8049566845369f55300a20843c48dfe7a620"
dependencies = [ dependencies = [
"log", "log",
"thiserror", "thiserror",
@ -2173,7 +2173,7 @@ dependencies = [
[[package]] [[package]]
name = "pimalaya-secret" name = "pimalaya-secret"
version = "0.0.1" version = "0.0.1"
source = "git+https://git.sr.ht/~soywod/pimalaya#5474a733194623c74665c8d37066974cf3fe4477" source = "git+https://git.sr.ht/~soywod/pimalaya#524f8049566845369f55300a20843c48dfe7a620"
dependencies = [ dependencies = [
"log", "log",
"pimalaya-keyring", "pimalaya-keyring",

View file

@ -55,6 +55,10 @@ pimalaya-email = { git = "https://git.sr.ht/~soywod/pimalaya" }
pimalaya-keyring = { git = "https://git.sr.ht/~soywod/pimalaya" } pimalaya-keyring = { git = "https://git.sr.ht/~soywod/pimalaya" }
pimalaya-process = { git = "https://git.sr.ht/~soywod/pimalaya" } pimalaya-process = { git = "https://git.sr.ht/~soywod/pimalaya" }
pimalaya-secret = { git = "https://git.sr.ht/~soywod/pimalaya" } pimalaya-secret = { git = "https://git.sr.ht/~soywod/pimalaya" }
# pimalaya-email = { path = "/home/soywod/sourcehut/pimalaya/email" }
# pimalaya-keyring = { path = "/home/soywod/sourcehut/pimalaya/keyring" }
# pimalaya-process = { path = "/home/soywod/sourcehut/pimalaya/process" }
# pimalaya-secret = { path = "/home/soywod/sourcehut/pimalaya/secret" }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
shellexpand = "2.1" shellexpand = "2.1"

View file

@ -1,7 +1,7 @@
use pimalaya_email::{ use pimalaya_email::{
folder::sync::Strategy as SyncFoldersStrategy, EmailHooks, EmailSender, EmailTextPlainFormat, folder::sync::Strategy as SyncFoldersStrategy, EmailHooks, EmailSender, EmailTextPlainFormat,
ImapAuthConfig, MaildirConfig, OAuth2Config, OAuth2Method, OAuth2Scopes, SendmailConfig, ImapAuthConfig, MaildirConfig, OAuth2Config, OAuth2Method, OAuth2Scopes, PasswdConfig,
SmtpAuthConfig, SmtpConfig, SendmailConfig, SmtpAuthConfig, SmtpConfig,
}; };
use pimalaya_keyring::Entry; use pimalaya_keyring::Entry;
use pimalaya_process::Cmd; use pimalaya_process::Cmd;
@ -15,14 +15,50 @@ use pimalaya_email::ImapConfig;
#[cfg(feature = "notmuch-backend")] #[cfg(feature = "notmuch-backend")]
use pimalaya_email::NotmuchConfig; use pimalaya_email::NotmuchConfig;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Cmd", from = "String")]
pub struct CmdDef;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Entry", from = "String")] #[serde(remote = "Entry", from = "String")]
pub struct EntryDef; pub struct EntryDef;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Cmd", from = "String")]
pub struct SingleCmdDef;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Cmd", from = "Vec<String>")]
pub struct PipelineDef;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Cmd", from = "SingleCmdOrPipeline")]
pub struct SingleCmdOrPipelineDef;
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(untagged)]
pub enum SingleCmdOrPipeline {
#[serde(with = "SingleCmdDef")]
SingleCmd(Cmd),
#[serde(with = "PipelineDef")]
Pipeline(Cmd),
}
impl From<SingleCmdOrPipeline> for Cmd {
fn from(cmd: SingleCmdOrPipeline) -> Cmd {
match cmd {
SingleCmdOrPipeline::SingleCmd(cmd) => cmd,
SingleCmdOrPipeline::Pipeline(cmd) => cmd,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret", rename_all = "kebab-case")]
pub enum SecretDef {
Raw(String),
#[serde(with = "SingleCmdOrPipelineDef")]
Cmd(Cmd),
#[serde(with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Method")] #[serde(remote = "OAuth2Method")]
pub enum OAuth2MethodDef { pub enum OAuth2MethodDef {
@ -32,110 +68,6 @@ pub enum OAuth2MethodDef {
OAuthBearer, OAuthBearer,
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "SmtpConfig")]
struct SmtpConfigDef {
#[serde(rename = "smtp-host")]
pub host: String,
#[serde(rename = "smtp-port")]
pub port: u16,
#[serde(rename = "smtp-ssl")]
pub ssl: Option<bool>,
#[serde(rename = "smtp-starttls")]
pub starttls: Option<bool>,
#[serde(rename = "smtp-insecure")]
pub insecure: Option<bool>,
#[serde(rename = "smtp-login")]
pub login: String,
#[serde(flatten, with = "SmtpAuthConfigDef")]
pub auth: SmtpAuthConfig,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "SmtpAuthConfig", tag = "smtp-auth")]
pub enum SmtpAuthConfigDef {
#[serde(rename = "passwd", alias = "password", with = "SmtpPasswdDef")]
Passwd(Secret),
#[serde(rename = "oauth2", with = "SmtpOAuth2ConfigDef")]
OAuth2(OAuth2Config),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret", rename_all = "kebab-case")]
pub enum SmtpPasswdDef {
#[serde(rename = "smtp-passwd")]
Raw(String),
#[serde(rename = "smtp-passwd-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "smtp-passwd-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Config")]
pub struct SmtpOAuth2ConfigDef {
#[serde(rename = "smtp-oauth2-method", with = "OAuth2MethodDef")]
pub method: OAuth2Method,
#[serde(rename = "smtp-oauth2-client-id")]
pub client_id: String,
#[serde(flatten, with = "SmtpOAuth2ClientSecretDef")]
pub client_secret: Secret,
#[serde(rename = "smtp-oauth2-auth-url")]
pub auth_url: String,
#[serde(rename = "smtp-oauth2-token-url")]
pub token_url: String,
#[serde(flatten, with = "SmtpOAuth2AccessTokenDef")]
pub access_token: Secret,
#[serde(flatten, with = "SmtpOAuth2RefreshTokenDef")]
pub refresh_token: Secret,
#[serde(flatten, with = "SmtpOAuth2ScopesDef")]
pub scopes: OAuth2Scopes,
#[serde(rename = "smtp-oauth2-pkce", default)]
pub pkce: bool,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret")]
pub enum SmtpOAuth2ClientSecretDef {
#[serde(rename = "smtp-oauth2-client-secret")]
Raw(String),
#[serde(rename = "smtp-oauth2-client-secret-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "smtp-oauth2-client-secret-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret")]
pub enum SmtpOAuth2AccessTokenDef {
#[serde(rename = "smtp-oauth2-access-token")]
Raw(String),
#[serde(rename = "smtp-oauth2-access-token-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "smtp-oauth2-access-token-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret")]
pub enum SmtpOAuth2RefreshTokenDef {
#[serde(rename = "smtp-oauth2-refresh-token")]
Raw(String),
#[serde(rename = "smtp-oauth2-refresh-token-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "smtp-oauth2-refresh-token-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Scopes")]
pub enum SmtpOAuth2ScopesDef {
#[serde(rename = "smtp-oauth2-scope")]
Scope(String),
#[serde(rename = "smtp-oauth2-scopes")]
Scopes(Vec<String>),
}
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "ImapConfig")] #[serde(remote = "ImapConfig")]
@ -165,39 +97,35 @@ pub struct ImapConfigDef {
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "ImapAuthConfig", tag = "imap-auth")] #[serde(remote = "ImapAuthConfig", tag = "imap-auth")]
pub enum ImapAuthConfigDef { pub enum ImapAuthConfigDef {
#[serde(rename = "passwd", alias = "password", with = "ImapPasswdDef")] #[serde(rename = "passwd", alias = "password", with = "ImapPasswdConfigDef")]
Passwd(Secret), Passwd(#[serde(default)] PasswdConfig),
#[serde(rename = "oauth2", with = "ImapOAuth2ConfigDef")] #[serde(rename = "oauth2", with = "ImapOAuth2ConfigDef")]
OAuth2(OAuth2Config), OAuth2(OAuth2Config),
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret", rename_all = "kebab-case")] #[serde(remote = "PasswdConfig")]
pub enum ImapPasswdDef { pub struct ImapPasswdConfigDef {
#[serde(rename = "imap-passwd")] #[serde(rename = "imap-passwd", with = "SecretDef", default)]
Raw(String), pub passwd: Secret,
#[serde(rename = "imap-passwd-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "imap-passwd-keyring", with = "EntryDef")]
Keyring(Entry),
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Config")] #[serde(remote = "OAuth2Config")]
pub struct ImapOAuth2ConfigDef { pub struct ImapOAuth2ConfigDef {
#[serde(rename = "imap-oauth2-method", with = "OAuth2MethodDef")] #[serde(rename = "imap-oauth2-method", with = "OAuth2MethodDef", default)]
pub method: OAuth2Method, pub method: OAuth2Method,
#[serde(rename = "imap-oauth2-client-id")] #[serde(rename = "imap-oauth2-client-id")]
pub client_id: String, pub client_id: String,
#[serde(flatten, with = "ImapOAuth2ClientSecretDef")] #[serde(rename = "imap-oauth2-client-secret", with = "SecretDef", default)]
pub client_secret: Secret, pub client_secret: Secret,
#[serde(rename = "imap-oauth2-auth-url")] #[serde(rename = "imap-oauth2-auth-url")]
pub auth_url: String, pub auth_url: String,
#[serde(rename = "imap-oauth2-token-url")] #[serde(rename = "imap-oauth2-token-url")]
pub token_url: String, pub token_url: String,
#[serde(flatten, with = "ImapOAuth2AccessTokenDef")] #[serde(rename = "imap-oauth2-access-token", with = "SecretDef", default)]
pub access_token: Secret, pub access_token: Secret,
#[serde(flatten, with = "ImapOAuth2RefreshTokenDef")] #[serde(rename = "imap-oauth2-refresh-token", with = "SecretDef", default)]
pub refresh_token: Secret, pub refresh_token: Secret,
#[serde(flatten, with = "ImapOAuth2ScopesDef")] #[serde(flatten, with = "ImapOAuth2ScopesDef")]
pub scopes: OAuth2Scopes, pub scopes: OAuth2Scopes,
@ -205,39 +133,6 @@ pub struct ImapOAuth2ConfigDef {
pub pkce: bool, pub pkce: bool,
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret")]
pub enum ImapOAuth2ClientSecretDef {
#[serde(rename = "imap-oauth2-client-secret")]
Raw(String),
#[serde(rename = "imap-oauth2-client-secret-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "imap-oauth2-client-secret-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret")]
pub enum ImapOAuth2AccessTokenDef {
#[serde(rename = "imap-oauth2-access-token")]
Raw(String),
#[serde(rename = "imap-oauth2-access-token-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "imap-oauth2-access-token-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "Secret")]
pub enum ImapOAuth2RefreshTokenDef {
#[serde(rename = "imap-oauth2-refresh-token")]
Raw(String),
#[serde(rename = "imap-oauth2-refresh-token-cmd", with = "CmdDef")]
Cmd(Cmd),
#[serde(rename = "imap-oauth2-refresh-token-keyring", with = "EntryDef")]
Keyring(Entry),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Scopes")] #[serde(remote = "OAuth2Scopes")]
pub enum ImapOAuth2ScopesDef { pub enum ImapOAuth2ScopesDef {
@ -287,6 +182,73 @@ pub enum EmailSenderDef {
Sendmail(SendmailConfig), Sendmail(SendmailConfig),
} }
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "SmtpConfig")]
struct SmtpConfigDef {
#[serde(rename = "smtp-host")]
pub host: String,
#[serde(rename = "smtp-port")]
pub port: u16,
#[serde(rename = "smtp-ssl")]
pub ssl: Option<bool>,
#[serde(rename = "smtp-starttls")]
pub starttls: Option<bool>,
#[serde(rename = "smtp-insecure")]
pub insecure: Option<bool>,
#[serde(rename = "smtp-login")]
pub login: String,
#[serde(flatten, with = "SmtpAuthConfigDef")]
pub auth: SmtpAuthConfig,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "SmtpAuthConfig", tag = "smtp-auth")]
pub enum SmtpAuthConfigDef {
#[serde(rename = "passwd", alias = "password", with = "SmtpPasswdConfigDef")]
Passwd(#[serde(default)] PasswdConfig),
#[serde(rename = "oauth2", with = "SmtpOAuth2ConfigDef")]
OAuth2(OAuth2Config),
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "PasswdConfig", default)]
pub struct SmtpPasswdConfigDef {
#[serde(rename = "smtp-passwd", with = "SecretDef", default)]
pub passwd: Secret,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Config")]
pub struct SmtpOAuth2ConfigDef {
#[serde(rename = "smtp-oauth2-method", with = "OAuth2MethodDef", default)]
pub method: OAuth2Method,
#[serde(rename = "smtp-oauth2-client-id")]
pub client_id: String,
#[serde(rename = "smtp-oauth2-client-secret", with = "SecretDef", default)]
pub client_secret: Secret,
#[serde(rename = "smtp-oauth2-auth-url")]
pub auth_url: String,
#[serde(rename = "smtp-oauth2-token-url")]
pub token_url: String,
#[serde(rename = "smtp-oauth2-access-token", with = "SecretDef", default)]
pub access_token: Secret,
#[serde(rename = "smtp-oauth2-refresh-token", with = "SecretDef", default)]
pub refresh_token: Secret,
#[serde(flatten, with = "SmtpOAuth2ScopesDef")]
pub scopes: OAuth2Scopes,
#[serde(rename = "smtp-oauth2-pkce", default)]
pub pkce: bool,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "OAuth2Scopes")]
pub enum SmtpOAuth2ScopesDef {
#[serde(rename = "smtp-oauth2-scope")]
Scope(String),
#[serde(rename = "smtp-oauth2-scopes")]
Scopes(Vec<String>),
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
#[serde(remote = "SendmailConfig", rename_all = "kebab-case")] #[serde(remote = "SendmailConfig", rename_all = "kebab-case")]
pub struct SendmailConfigDef { pub struct SendmailConfigDef {

View file

@ -1,7 +1,6 @@
use anyhow::Result; use anyhow::Result;
use dialoguer::{Input, Select}; use dialoguer::{Input, Select};
use pimalaya_email::ImapConfig; use pimalaya_email::ImapConfig;
use std::io;
use crate::account::{ use crate::account::{
DeserializedAccountConfig, DeserializedBaseAccountConfig, DeserializedImapAccountConfig, DeserializedAccountConfig, DeserializedBaseAccountConfig, DeserializedImapAccountConfig,
@ -59,11 +58,3 @@ pub(crate) fn configure(base: DeserializedBaseAccountConfig) -> Result<Deseriali
DeserializedImapAccountConfig { base, backend }, DeserializedImapAccountConfig { base, backend },
)) ))
} }
#[cfg(feature = "imap-backend")]
pub(crate) fn configure_oauth2_client_secret() -> io::Result<String> {
Input::with_theme(&*THEME)
.with_prompt("Enter your OAuth 2.0 client secret:")
.report(false)
.interact()
}

View file

@ -11,10 +11,10 @@ use super::DeserializedConfig;
use crate::account::{DeserializedAccountConfig, DeserializedBaseAccountConfig}; use crate::account::{DeserializedAccountConfig, DeserializedBaseAccountConfig};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use console::style; use console::style;
use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select}; use dialoguer::{theme::ColorfulTheme, Confirm, Input, Password, Select};
use log::trace; use log::trace;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::{fs, process}; use std::{fs, io, process};
const BACKENDS: &[&str] = &[ const BACKENDS: &[&str] = &[
"Maildir", "Maildir",
@ -163,3 +163,20 @@ fn configure_base() -> Result<DeserializedBaseAccountConfig> {
Ok(base_account_config) Ok(base_account_config)
} }
pub(crate) fn prompt_passwd(prompt: &str) -> io::Result<String> {
Password::with_theme(&*THEME)
.with_prompt(prompt)
.with_confirmation(
"Confirm password:",
"Passwords do not match, please try again.",
)
.interact()
}
pub(crate) fn prompt_secret(prompt: &str) -> io::Result<String> {
Input::with_theme(&*THEME)
.with_prompt(prompt)
.report(false)
.interact()
}

View file

@ -5,7 +5,7 @@
use pimalaya_email::{ use pimalaya_email::{
folder::sync::Strategy as SyncFoldersStrategy, AccountConfig, BackendConfig, EmailHooks, folder::sync::Strategy as SyncFoldersStrategy, AccountConfig, BackendConfig, EmailHooks,
EmailSender, EmailTextPlainFormat, MaildirConfig, EmailSender, EmailTextPlainFormat, ImapAuthConfig, MaildirConfig,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::HashMap, path::PathBuf}; use std::{collections::HashMap, path::PathBuf};
@ -46,10 +46,29 @@ impl DeserializedAccountConfig {
BackendConfig::Maildir(config.backend.clone()), BackendConfig::Maildir(config.backend.clone()),
), ),
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
DeserializedAccountConfig::Imap(config) => ( DeserializedAccountConfig::Imap(config) => {
config.base.to_account_config(name, global_config), let mut imap_config = config.backend.clone();
BackendConfig::Imap(config.backend.clone()),
), match &mut imap_config.auth {
ImapAuthConfig::Passwd(secret) => {
secret.replace_undefined_entry_with(format!("{name}-imap-passwd"));
}
ImapAuthConfig::OAuth2(config) => {
config.client_secret.replace_undefined_entry_with(format!(
"{name}-imap-oauth2-client-secret"
));
config.access_token.replace_undefined_entry_with(format!(
"{name}-imap-oauth2-access-token"
));
config.refresh_token.replace_undefined_entry_with(format!(
"{name}-imap-oauth2-refresh-token"
));
}
};
let account_config = config.base.to_account_config(name, global_config);
(account_config, BackendConfig::Imap(imap_config))
}
#[cfg(feature = "notmuch-backend")] #[cfg(feature = "notmuch-backend")]
DeserializedAccountConfig::Notmuch(config) => ( DeserializedAccountConfig::Notmuch(config) => (
config.base.to_account_config(name, global_config), config.base.to_account_config(name, global_config),

View file

@ -7,11 +7,14 @@ use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
use log::{info, trace, warn}; use log::{info, trace, warn};
use pimalaya_email::{ use pimalaya_email::{
folder::sync::Strategy as SyncFoldersStrategy, AccountConfig, Backend, BackendConfig, folder::sync::Strategy as SyncFoldersStrategy, AccountConfig, Backend, BackendConfig,
BackendSyncBuilder, BackendSyncProgressEvent, EmailSender, BackendSyncBuilder, BackendSyncProgressEvent, EmailSender, ImapAuthConfig, SmtpAuthConfig,
}; };
use crate::{ use crate::{
config::{wizard::imap::configure_oauth2_client_secret, DeserializedConfig}, config::{
wizard::{prompt_passwd, prompt_secret},
DeserializedConfig,
},
printer::{PrintTableOpts, Printer}, printer::{PrintTableOpts, Printer},
Accounts, Accounts,
}; };
@ -27,8 +30,11 @@ pub fn configure(
if reset { if reset {
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
if let BackendConfig::Imap(imap_config) = backend_config { if let BackendConfig::Imap(imap_config) = backend_config {
println!("Resetting IMAP secrets…"); let reset = match &imap_config.auth {
if let Err(err) = imap_config.auth.reset() { ImapAuthConfig::Passwd(passwd) => passwd.reset(),
ImapAuthConfig::OAuth2(oauth2) => oauth2.reset(),
};
if let Err(err) = reset {
warn!("error while resetting imap secrets, skipping it"); warn!("error while resetting imap secrets, skipping it");
warn!("{err}"); warn!("{err}");
} }
@ -36,8 +42,11 @@ pub fn configure(
#[cfg(feature = "smtp-sender")] #[cfg(feature = "smtp-sender")]
if let EmailSender::Smtp(smtp_config) = &account_config.email_sender { if let EmailSender::Smtp(smtp_config) = &account_config.email_sender {
println!("Resetting SMTP secrets…"); let reset = match &smtp_config.auth {
if let Err(err) = smtp_config.auth.reset() { SmtpAuthConfig::Passwd(passwd) => passwd.reset(),
SmtpAuthConfig::OAuth2(oauth2) => oauth2.reset(),
};
if let Err(err) = reset {
warn!("error while resetting smtp secrets, skipping it"); warn!("error while resetting smtp secrets, skipping it");
warn!("{err}"); warn!("{err}");
} }
@ -46,14 +55,26 @@ pub fn configure(
#[cfg(feature = "imap-backend")] #[cfg(feature = "imap-backend")]
if let BackendConfig::Imap(imap_config) = backend_config { if let BackendConfig::Imap(imap_config) = backend_config {
println!("Configuring IMAP secrets…"); match &imap_config.auth {
imap_config.auth.configure(configure_oauth2_client_secret)?; ImapAuthConfig::Passwd(passwd) => {
passwd.configure(|| prompt_passwd("Enter your IMAP password:"))
}
ImapAuthConfig::OAuth2(oauth2) => {
oauth2.configure(|| prompt_secret("Enter your IMAP OAuth 2.0 client secret:"))
}
}?;
} }
#[cfg(feature = "smtp-sender")] #[cfg(feature = "smtp-sender")]
if let EmailSender::Smtp(smtp_config) = &account_config.email_sender { if let EmailSender::Smtp(smtp_config) = &account_config.email_sender {
println!("Configuring SMTP secrets…"); match &smtp_config.auth {
smtp_config.auth.configure(configure_oauth2_client_secret)?; SmtpAuthConfig::Passwd(passwd) => {
passwd.configure(|| prompt_passwd("Enter your SMTP password:"))
}
SmtpAuthConfig::OAuth2(oauth2) => {
oauth2.configure(|| prompt_secret("Enter your SMTP OAuth 2.0 client secret:"))
}
}?;
} }
println!("Account successfully configured!"); println!("Account successfully configured!");