style(all): Fix LOGIN auth detection and improve response tests

This commit is contained in:
Alexis Mousset
2017-06-17 16:05:59 +02:00
parent 7eb0828bca
commit c5034324d2
3 changed files with 110 additions and 13 deletions

View File

@@ -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));
}

View File

@@ -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]
}
}

View File

@@ -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("")
);
}
}