Error management for authentication
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
|
||||
name = "smtp"
|
||||
version = "0.0.13"
|
||||
version = "0.0.15"
|
||||
description = "Simple SMTP client"
|
||||
readme = "README.md"
|
||||
documentation = "http://amousset.github.io/rust-smtp/smtp/"
|
||||
|
||||
@@ -16,6 +16,7 @@ use crypto::md5::Md5;
|
||||
use crypto::mac::Mac;
|
||||
|
||||
use NUL;
|
||||
use error::Error;
|
||||
|
||||
/// Returns a PLAIN mecanism response
|
||||
pub fn plain(username: &str, password: &str) -> String {
|
||||
@@ -23,14 +24,16 @@ pub fn plain(username: &str, password: &str) -> String {
|
||||
}
|
||||
|
||||
/// Returns a CRAM-MD5 mecanism response
|
||||
pub fn cram_md5(username: &str, password: &str, encoded_challenge: &str) -> String {
|
||||
// TODO manage errors
|
||||
let challenge = encoded_challenge.from_base64().unwrap();
|
||||
pub fn cram_md5(username: &str, password: &str, encoded_challenge: &str) -> Result<String, Error> {
|
||||
let challenge = match encoded_challenge.from_base64() {
|
||||
Ok(challenge) => challenge,
|
||||
Err(error) => return Err(Error::ChallengeParsingError(error)),
|
||||
};
|
||||
|
||||
let mut hmac = Hmac::new(Md5::new(), password.as_bytes());
|
||||
hmac.input(&challenge);
|
||||
|
||||
format!("{} {}", username, hmac.result().code().to_hex()).as_bytes().to_base64(base64::STANDARD)
|
||||
Ok(format!("{} {}", username, hmac.result().code().to_hex()).as_bytes().to_base64(base64::STANDARD))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -45,7 +48,7 @@ mod test {
|
||||
#[test]
|
||||
fn test_cram_md5() {
|
||||
assert_eq!(cram_md5("alice", "wonderland",
|
||||
"PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg=="),
|
||||
"PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg==").unwrap(),
|
||||
"YWxpY2UgNjRiMmE0M2MxZjZlZDY4MDZhOTgwOTE0ZTIzZTc1ZjA=");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ use std::io::{BufRead, Read, Write};
|
||||
use bufstream::BufStream;
|
||||
|
||||
use response::ResponseParser;
|
||||
use error::SmtpResult;
|
||||
use error::{Error, SmtpResult};
|
||||
use client::net::{Connector, SmtpStream};
|
||||
use client::authentication::{plain, cram_md5};
|
||||
use {CRLF, MESSAGE_ENDING};
|
||||
@@ -175,8 +175,14 @@ impl<S: Connector + Write + Read = SmtpStream> Client<S> {
|
||||
|
||||
/// Sends an AUTH command with CRAM-MD5 mecanism
|
||||
pub fn auth_cram_md5(&mut self, username: &str, password: &str) -> SmtpResult {
|
||||
let encoded_challenge = try!(self.command("AUTH CRAM-MD5")).first_word().expect("No challenge");
|
||||
self.command(&format!("AUTH CRAM-MD5 {}", cram_md5(username, password, &encoded_challenge)))
|
||||
let encoded_challenge = match try!(self.command("AUTH CRAM-MD5")).first_word() {
|
||||
Some(challenge) => challenge,
|
||||
None => return Err(Error::ResponseParsingError("Could not read CRAM challenge")),
|
||||
};
|
||||
|
||||
let cram_response = try!(cram_md5(username, password, &encoded_challenge));
|
||||
|
||||
self.command(&format!("AUTH CRAM-MD5 {}", cram_response))
|
||||
}
|
||||
|
||||
/// Sends the message content
|
||||
|
||||
@@ -103,11 +103,10 @@ impl EmailBuilder {
|
||||
message_id: current_message,
|
||||
};
|
||||
|
||||
email.message.headers.insert(
|
||||
Header::new_with_value("Message-ID".to_string(),
|
||||
format!("<{}@rust-smtp>", current_message)
|
||||
).unwrap()
|
||||
);
|
||||
match Header::new_with_value("Message-ID".to_string(), format!("<{}@rust-smtp>", current_message)) {
|
||||
Ok(header) => email.message.headers.insert(header),
|
||||
Err(_) => (),
|
||||
}
|
||||
|
||||
EmailBuilder {
|
||||
content: email,
|
||||
|
||||
@@ -15,6 +15,7 @@ use std::fmt::{Display, Formatter};
|
||||
use std::fmt;
|
||||
|
||||
use response::{Severity, Response};
|
||||
use serialize::base64::FromBase64Error;
|
||||
use self::Error::*;
|
||||
|
||||
/// An enum of all error kinds.
|
||||
@@ -30,6 +31,8 @@ pub enum Error {
|
||||
PermanentError(Response),
|
||||
/// Error parsing a response
|
||||
ResponseParsingError(&'static str),
|
||||
/// Error parsing a base64 string in response
|
||||
ChallengeParsingError(FromBase64Error),
|
||||
/// Internal client error
|
||||
ClientError(&'static str),
|
||||
/// DNS resolution error
|
||||
@@ -50,6 +53,7 @@ impl StdError for Error {
|
||||
TransientError(_) => "a transient error occured during the SMTP transaction",
|
||||
PermanentError(_) => "a permanent error occured during the SMTP transaction",
|
||||
ResponseParsingError(_) => "an error occured while parsing an SMTP response",
|
||||
ChallengeParsingError(_) => "an error occured while parsing a CRAM-MD5 challenge",
|
||||
ResolutionError => "Could no resolve hostname",
|
||||
ClientError(_) => "an unknown error occured",
|
||||
IoError(_) => "an I/O error occured",
|
||||
|
||||
Reference in New Issue
Block a user