forked from meli/meli
1
Fork 0

melib: add server_password_command to jmap

Move the handling of either `server_password` or
`server_password_command` from the imap backend to the common
`AccountSettings` struct and add it for jmap as well.
jmap-bearer-token
Johannes Schilling 2023-03-05 19:53:00 +01:00 committed by Manos Pitsidianakis
parent f9ac9b607a
commit 12cb717bda
3 changed files with 45 additions and 29 deletions

View File

@ -1259,33 +1259,15 @@ impl ImapType {
let server_hostname = get_conf_val!(s["server_hostname"])?;
let server_username = get_conf_val!(s["server_username"])?;
let use_oauth2: bool = get_conf_val!(s["use_oauth2"], false)?;
let server_password = if !s.extra.contains_key("server_password_command") {
if use_oauth2 {
return Err(Error::new(format!(
"({}) `use_oauth2` use requires `server_password_command` set with a command that returns an OAUTH2 token. Consult documentation for guidance.",
s.name,
)));
}
get_conf_val!(s["server_password"])?.to_string()
} else {
let invocation = get_conf_val!(s["server_password_command"])?;
let output = std::process::Command::new("sh")
.args(&["-c", invocation])
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()?;
if !output.status.success() {
return Err(Error::new(format!(
"({}) server_password_command `{}` returned {}: {}",
s.name,
get_conf_val!(s["server_password_command"])?,
output.status,
String::from_utf8_lossy(&output.stderr)
)));
}
std::str::from_utf8(&output.stdout)?.trim_end().to_string()
};
if use_oauth2 && !s.extra.contains_key("server_password_command") {
return Err(Error::new(format!(
"({}) `use_oauth2` use requires `server_password_command` set with a command that returns an OAUTH2 token. Consult documentation for guidance.",
s.name,
)));
}
let server_password = s.server_password()?;
let server_port = get_conf_val!(s["server_port"], 143)?;
let use_tls = get_conf_val!(s["use_tls"], true)?;
let use_starttls = use_tls && get_conf_val!(s["use_starttls"], server_port != 993)?;

View File

@ -126,7 +126,7 @@ impl JmapServerConf {
Ok(JmapServerConf {
server_url: get_conf_val!(s["server_url"])?.to_string(),
server_username: get_conf_val!(s["server_username"])?.to_string(),
server_password: get_conf_val!(s["server_password"])?.to_string(),
server_password: s.server_password()?,
danger_accept_invalid_certs: get_conf_val!(s["danger_accept_invalid_certs"], false)?,
timeout: get_conf_val!(s["timeout"], 16_u64).map(|t| {
if t == 0 {
@ -924,7 +924,10 @@ impl JmapType {
}
get_conf_val!(s["server_url"])?;
get_conf_val!(s["server_username"])?;
get_conf_val!(s["server_password"])?;
// either of these two needed
get_conf_val!(s["server_password"]).or(get_conf_val!(s["server_password_command"]))?;
get_conf_val!(s["danger_accept_invalid_certs"], false)?;
Ok(())
}

View File

@ -21,6 +21,7 @@
//! Basic mail account configuration to use with [`backends`](./backends/index.html)
use crate::backends::SpecialUsageMailbox;
use crate::error::{Error, Result};
pub use crate::{SortField, SortOrder};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;
@ -79,6 +80,36 @@ impl AccountSettings {
pub fn vcard_folder(&self) -> Option<&str> {
self.extra.get("vcard_folder").map(String::as_str)
}
/// Get the server password, either directly from the `server_password`
/// settings value, or by running the `server_password_command` and reading
/// the output.
pub fn server_password(&self) -> Result<String> {
if let Some(cmd) = self.extra.get("server_password_command") {
let output = std::process::Command::new("sh")
.args(&["-c", cmd])
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::piped())
.output()?;
if output.status.success() {
Ok(std::str::from_utf8(&output.stdout)?.trim_end().to_string())
} else {
Err(Error::new(format!(
"({}) server_password_command `{}` returned {}: {}",
self.name,
cmd,
output.status,
String::from_utf8_lossy(&output.stderr)
)))
}
} else if let Some(pass) = self.extra.get("server_password") {
Ok(pass.to_owned())
} else {
Err(Error::new(format!("Configuration error: connection requires either server_password or server_password_command")))
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]