Start refactoring streams to introduce a mock server

This commit is contained in:
Alexis Mousset
2015-04-22 21:52:03 +02:00
parent 78e88d5bc6
commit ee8da8196a
5 changed files with 28 additions and 31 deletions

View File

@@ -28,7 +28,7 @@ fn main() {
.subject("Hello")
.build();
let mut sender: Sender<TcpStream> = SenderBuilder::localhost().hello_name("localhost")
let mut sender: Sender = SenderBuilder::localhost().hello_name("localhost")
.enable_connection_reuse(true).build();
for _ in (1..5) {

View File

@@ -10,17 +10,16 @@
//! SMTP client
use std::string::String;
use std::net::TcpStream;
use std::net::{SocketAddr, ToSocketAddrs};
use std::io::{BufRead, BufStream, Read, Write};
use response::{Response, Severity, Category};
use error::SmtpResult;
use client::connecter::Connecter;
use client::net::{Connector, SmtpStream};
use client::authentication::{plain, cram_md5};
use {CRLF, MESSAGE_ENDING};
pub mod connecter;
pub mod net;
mod authentication;
/// Returns the string after adding a dot at the beginning of each line starting with a dot
@@ -43,7 +42,7 @@ fn escape_crlf(string: &str) -> String {
}
/// Structure that implements the SMTP client
pub struct Client<S: Write + Read = TcpStream> {
pub struct Client<S: Write + Read = SmtpStream> {
/// TCP stream between client and server
/// Value is None before connection
stream: Option<BufStream<S>>,
@@ -58,7 +57,7 @@ macro_rules! return_err (
})
);
impl<S: Write + Read = TcpStream> Client<S> {
impl<S: Write + Read = SmtpStream> Client<S> {
/// Creates a new SMTP client
///
/// It does not connects to the server, but only creates the `Client`
@@ -70,7 +69,7 @@ impl<S: Write + Read = TcpStream> Client<S> {
}
}
impl<S: Connecter + Write + Read = TcpStream> Client<S> {
impl<S: Connector + Write + Read = SmtpStream> Client<S> {
/// Closes the SMTP transaction if possible
pub fn close(&mut self) {
let _ = self.quit();
@@ -85,7 +84,7 @@ impl<S: Connecter + Write + Read = TcpStream> Client<S> {
}
// Try to connect
self.stream = Some(BufStream::new(try!(Connecter::connect(&self.server_addr))));
self.stream = Some(BufStream::new(try!(Connector::connect(&self.server_addr))));
self.get_reply()
}
@@ -172,7 +171,7 @@ impl<S: Connecter + Write + Read = TcpStream> Client<S> {
self.command(&format!("AUTH CRAM-MD5 {}", cram_md5(username, password, &encoded_challenge)))
}
/// Sends the message content and close
/// Sends the message content
pub fn message(&mut self, message_content: &str) -> SmtpResult {
self.send_server(&escape_dot(message_content), MESSAGE_ENDING)
}

View File

@@ -7,20 +7,24 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A trait to represent a connected stream
//! A trait to represent a stream
use std::io;
use std::net::SocketAddr;
use std::net::TcpStream;
/// A trait for the concept of opening a stream
pub trait Connecter {
pub trait Connector {
/// Opens a connection to the given IP socket
fn connect(addr: &SocketAddr) -> io::Result<Self>;
}
impl Connecter for TcpStream {
fn connect(addr: &SocketAddr) -> io::Result<TcpStream> {
impl Connector for SmtpStream {
fn connect(addr: &SocketAddr) -> io::Result<SmtpStream> {
TcpStream::connect(addr)
}
}
/// Represents an atual SMTP network stream
//Used later for ssl
pub type SmtpStream = TcpStream;

View File

@@ -40,7 +40,6 @@
//! ```rust,no_run
//! use smtp::sender::{Sender, SenderBuilder};
//! use smtp::mailer::EmailBuilder;
//! use std::net::TcpStream;
//!
//! // Create an email
//! let email = EmailBuilder::new()
@@ -53,7 +52,7 @@
//! .build();
//!
//! // Open a local connection on port 25
//! let mut sender: Sender<TcpStream> = SenderBuilder::localhost().build();
//! let mut sender = SenderBuilder::localhost().build();
//! // Send the email
//! let result = sender.send(email);
//!
@@ -65,7 +64,6 @@
//! ```rust,no_run
//! use smtp::sender::{Sender, SenderBuilder};
//! use smtp::mailer::EmailBuilder;
//! use std::net::TcpStream;
//!
//! let mut builder = EmailBuilder::new();
//! builder = builder.to(("user@example.org", "Alias name"));
@@ -81,7 +79,7 @@
//! let email = builder.build();
//!
//! // Connect to a remote server on a custom port
//! let mut sender: Sender<TcpStream> = SenderBuilder::new(("server.tld", 10025))
//! let mut sender = SenderBuilder::new(("server.tld", 10025))
//! // Set the name sent during EHLO/HELO, default is `localhost`
//! .hello_name("my.hostname.tld")
//! // Add credentials for authentication
@@ -107,7 +105,6 @@
//! ```rust,no_run
//! use smtp::sender::{Sender, SenderBuilder};
//! use smtp::sendable_email::SimpleSendableEmail;
//! use std::net::TcpStream;
//!
//! // Create a minimal email
//! let email = SimpleSendableEmail::new(
@@ -116,7 +113,7 @@
//! "Hello world !"
//! );
//!
//! let mut sender: Sender<TcpStream> = SenderBuilder::localhost().build();
//! let mut sender = SenderBuilder::localhost().build();
//! let result = sender.send(email);
//! assert!(result.is_ok());
//! ```
@@ -127,10 +124,11 @@
//!
//! ```rust,no_run
//! use smtp::client::Client;
//! use smtp::client::net::SmtpStream;
//! use smtp::SMTP_PORT;
//! use std::net::TcpStream;
//!
//! let mut email_client: Client<TcpStream> = Client::new(("localhost", SMTP_PORT));
//! let mut email_client: Client<SmtpStream> = Client::new(("localhost", SMTP_PORT));
//! let _ = email_client.connect();
//! let _ = email_client.ehlo("my_hostname");
//! let _ = email_client.mail("user@example.com", None);

View File

@@ -10,9 +10,7 @@
//! Sends an email using the client
use std::string::String;
use std::net::TcpStream;
use std::net::{SocketAddr, ToSocketAddrs};
use std::io::{Read, Write};
use uuid::Uuid;
@@ -22,7 +20,7 @@ use error::{SmtpResult, SmtpError};
use sendable_email::SendableEmail;
use sender::server_info::ServerInfo;
use client::Client;
use client::connecter::Connecter;
use client::net::SmtpStream;
mod server_info;
@@ -87,7 +85,7 @@ impl SenderBuilder {
/// Build the SMTP client
///
/// It does not connects to the server, but only creates the `Sender`
pub fn build<S: Connecter + Read + Write>(self) -> Sender<S> {
pub fn build(self) -> Sender {
Sender::new(self)
}
}
@@ -102,7 +100,7 @@ struct State {
}
/// Structure that implements the high level SMTP client
pub struct Sender<S: Write + Read = TcpStream> {
pub struct Sender {
/// Information about the server
/// Value is None before HELO/EHLO
server_info: Option<ServerInfo>,
@@ -111,7 +109,7 @@ pub struct Sender<S: Write + Read = TcpStream> {
/// Information about the client
client_info: SenderBuilder,
/// Low level client
client: Client<S>,
client: Client<SmtpStream>,
}
macro_rules! try_smtp (
@@ -129,12 +127,12 @@ macro_rules! try_smtp (
})
);
impl<S: Write + Read = TcpStream> Sender<S> {
impl Sender {
/// Creates a new SMTP client
///
/// It does not connects to the server, but only creates the `Sender`
pub fn new(builder: SenderBuilder) -> Sender<S> {
let client: Client<S> = Client::new(builder.server_addr);
pub fn new(builder: SenderBuilder) -> Sender {
let client: Client<SmtpStream> = Client::new(builder.server_addr);
Sender{
client: client,
server_info: None,
@@ -145,9 +143,7 @@ impl<S: Write + Read = TcpStream> Sender<S> {
},
}
}
}
impl<S: Connecter + Write + Read = TcpStream> Sender<S> {
/// Reset the client state
fn reset(&mut self) {
// Close the SMTP transaction if needed