feat(starttls): remove opportunistic value
This commit removes the `Opportunistic` value from the struct `StartTls`. This value was strictly equivalent to `Always` and could potentially cause confusion.
This commit is contained in:
@@ -321,7 +321,7 @@ backend/
|
|||||||
|
|
||||||
The contact form supports multiple SMTP configurations:
|
The contact form supports multiple SMTP configurations:
|
||||||
- **Implicit TLS (SMTPS)** - typically port 465
|
- **Implicit TLS (SMTPS)** - typically port 465
|
||||||
- **STARTTLS (Always/Opportunistic)** - typically port 587
|
- **STARTTLS (Always)** - typically port 587
|
||||||
- **Unencrypted** (for local dev) - with or without authentication
|
- **Unencrypted** (for local dev) - with or without authentication
|
||||||
|
|
||||||
The `SmtpTransport` is built dynamically from `EmailSettings` based on
|
The `SmtpTransport` is built dynamically from `EmailSettings` based on
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ impl TryFrom<&EmailSettings> for SmtpTransport {
|
|||||||
Ok(builder.credentials(creds).build())
|
Ok(builder.credentials(creds).build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Starttls::Opportunistic | Starttls::Always => {
|
Starttls::Always => {
|
||||||
// STARTTLS - typically port 587
|
// STARTTLS - typically port 587
|
||||||
tracing::event!(target: "backend::contact", tracing::Level::DEBUG, "Using STARTTLS");
|
tracing::event!(target: "backend::contact", tracing::Level::DEBUG, "Using STARTTLS");
|
||||||
let creds = Credentials::new(settings.user.clone(), settings.password.clone());
|
let creds = Credentials::new(settings.user.clone(), settings.password.clone());
|
||||||
@@ -429,23 +429,6 @@ mod tests {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn smtp_transport_starttls_opportunistic() {
|
|
||||||
let settings = EmailSettings {
|
|
||||||
host: "smtp.example.com".to_string(),
|
|
||||||
port: 587,
|
|
||||||
user: "user@example.com".to_string(),
|
|
||||||
password: "password".to_string(),
|
|
||||||
from: "from@example.com".to_string(),
|
|
||||||
recipient: "to@example.com".to_string(),
|
|
||||||
tls: false,
|
|
||||||
starttls: Starttls::Opportunistic,
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = SmtpTransport::try_from(&settings);
|
|
||||||
assert!(result.is_ok());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn smtp_transport_no_encryption_with_credentials() {
|
fn smtp_transport_no_encryption_with_credentials() {
|
||||||
let settings = EmailSettings {
|
let settings = EmailSettings {
|
||||||
|
|||||||
+2
-39
@@ -196,8 +196,6 @@ pub enum Starttls {
|
|||||||
/// Never use STARTTLS (unencrypted connection)
|
/// Never use STARTTLS (unencrypted connection)
|
||||||
#[default]
|
#[default]
|
||||||
Never,
|
Never,
|
||||||
/// Use STARTTLS if available (opportunistic encryption)
|
|
||||||
Opportunistic,
|
|
||||||
/// Always use STARTTLS (required encryption)
|
/// Always use STARTTLS (required encryption)
|
||||||
Always,
|
Always,
|
||||||
}
|
}
|
||||||
@@ -208,10 +206,9 @@ impl TryFrom<&str> for Starttls {
|
|||||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||||
match value.to_lowercase().as_str() {
|
match value.to_lowercase().as_str() {
|
||||||
"off" | "no" | "never" => Ok(Self::Never),
|
"off" | "no" | "never" => Ok(Self::Never),
|
||||||
"opportunistic" => Ok(Self::Opportunistic),
|
|
||||||
"yes" | "always" => Ok(Self::Always),
|
"yes" | "always" => Ok(Self::Always),
|
||||||
other => Err(format!(
|
other => Err(format!(
|
||||||
"{other} is not a supported option. Use either `yes`, `no`, or `opportunistic`"
|
"{other} is not a supported option. Use either `yes` or `no`"
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,7 +231,6 @@ impl std::fmt::Display for Starttls {
|
|||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let self_str = match self {
|
let self_str = match self {
|
||||||
Self::Never => "never",
|
Self::Never => "never",
|
||||||
Self::Opportunistic => "opportunistic",
|
|
||||||
Self::Always => "always",
|
Self::Always => "always",
|
||||||
};
|
};
|
||||||
write!(f, "{self_str}")
|
write!(f, "{self_str}")
|
||||||
@@ -252,7 +248,7 @@ impl<'de> serde::Deserialize<'de> for Starttls {
|
|||||||
type Value = Starttls;
|
type Value = Starttls;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
formatter.write_str("a string or boolean representing STARTTLS setting (e.g., 'yes', 'no', 'opportunistic', true, false)")
|
formatter.write_str("a string or boolean representing STARTTLS setting (e.g., 'yes', 'no', true, false)")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_str<E>(self, value: &str) -> Result<Starttls, E>
|
fn visit_str<E>(self, value: &str) -> Result<Starttls, E>
|
||||||
@@ -434,13 +430,6 @@ mod tests {
|
|||||||
assert_eq!(result, Starttls::Always);
|
assert_eq!(result, Starttls::Always);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn startls_deserialize_from_string_opportunistic() {
|
|
||||||
let json = r#""opportunistic""#;
|
|
||||||
let result: Starttls = serde_json::from_str(json).unwrap();
|
|
||||||
assert_eq!(result, Starttls::Opportunistic);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn startls_deserialize_from_bool() {
|
fn startls_deserialize_from_bool() {
|
||||||
let json = "true";
|
let json = "true";
|
||||||
@@ -482,18 +471,6 @@ mod tests {
|
|||||||
assert_eq!(Starttls::try_from("Yes").unwrap(), Starttls::Always);
|
assert_eq!(Starttls::try_from("Yes").unwrap(), Starttls::Always);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn startls_try_from_str_opportunistic() {
|
|
||||||
assert_eq!(
|
|
||||||
Starttls::try_from("opportunistic").unwrap(),
|
|
||||||
Starttls::Opportunistic
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Starttls::try_from("OPPORTUNISTIC").unwrap(),
|
|
||||||
Starttls::Opportunistic
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn startls_try_from_str_invalid() {
|
fn startls_try_from_str_invalid() {
|
||||||
let result = Starttls::try_from("invalid");
|
let result = Starttls::try_from("invalid");
|
||||||
@@ -517,14 +494,6 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn startls_try_from_string_opportunistic() {
|
|
||||||
assert_eq!(
|
|
||||||
Starttls::try_from("opportunistic".to_string()).unwrap(),
|
|
||||||
Starttls::Opportunistic
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn startls_try_from_string_invalid() {
|
fn startls_try_from_string_invalid() {
|
||||||
let result = Starttls::try_from("invalid".to_string());
|
let result = Starttls::try_from("invalid".to_string());
|
||||||
@@ -553,12 +522,6 @@ mod tests {
|
|||||||
assert_eq!(startls.to_string(), "always");
|
assert_eq!(startls.to_string(), "always");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn startls_display_opportunistic() {
|
|
||||||
let startls = Starttls::Opportunistic;
|
|
||||||
assert_eq!(startls.to_string(), "opportunistic");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rate_limit_settings_default() {
|
fn rate_limit_settings_default() {
|
||||||
let settings = RateLimitSettings::default();
|
let settings = RateLimitSettings::default();
|
||||||
|
|||||||
Reference in New Issue
Block a user