mirror of
https://github.com/pimalaya/himalaya.git
synced 2026-06-16 20:57:53 +08:00
generate one autoconfig per email address
This commit is contained in:
+20
-2
@@ -5,6 +5,7 @@ use dialoguer::Input;
|
||||
#[cfg(feature = "account-sync")]
|
||||
use email::account::sync::config::SyncConfig;
|
||||
use email_address::EmailAddress;
|
||||
use log::{debug, trace, warn};
|
||||
|
||||
#[allow(unused)]
|
||||
use crate::backend::{self, config::BackendConfig, BackendKind};
|
||||
@@ -35,6 +36,8 @@ pub(crate) async fn configure() -> Result<Option<(String, TomlAccountConfig)>> {
|
||||
})
|
||||
.interact()?;
|
||||
|
||||
let email = &config.email;
|
||||
|
||||
config.display_name = Some(
|
||||
Input::with_theme(&*THEME)
|
||||
.with_prompt("Full display name")
|
||||
@@ -49,7 +52,22 @@ pub(crate) async fn configure() -> Result<Option<(String, TomlAccountConfig)>> {
|
||||
.into(),
|
||||
);
|
||||
|
||||
match backend::wizard::configure(&account_name, &config.email).await? {
|
||||
let autoconfig = match autoconfig::from_addr(email).await {
|
||||
Ok(autoconfig) => {
|
||||
println!("An automatic configuration has been found for {email},");
|
||||
println!("it will be used by default for the rest of the configuration.\n");
|
||||
trace!("{autoconfig:#?}");
|
||||
Some(autoconfig)
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("cannot discover configuration from {email}: {err}");
|
||||
debug!("{err:?}");
|
||||
None
|
||||
}
|
||||
};
|
||||
let autoconfig = autoconfig.as_ref();
|
||||
|
||||
match backend::wizard::configure(&account_name, email, autoconfig).await? {
|
||||
#[cfg(feature = "imap")]
|
||||
Some(BackendConfig::Imap(imap_config)) => {
|
||||
config.imap = Some(imap_config);
|
||||
@@ -68,7 +86,7 @@ pub(crate) async fn configure() -> Result<Option<(String, TomlAccountConfig)>> {
|
||||
_ => (),
|
||||
};
|
||||
|
||||
match backend::wizard::configure_sender(&account_name, &config.email).await? {
|
||||
match backend::wizard::configure_sender(&account_name, email, autoconfig).await? {
|
||||
#[cfg(feature = "smtp")]
|
||||
Some(BackendConfig::Smtp(smtp_config)) => {
|
||||
config.smtp = Some(smtp_config);
|
||||
|
||||
+4
-21
@@ -1,8 +1,6 @@
|
||||
use anyhow::Result;
|
||||
use autoconfig::config::Config as AutoConfig;
|
||||
use dialoguer::Select;
|
||||
use log::{debug, warn};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
#[cfg(feature = "imap")]
|
||||
use crate::imap;
|
||||
@@ -34,26 +32,10 @@ const SEND_MESSAGE_BACKEND_KINDS: &[BackendKind] = &[
|
||||
BackendKind::Sendmail,
|
||||
];
|
||||
|
||||
static AUTOCONFIG: OnceLock<AutoConfig> = OnceLock::new();
|
||||
|
||||
#[cfg(any(feature = "imap", feature = "smtp"))]
|
||||
pub(crate) async fn get_or_init_autoconfig(email: &str) -> Option<&AutoConfig> {
|
||||
match AUTOCONFIG.get() {
|
||||
Some(autoconfig) => Some(autoconfig),
|
||||
None => match autoconfig::from_addr(email).await {
|
||||
Ok(autoconfig) => Some(AUTOCONFIG.get_or_init(|| autoconfig)),
|
||||
Err(err) => {
|
||||
warn!("cannot discover SMTP configuration from {email}: {err}");
|
||||
debug!("{err:?}");
|
||||
None
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn configure(
|
||||
#[allow(unused)] account_name: &str,
|
||||
#[allow(unused)] email: &str,
|
||||
autoconfig: Option<&AutoConfig>,
|
||||
) -> Result<Option<BackendConfig>> {
|
||||
let kind = Select::with_theme(&*THEME)
|
||||
.with_prompt("Default email backend")
|
||||
@@ -65,7 +47,7 @@ pub(crate) async fn configure(
|
||||
let config = match kind {
|
||||
#[cfg(feature = "imap")]
|
||||
Some(kind) if kind == BackendKind::Imap => {
|
||||
Some(imap::wizard::configure(account_name, email).await?)
|
||||
Some(imap::wizard::configure(account_name, email, autoconfig).await?)
|
||||
}
|
||||
#[cfg(feature = "maildir")]
|
||||
Some(kind) if kind == BackendKind::Maildir => Some(maildir::wizard::configure()?),
|
||||
@@ -80,6 +62,7 @@ pub(crate) async fn configure(
|
||||
pub(crate) async fn configure_sender(
|
||||
#[allow(unused)] account_name: &str,
|
||||
#[allow(unused)] email: &str,
|
||||
autoconfig: Option<&AutoConfig>,
|
||||
) -> Result<Option<BackendConfig>> {
|
||||
let kind = Select::with_theme(&*THEME)
|
||||
.with_prompt("Backend for sending messages")
|
||||
@@ -91,7 +74,7 @@ pub(crate) async fn configure_sender(
|
||||
let config = match kind {
|
||||
#[cfg(feature = "smtp")]
|
||||
Some(kind) if kind == BackendKind::Smtp => {
|
||||
Some(smtp::wizard::configure(account_name, email).await?)
|
||||
Some(smtp::wizard::configure(account_name, email, autoconfig).await?)
|
||||
}
|
||||
#[cfg(feature = "sendmail")]
|
||||
Some(kind) if kind == BackendKind::Sendmail => Some(sendmail::wizard::configure()?),
|
||||
|
||||
@@ -191,13 +191,15 @@ mod test {
|
||||
|
||||
use crate::{account::config::TomlAccountConfig, config::TomlConfig};
|
||||
|
||||
use super::pretty_serialize;
|
||||
|
||||
fn assert_eq(config: TomlAccountConfig, expected_toml: &str) {
|
||||
let config = TomlConfig {
|
||||
accounts: HashMap::from_iter([("test".into(), config)]),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let toml = super::pretty_serialize(&config).expect("serialize error");
|
||||
let toml = pretty_serialize(&config).expect("serialize error");
|
||||
assert_eq!(toml, expected_toml);
|
||||
|
||||
let expected_config = toml::from_str(&toml).expect("deserialize error");
|
||||
|
||||
+7
-4
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use autoconfig::config::{AuthenticationType, SecurityType, ServerType};
|
||||
use autoconfig::config::{AuthenticationType, Config as AutoConfig, SecurityType, ServerType};
|
||||
use dialoguer::{Confirm, Input, Password, Select};
|
||||
use email::{
|
||||
account::config::{
|
||||
@@ -12,7 +12,7 @@ use oauth::v2_0::{AuthorizationCodeGrant, Client};
|
||||
use secret::Secret;
|
||||
|
||||
use crate::{
|
||||
backend::{config::BackendConfig, wizard::get_or_init_autoconfig},
|
||||
backend::config::BackendConfig,
|
||||
ui::{prompt, THEME},
|
||||
wizard_log, wizard_prompt,
|
||||
};
|
||||
@@ -32,8 +32,11 @@ const KEYRING: &str = "Ask my password, then save it in my system's global keyri
|
||||
const RAW: &str = "Ask my password, then save it in the configuration file (not safe)";
|
||||
const CMD: &str = "Ask me a shell command that exposes my password";
|
||||
|
||||
pub(crate) async fn configure(account_name: &str, email: &str) -> Result<BackendConfig> {
|
||||
let autoconfig = get_or_init_autoconfig(email).await;
|
||||
pub(crate) async fn configure(
|
||||
account_name: &str,
|
||||
email: &str,
|
||||
autoconfig: Option<&AutoConfig>,
|
||||
) -> Result<BackendConfig> {
|
||||
let autoconfig_oauth2 = autoconfig.and_then(|c| c.oauth2());
|
||||
let autoconfig_server = autoconfig.and_then(|c| {
|
||||
c.email_provider()
|
||||
|
||||
+10
-7
@@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use autoconfig::config::{AuthenticationType, SecurityType, ServerType};
|
||||
use autoconfig::config::{AuthenticationType, Config as AutoConfig, SecurityType, ServerType};
|
||||
use dialoguer::{Confirm, Input, Password, Select};
|
||||
use email::{
|
||||
account::config::{
|
||||
@@ -12,7 +12,7 @@ use oauth::v2_0::{AuthorizationCodeGrant, Client};
|
||||
use secret::Secret;
|
||||
|
||||
use crate::{
|
||||
backend::{config::BackendConfig, wizard::get_or_init_autoconfig},
|
||||
backend::config::BackendConfig,
|
||||
ui::{prompt, THEME},
|
||||
wizard_log, wizard_prompt,
|
||||
};
|
||||
@@ -32,8 +32,11 @@ const KEYRING: &str = "Ask my password, then save it in my system's global keyri
|
||||
const RAW: &str = "Ask my password, then save it in the configuration file (not safe)";
|
||||
const CMD: &str = "Ask me a shell command that exposes my password";
|
||||
|
||||
pub(crate) async fn configure(account_name: &str, email: &str) -> Result<BackendConfig> {
|
||||
let autoconfig = get_or_init_autoconfig(email).await;
|
||||
pub(crate) async fn configure(
|
||||
account_name: &str,
|
||||
email: &str,
|
||||
autoconfig: Option<&AutoConfig>,
|
||||
) -> Result<BackendConfig> {
|
||||
let autoconfig_oauth2 = autoconfig.and_then(|c| c.oauth2());
|
||||
let autoconfig_server = autoconfig.and_then(|c| {
|
||||
c.email_provider()
|
||||
@@ -80,9 +83,9 @@ pub(crate) async fn configure(account_name: &str, email: &str) -> Result<Backend
|
||||
.and_then(|s| s.port())
|
||||
.map(ToOwned::to_owned)
|
||||
.unwrap_or_else(|| match &autoconfig_encryption {
|
||||
SmtpEncryptionKind::Tls => 993,
|
||||
SmtpEncryptionKind::StartTls => 143,
|
||||
SmtpEncryptionKind::None => 143,
|
||||
SmtpEncryptionKind::Tls => 465,
|
||||
SmtpEncryptionKind::StartTls => 587,
|
||||
SmtpEncryptionKind::None => 25,
|
||||
});
|
||||
|
||||
let (encryption, default_port) = match encryption_idx {
|
||||
|
||||
Reference in New Issue
Block a user