mirror of
https://github.com/pimalaya/himalaya.git
synced 2026-06-15 11:27:53 +08:00
refactor: improve sasl config
This commit is contained in:
+10
-15
@@ -180,22 +180,19 @@ imap.server = "example.com"
|
||||
|
||||
# SASL PLAIN
|
||||
# https://datatracker.ietf.org/doc/html/rfc4616
|
||||
imap.sasl.plain.authcid = "user@example.com"
|
||||
imap.sasl.plain.passwd.raw = "***"
|
||||
#imap.sasl.plain.passwd.command = "pass show example"
|
||||
#imap.sasl.plain.passwd.command = ["mimosa", "password", "read", "example"]
|
||||
imap.sasl.plain.username = "user@example.com"
|
||||
imap.sasl.plain.password.raw = "***"
|
||||
#imap.sasl.plain.password.command = "pass show example"
|
||||
|
||||
# SASL LOGIN
|
||||
# https://datatracker.ietf.org/doc/html/draft-murchison-sasl-login-00
|
||||
#imap.sasl.login.username = "user@example.com"
|
||||
#imap.sasl.login.password.raw = "***"
|
||||
|
||||
# SASL OAUTHBEARER (host/port echoed in the GS2 header; usually mirror the
|
||||
# server you actually connect to).
|
||||
# SASL OAUTHBEARER (host/port for the GS2 header are derived from the
|
||||
# IMAP server URL at connect time).
|
||||
# https://datatracker.ietf.org/doc/html/rfc7628
|
||||
#imap.sasl.oauthbearer.username = "user@example.com"
|
||||
#imap.sasl.oauthbearer.host = "imap.example.com"
|
||||
#imap.sasl.oauthbearer.port = 993
|
||||
#imap.sasl.oauthbearer.token.raw = "***"
|
||||
#imap.sasl.oauthbearer.token.command = ["ortie", "token", "read", "example"]
|
||||
|
||||
@@ -312,19 +309,17 @@ smtp.server = "example.com"
|
||||
#smtp.sasl.anonymous.message = "himalaya"
|
||||
|
||||
# SASL PLAIN
|
||||
smtp.sasl.plain.authcid = "user@example.com"
|
||||
smtp.sasl.plain.passwd.raw = "***"
|
||||
#smtp.sasl.plain.passwd.command = "pass show example"
|
||||
#smtp.sasl.plain.passwd.command = ["mimosa", "password", "read", "example"]
|
||||
smtp.sasl.plain.username = "user@example.com"
|
||||
smtp.sasl.plain.password.raw = "***"
|
||||
#smtp.sasl.plain.password.command = "pass show example"
|
||||
|
||||
# SASL LOGIN
|
||||
#smtp.sasl.login.username = "user@example.com"
|
||||
#smtp.sasl.login.password.raw = "***"
|
||||
|
||||
# SASL OAUTHBEARER
|
||||
# SASL OAUTHBEARER (host/port for the GS2 header are derived from the
|
||||
# SMTP server URL at connect time).
|
||||
#smtp.sasl.oauthbearer.username = "user@example.com"
|
||||
#smtp.sasl.oauthbearer.host = "smtp.example.com"
|
||||
#smtp.sasl.oauthbearer.port = 465
|
||||
#smtp.sasl.oauthbearer.token.raw = "***"
|
||||
|
||||
# SASL XOAUTH2
|
||||
|
||||
+18
-2
@@ -120,9 +120,17 @@ fn check_imap(
|
||||
|
||||
let result = (|| -> Result<()> {
|
||||
let tls = imap_config.tls.clone().into_tls(imap_config.alpn.clone());
|
||||
let sasl: Option<Sasl> = imap_config.sasl.clone().map(Sasl::try_from).transpose()?;
|
||||
let auto_id = resolve_auto_id_params(&imap_config.id)?;
|
||||
let server = crate::imap::client::parse_imap_server(&imap_config.server)?;
|
||||
let sasl: Option<Sasl> = imap_config
|
||||
.sasl
|
||||
.clone()
|
||||
.and_then(|cfg| {
|
||||
let host = server.host_str()?;
|
||||
let port = server.port_or_known_default()?;
|
||||
Some(cfg.try_into_sasl(host, port))
|
||||
})
|
||||
.transpose()?;
|
||||
let _ = ImapClientStd::connect(&server, &tls, imap_config.starttls, sasl, auto_id)?;
|
||||
Ok(())
|
||||
})();
|
||||
@@ -184,9 +192,17 @@ fn check_smtp(
|
||||
|
||||
let result = (|| -> Result<()> {
|
||||
let tls = smtp_config.tls.clone().into_tls(smtp_config.alpn.clone());
|
||||
let sasl: Option<Sasl> = smtp_config.sasl.clone().map(Sasl::try_from).transpose()?;
|
||||
let domain: EhloDomain<'static> = Ipv4Addr::new(127, 0, 0, 1).into();
|
||||
let server = crate::smtp::client::parse_smtp_server(&smtp_config.server)?;
|
||||
let sasl: Option<Sasl> = smtp_config
|
||||
.sasl
|
||||
.clone()
|
||||
.and_then(|cfg| {
|
||||
let host = server.host_str()?;
|
||||
let port = server.port_or_known_default()?;
|
||||
Some(cfg.try_into_sasl(host, port))
|
||||
})
|
||||
.transpose()?;
|
||||
let _client = SmtpClientStd::connect(&server, &tls, smtp_config.starttls, domain, sasl)?;
|
||||
Ok(())
|
||||
})();
|
||||
|
||||
+14
-11
@@ -518,14 +518,17 @@ pub struct SaslLoginConfig {
|
||||
pub struct SaslPlainConfig {
|
||||
pub authzid: Option<String>,
|
||||
#[serde(deserialize_with = "shell_expanded_string")]
|
||||
#[serde(alias = "username")]
|
||||
pub authcid: String,
|
||||
#[serde(alias = "password")]
|
||||
pub passwd: Secret,
|
||||
}
|
||||
|
||||
/// SASL OAUTHBEARER configuration <sup>[rfc7628]</sup>.
|
||||
///
|
||||
/// `host` and `port` are echoed verbatim in the GS2 header and should
|
||||
/// match the server the connection is actually opened against.
|
||||
/// The `host` and `port` echoed in the GS2 header are derived from
|
||||
/// the live IMAP/SMTP server URL at connect time, so they aren't part
|
||||
/// of the user-facing config.
|
||||
///
|
||||
/// [rfc7628]: https://www.iana.org/go/rfc7628
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
@@ -533,8 +536,6 @@ pub struct SaslPlainConfig {
|
||||
pub struct SaslOauthbearerConfig {
|
||||
#[serde(deserialize_with = "shell_expanded_string")]
|
||||
pub username: String,
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
pub token: Secret,
|
||||
}
|
||||
|
||||
@@ -559,11 +560,13 @@ pub struct SaslScramSha256Config {
|
||||
pub password: Secret,
|
||||
}
|
||||
|
||||
impl TryFrom<SaslConfig> for Sasl {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(config: SaslConfig) -> Result<Self> {
|
||||
Ok(match config {
|
||||
impl SaslConfig {
|
||||
/// Resolves the SASL config into a runtime [`Sasl`]. `host` and
|
||||
/// `port` come from the live server URL; they are only used by
|
||||
/// OAUTHBEARER (echoed in the GS2 header) and ignored by every
|
||||
/// other mechanism.
|
||||
pub fn try_into_sasl(self, host: impl ToString, port: u16) -> Result<Sasl> {
|
||||
Ok(match self {
|
||||
SaslConfig::Anonymous(c) => Sasl::Anonymous(SaslAnonymous { message: c.message }),
|
||||
SaslConfig::Login(c) => Sasl::Login(SaslLogin {
|
||||
username: c.username,
|
||||
@@ -576,8 +579,8 @@ impl TryFrom<SaslConfig> for Sasl {
|
||||
}),
|
||||
SaslConfig::Oauthbearer(c) => Sasl::Oauthbearer(SaslOauthbearer {
|
||||
username: c.username,
|
||||
host: c.host,
|
||||
port: c.port,
|
||||
host: host.to_string(),
|
||||
port,
|
||||
token: c.token.get()?,
|
||||
}),
|
||||
SaslConfig::Xoauth2(c) => Sasl::Xoauth2(SaslXoauth2 {
|
||||
|
||||
+8
-1
@@ -49,9 +49,16 @@ impl ImapClient {
|
||||
/// [`Inner::capability`] explicitly.
|
||||
pub fn new(config: ImapConfig) -> Result<Self> {
|
||||
let tls = config.tls.into_tls(config.alpn);
|
||||
let sasl: Option<Sasl> = config.sasl.map(Sasl::try_from).transpose()?;
|
||||
let auto_id = resolve_auto_id_params(&config.id)?;
|
||||
let server = parse_imap_server(&config.server)?;
|
||||
let sasl: Option<Sasl> = config
|
||||
.sasl
|
||||
.and_then(|cfg| {
|
||||
let host = server.host_str()?;
|
||||
let port = server.port_or_known_default()?;
|
||||
Some(cfg.try_into_sasl(host, port))
|
||||
})
|
||||
.transpose()?;
|
||||
let (inner, _capability) = Inner::connect(&server, &tls, config.starttls, sasl, auto_id)?;
|
||||
Ok(Self { inner })
|
||||
}
|
||||
|
||||
+16
-2
@@ -78,9 +78,16 @@ impl EmailClient {
|
||||
use crate::imap::id::resolve_auto_id_params;
|
||||
|
||||
let tls = imap_config.tls.into_tls(imap_config.alpn);
|
||||
let sasl: Option<Sasl> = imap_config.sasl.map(Sasl::try_from).transpose()?;
|
||||
let auto_id = resolve_auto_id_params(&imap_config.id)?;
|
||||
let server = crate::imap::client::parse_imap_server(&imap_config.server)?;
|
||||
let sasl: Option<Sasl> = imap_config
|
||||
.sasl
|
||||
.and_then(|cfg| {
|
||||
let host = server.host_str()?;
|
||||
let port = server.port_or_known_default()?;
|
||||
Some(cfg.try_into_sasl(host, port))
|
||||
})
|
||||
.transpose()?;
|
||||
let imap =
|
||||
ImapClientStd::connect(&server, &tls, imap_config.starttls, sasl, auto_id)?;
|
||||
inner = inner.with_imap(imap);
|
||||
@@ -126,9 +133,16 @@ impl EmailClient {
|
||||
use pimalaya_stream::sasl::Sasl;
|
||||
|
||||
let tls = smtp_config.tls.into_tls(smtp_config.alpn);
|
||||
let sasl: Option<Sasl> = smtp_config.sasl.map(Sasl::try_from).transpose()?;
|
||||
let domain: EhloDomain<'static> = Ipv4Addr::new(127, 0, 0, 1).into();
|
||||
let server = crate::smtp::client::parse_smtp_server(&smtp_config.server)?;
|
||||
let sasl: Option<Sasl> = smtp_config
|
||||
.sasl
|
||||
.and_then(|cfg| {
|
||||
let host = server.host_str()?;
|
||||
let port = server.port_or_known_default()?;
|
||||
Some(cfg.try_into_sasl(host, port))
|
||||
})
|
||||
.transpose()?;
|
||||
inner = inner.with_smtp(SmtpClientStd::connect(
|
||||
&server,
|
||||
&tls,
|
||||
|
||||
+8
-1
@@ -46,9 +46,16 @@ impl SmtpClient {
|
||||
/// SASL).
|
||||
pub fn new(config: SmtpConfig) -> Result<Self> {
|
||||
let tls = config.tls.into_tls(config.alpn);
|
||||
let sasl: Option<Sasl> = config.sasl.map(Sasl::try_from).transpose()?;
|
||||
let domain: EhloDomain<'static> = Ipv4Addr::new(127, 0, 0, 1).into();
|
||||
let server = parse_smtp_server(&config.server)?;
|
||||
let sasl: Option<Sasl> = config
|
||||
.sasl
|
||||
.and_then(|cfg| {
|
||||
let host = server.host_str()?;
|
||||
let port = server.port_or_known_default()?;
|
||||
Some(cfg.try_into_sasl(host, port))
|
||||
})
|
||||
.transpose()?;
|
||||
let inner = Inner::connect(&server, &tls, config.starttls, domain, sasl)?;
|
||||
Ok(Self { inner })
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user