Refactoring

This commit is contained in:
Alexis Mousset
2015-07-14 22:07:05 +02:00
parent ef8c426cd4
commit e30e96c1ca
6 changed files with 56 additions and 125 deletions

View File

@@ -1,54 +0,0 @@
// Copyright 2014 Alexis Mousset. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Provides authentication functions
use serialize::base64::{self, ToBase64, FromBase64};
use serialize::hex::ToHex;
use crypto::hmac::Hmac;
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 {
format!("{}{}{}{}", NUL, username, NUL, password).as_bytes().to_base64(base64::STANDARD)
}
/// Returns a CRAM-MD5 mecanism response
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);
Ok(format!("{} {}", username, hmac.result().code().to_hex()).as_bytes().to_base64(base64::STANDARD))
}
#[cfg(test)]
mod test {
use super::{plain, cram_md5};
#[test]
fn test_plain() {
assert_eq!(plain("username", "password"), "AHVzZXJuYW1lAHBhc3N3b3Jk");
}
#[test]
fn test_cram_md5() {
assert_eq!(cram_md5("alice", "wonderland",
"PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg==").unwrap(),
"YWxpY2UgNjRiMmE0M2MxZjZlZDY4MDZhOTgwOTE0ZTIzZTc1ZjA=");
}
}

View File

@@ -15,8 +15,6 @@ use email_format::{MimeMessage, Header, Mailbox};
use time::{now, Tm};
use uuid::Uuid;
use sendable_email::SendableEmail;
/// Converts an adress or an address with an alias to a `Address`
pub trait ToHeader {
/// Converts to a `Header` struct
@@ -192,6 +190,58 @@ impl EmailBuilder {
}
}
/// Email sendable by an SMTP client
pub trait SendableEmail {
/// From address
fn from_address(&self) -> String;
/// To addresses
fn to_addresses(&self) -> Vec<String>;
/// Message content
fn message(&self) -> String;
/// Message ID
fn message_id(&self) -> String;
}
/// Minimal email structure
pub struct SimpleSendableEmail {
/// From address
from: String,
/// To addresses
to: Vec<String>,
/// Message
message: String,
}
impl SimpleSendableEmail {
/// Returns a new email
pub fn new(from_address: &str, to_address: &str, message: &str) -> SimpleSendableEmail {
SimpleSendableEmail {
from: from_address.to_string(),
to: vec![to_address.to_string()],
message: message.to_string(),
}
}
}
impl SendableEmail for SimpleSendableEmail {
fn from_address(&self) -> String {
self.from.clone()
}
fn to_addresses(&self) -> Vec<String> {
self.to.clone()
}
fn message(&self) -> String {
self.message.clone()
}
fn message_id(&self) -> String {
format!("<{}@rust-smtp>", Uuid::new_v4())
}
}
impl SendableEmail for Email {
/// Return the to addresses, and fails if it is not set
fn to_addresses(&self) -> Vec<String> {
@@ -225,8 +275,7 @@ mod test {
use uuid::Uuid;
use email_format::{MimeMessage, Header};
use sendable_email::SendableEmail;
use super::{EmailBuilder, Email};
use super::{SendableEmail, EmailBuilder, Email};
#[test]
fn test_email_display() {

View File

@@ -104,7 +104,7 @@
//!
//! ```rust,no_run
//! use smtp::sender::{Sender, SenderBuilder};
//! use smtp::sendable_email::SimpleSendableEmail;
//! use smtp::email::SimpleSendableEmail;
//!
//! // Create a minimal email
//! let email = SimpleSendableEmail::new(
@@ -153,9 +153,8 @@ pub mod client;
pub mod sender;
pub mod response;
pub mod error;
pub mod sendable_email;
pub mod email;
pub mod authentication;
pub mod email;
// Registrated port numbers:
// https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml

View File

@@ -1,63 +0,0 @@
// Copyright 2014 Alexis Mousset. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! SMTP sendable email
use uuid::Uuid;
/// Email sendable by an SMTP client
pub trait SendableEmail {
/// From address
fn from_address(&self) -> String;
/// To addresses
fn to_addresses(&self) -> Vec<String>;
/// Message content
fn message(&self) -> String;
/// Message ID
fn message_id(&self) -> String;
}
/// Minimal email structure
pub struct SimpleSendableEmail {
/// From address
from: String,
/// To addresses
to: Vec<String>,
/// Message
message: String,
}
impl SimpleSendableEmail {
/// Returns a new email
pub fn new(from_address: &str, to_address: &str, message: &str) -> SimpleSendableEmail {
SimpleSendableEmail {
from: from_address.to_string(),
to: vec![to_address.to_string()],
message: message.to_string(),
}
}
}
impl SendableEmail for SimpleSendableEmail {
fn from_address(&self) -> String {
self.from.clone()
}
fn to_addresses(&self) -> Vec<String> {
self.to.clone()
}
fn message(&self) -> String {
self.message.clone()
}
fn message_id(&self) -> String {
format!("<{}@rust-smtp>", Uuid::new_v4())
}
}

View File

@@ -15,7 +15,7 @@ use std::net::{SocketAddr, ToSocketAddrs};
use SMTP_PORT;
use extension::{Extension, ServerInfo};
use error::{SmtpResult, Error};
use sendable_email::SendableEmail;
use email::SendableEmail;
use client::Client;
use client::net::SmtpStream;
use authentication::Mecanism;