Merge pull request #155 from amousset/improve-variables
style(all): Fix LOGIN auth detection and improve response tests
This commit is contained in:
@@ -67,7 +67,7 @@ impl Display for ServerInfo {
|
||||
}
|
||||
|
||||
impl ServerInfo {
|
||||
/// Parses a response to create a `ServerInfo`
|
||||
/// Parses a EHLO response to create a `ServerInfo`
|
||||
pub fn from_response(response: &Response) -> Result<ServerInfo, Error> {
|
||||
let name = match response.first_word() {
|
||||
Some(name) => name,
|
||||
@@ -77,7 +77,6 @@ impl ServerInfo {
|
||||
let mut features: HashSet<Extension> = HashSet::new();
|
||||
|
||||
for line in response.message() {
|
||||
|
||||
let splitted: Vec<&str> = line.split_whitespace().collect();
|
||||
match splitted[0] {
|
||||
"8BITMIME" => {
|
||||
@@ -95,6 +94,9 @@ impl ServerInfo {
|
||||
"PLAIN" => {
|
||||
features.insert(Extension::Authentication(Mechanism::Plain));
|
||||
}
|
||||
"LOGIN" => {
|
||||
features.insert(Extension::Authentication(Mechanism::Login));
|
||||
}
|
||||
"CRAM-MD5" => {
|
||||
features.insert(Extension::Authentication(Mechanism::CramMd5));
|
||||
}
|
||||
|
||||
@@ -156,13 +156,13 @@ pub enum SecurityLevel {
|
||||
EncryptedWrapper,
|
||||
/// Only send an email on encrypted connection (with STARTTLS)
|
||||
///
|
||||
/// Recommended mode, prevents MITM when used with verified certificates.
|
||||
/// Default mode, prevents MITM when used with verified certificates.
|
||||
AlwaysEncrypt,
|
||||
/// Use TLS when available (with STARTTLS)
|
||||
///
|
||||
/// Default mode.
|
||||
/// Should be used when not possible to always encrypt the connection
|
||||
Opportunistic,
|
||||
/// Never use TLS
|
||||
/// Never use encryption
|
||||
NeverEncrypt,
|
||||
}
|
||||
|
||||
@@ -460,7 +460,7 @@ impl EmailTransport<SmtpResult> for SmtpTransport {
|
||||
// Login is obsolete so try it last
|
||||
vec![Mechanism::Plain, Mechanism::CramMd5, Mechanism::Login]
|
||||
} else {
|
||||
// If not encrypted, do not allow clear-text passwords
|
||||
// If not encrypted, do not allow clear-text passwords by default
|
||||
vec![Mechanism::CramMd5]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +150,10 @@ impl FromStr for Code {
|
||||
impl Code {
|
||||
/// Creates a new `Code` structure
|
||||
pub fn new(severity: Severity, category: Category, detail: u8) -> Code {
|
||||
if detail > 9 {
|
||||
panic!("The detail code must be between 0 and 9");
|
||||
}
|
||||
|
||||
Code {
|
||||
severity: severity,
|
||||
category: category,
|
||||
@@ -174,7 +178,7 @@ impl ResponseParser {
|
||||
|
||||
if line.len() < 3 {
|
||||
return Err(Error::ResponseParsing(
|
||||
"Wrong code length (should be 3 digit)",
|
||||
"Incorrect response code (should be 3 digits)",
|
||||
));
|
||||
}
|
||||
|
||||
@@ -283,13 +287,9 @@ impl Response {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns only the line word of the message if possible
|
||||
/// Returns only the line of the message if possible
|
||||
pub fn first_line(&self) -> Option<&str> {
|
||||
if self.message.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(&self.message[0])
|
||||
}
|
||||
self.message.first().map(String::as_str)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,6 +308,7 @@ mod test {
|
||||
Severity::TransientNegativeCompletion
|
||||
);
|
||||
assert!("1".parse::<Severity>().is_err());
|
||||
assert!("51".parse::<Severity>().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -343,6 +344,16 @@ mod test {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_code_new_panic() {
|
||||
let _ = Code::new(
|
||||
Severity::TransientNegativeCompletion,
|
||||
Category::Connections,
|
||||
11,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_code_from_str() {
|
||||
assert_eq!(
|
||||
@@ -353,6 +364,12 @@ mod test {
|
||||
detail: 1,
|
||||
}
|
||||
);
|
||||
assert!("2222".parse::<Code>().is_err());
|
||||
assert!("aaa".parse::<Code>().is_err());
|
||||
assert!("-32".parse::<Code>().is_err());
|
||||
assert!("-333".parse::<Code>().is_err());
|
||||
assert!("".parse::<Code>().is_err());
|
||||
assert!("292".parse::<Code>().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -707,4 +724,82 @@ mod test {
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_response_first_line() {
|
||||
assert_eq!(
|
||||
Response::new(
|
||||
Code {
|
||||
severity: "2".parse::<Severity>().unwrap(),
|
||||
category: "4".parse::<Category>().unwrap(),
|
||||
detail: 1,
|
||||
},
|
||||
vec![
|
||||
"me".to_string(),
|
||||
"8BITMIME".to_string(),
|
||||
"SIZE 42".to_string(),
|
||||
],
|
||||
).first_line(),
|
||||
Some("me")
|
||||
);
|
||||
assert_eq!(
|
||||
Response::new(
|
||||
Code {
|
||||
severity: "2".parse::<Severity>().unwrap(),
|
||||
category: "4".parse::<Category>().unwrap(),
|
||||
detail: 1,
|
||||
},
|
||||
vec![
|
||||
"me mo".to_string(),
|
||||
"8BITMIME".to_string(),
|
||||
"SIZE 42".to_string(),
|
||||
],
|
||||
).first_line(),
|
||||
Some("me mo")
|
||||
);
|
||||
assert_eq!(
|
||||
Response::new(
|
||||
Code {
|
||||
severity: "2".parse::<Severity>().unwrap(),
|
||||
category: "4".parse::<Category>().unwrap(),
|
||||
detail: 1,
|
||||
},
|
||||
vec![],
|
||||
).first_line(),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
Response::new(
|
||||
Code {
|
||||
severity: "2".parse::<Severity>().unwrap(),
|
||||
category: "4".parse::<Category>().unwrap(),
|
||||
detail: 1,
|
||||
},
|
||||
vec![" ".to_string()],
|
||||
).first_line(),
|
||||
Some(" ")
|
||||
);
|
||||
assert_eq!(
|
||||
Response::new(
|
||||
Code {
|
||||
severity: "2".parse::<Severity>().unwrap(),
|
||||
category: "4".parse::<Category>().unwrap(),
|
||||
detail: 1,
|
||||
},
|
||||
vec![" ".to_string()],
|
||||
).first_line(),
|
||||
Some(" ")
|
||||
);
|
||||
assert_eq!(
|
||||
Response::new(
|
||||
Code {
|
||||
severity: "2".parse::<Severity>().unwrap(),
|
||||
category: "4".parse::<Category>().unwrap(),
|
||||
detail: 1,
|
||||
},
|
||||
vec!["".to_string()],
|
||||
).first_line(),
|
||||
Some("")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user