Remove Smtp from type names

This commit is contained in:
Alexis Mousset
2014-10-19 15:07:18 +02:00
parent 3041a5fdba
commit 76d465ce8e
7 changed files with 124 additions and 124 deletions

View File

@@ -14,12 +14,12 @@ use std::io::net::tcp::TcpStream;
use std::string::String;
use std::io::net::ip::Port;
use std::os;
use smtp::client::SmtpClient;
use smtp::client::Client;
use getopts::{optopt,optflag,getopts,OptGroup,usage};
fn sendmail(source_address: String, recipient_addresses: Vec<String>, message: String, server: String, port: Option<Port>, my_hostname: Option<String>) {
let mut email_client: SmtpClient<TcpStream> =
SmtpClient::new(
let mut email_client: Client<TcpStream> =
Client::new(
server,
port,
my_hostname);

View File

@@ -17,21 +17,21 @@ use std::io::{IoResult, Reader, Writer};
use std::io::net::ip::Port;
use common::{get_first_word, unquote_email_address};
use response::SmtpResponse;
use response::Response;
use extension;
use command;
use command::SmtpCommand;
use command::Command;
use common::{SMTP_PORT, CRLF};
use transaction;
use transaction::TransactionState;
use client::connecter::Connecter;
use client::server_info::SmtpServerInfo;
use client::server_info::ServerInfo;
mod connecter;
mod server_info;
/// Structure that implements the SMTP client
pub struct SmtpClient<S> {
pub struct Client<S> {
/// TCP stream between client and server
/// Value is None before connection
stream: Option<S>,
@@ -43,15 +43,15 @@ pub struct SmtpClient<S> {
my_hostname: String,
/// Information about the server
/// Value is None before HELO/EHLO
server_info: Option<SmtpServerInfo>,
server_info: Option<ServerInfo>,
/// Transaction state, to check the sequence of commands
state: TransactionState
}
impl<S> SmtpClient<S> {
impl<S> Client<S> {
/// Creates a new SMTP client
pub fn new(host: String, port: Option<Port>, my_hostname: Option<String>) -> SmtpClient<S> {
SmtpClient{
pub fn new(host: String, port: Option<Port>, my_hostname: Option<String>) -> Client<S> {
Client{
stream: None,
host: host,
port: port.unwrap_or(SMTP_PORT),
@@ -63,20 +63,20 @@ impl<S> SmtpClient<S> {
}
// T : String ou String, selon le support
impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
impl<S: Connecter + Reader + Writer + Clone> Client<S> {
/// TODO
fn smtp_fail_if_err<S>(&mut self, response: Result<SmtpResponse, SmtpResponse>) {
fn smtp_fail_if_err<S>(&mut self, response: Result<Response, Response>) {
match response {
Err(response) => {
self.smtp_fail::<S, SmtpResponse>(response)
self.smtp_fail::<S, Response>(response)
},
Ok(_) => {}
}
}
/// Connects to the configured server
pub fn connect(&mut self) -> Result<SmtpResponse, SmtpResponse> {
pub fn connect(&mut self) -> Result<Response, Response> {
// connect should not be called when the client is already connected
if !self.stream.is_none() {
fail!("The connection is already established");
@@ -110,7 +110,7 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
pub fn send_mail<S>(&mut self, from_address: String,
to_addresses: Vec<String>, message: String) {
let my_hostname = self.my_hostname.clone();
let mut smtp_result: Result<SmtpResponse, SmtpResponse>;
let mut smtp_result: Result<Response, Response>;
match self.connect() {
Ok(_) => {},
@@ -122,12 +122,12 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
// Extended Hello or Hello
match self.ehlo::<S>(my_hostname.clone().to_string()) {
Err(SmtpResponse{code: 550, message: _}) => {
Err(Response{code: 550, message: _}) => {
smtp_result = self.helo::<S>(my_hostname.clone());
self.smtp_fail_if_err::<S>(smtp_result);
},
Err(response) => {
self.smtp_fail::<S, SmtpResponse>(response)
self.smtp_fail::<S, Response>(response)
}
_ => {}
}
@@ -165,7 +165,7 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
let sent = self.message::<S>(message);
if sent.clone().is_err() {
self.smtp_fail::<S, SmtpResponse>(sent.clone().err().unwrap())
self.smtp_fail::<S, Response>(sent.clone().err().unwrap())
}
info!("to=<{}>, status=sent ({})",
@@ -178,7 +178,7 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
/// Sends an SMTP command
// TODO : ensure this is an ASCII string
fn send_command(&mut self, command: SmtpCommand) -> SmtpResponse {
fn send_command(&mut self, command: Command) -> Response {
if !self.state.is_command_possible(command.clone()) {
fail!("Bad command sequence");
}
@@ -186,12 +186,12 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
}
/// Sends an email
fn send_message(&mut self, message: String) -> SmtpResponse {
fn send_message(&mut self, message: String) -> Response {
self.send_and_get_response(format!("{}{:s}.", message, CRLF).as_slice())
}
/// Sends a complete message or a command to the server and get the response
fn send_and_get_response(&mut self, string: &str) -> SmtpResponse {
fn send_and_get_response(&mut self, string: &str) -> Response {
match (&mut self.stream.clone().unwrap() as &mut Writer)
.write_str(format!("{:s}{:s}", string, CRLF).as_slice()) { // TODO improve this
Ok(..) => debug!("Wrote: {:s}", string),
@@ -205,12 +205,12 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
}
/// Gets the SMTP response
fn get_reply(&mut self) -> Option<SmtpResponse> {
fn get_reply(&mut self) -> Option<Response> {
let response = match self.read_to_string() {
Ok(string) => string,
Err(..) => fail!("No answer")
};
from_str::<SmtpResponse>(response.as_slice())
from_str::<Response>(response.as_slice())
}
/// Closes the connection and fail with a given messgage
@@ -242,11 +242,11 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
}
/// Send a HELO command
pub fn helo<S>(&mut self, my_hostname: String) -> Result<SmtpResponse, SmtpResponse> {
pub fn helo<S>(&mut self, my_hostname: String) -> Result<Response, Response> {
match self.send_command(command::Hello(my_hostname.clone())).with_code(vec!(250)) {
Ok(response) => {
self.server_info = Some(
SmtpServerInfo{
ServerInfo{
name: get_first_word(response.message.clone().unwrap()),
esmtp_features: None
}
@@ -259,13 +259,13 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
}
/// Sends a EHLO command
pub fn ehlo<S>(&mut self, my_hostname: String) -> Result<SmtpResponse, SmtpResponse> {
pub fn ehlo<S>(&mut self, my_hostname: String) -> Result<Response, Response> {
match self.send_command(command::ExtendedHello(my_hostname.clone())).with_code(vec!(250)) {
Ok(response) => {
self.server_info = Some(
SmtpServerInfo{
ServerInfo{
name: get_first_word(response.message.clone().unwrap()),
esmtp_features: SmtpServerInfo::parse_esmtp_response(
esmtp_features: ServerInfo::parse_esmtp_response(
response.message.clone().unwrap()
)
}
@@ -279,7 +279,7 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
/// Sends a MAIL command
pub fn mail<S>(&mut self, from_address: String,
options: Option<Vec<String>>) -> Result<SmtpResponse, SmtpResponse> {
options: Option<Vec<String>>) -> Result<Response, Response> {
match self.send_command(
command::Mail(unquote_email_address(from_address.to_string()), options)
).with_code(vec!(250)) {
@@ -295,7 +295,7 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
/// Sends a RCPT command
pub fn rcpt<S>(&mut self, to_address: String,
options: Option<Vec<String>>) -> Result<SmtpResponse, SmtpResponse> {
options: Option<Vec<String>>) -> Result<Response, Response> {
match self.send_command(
command::Recipient(unquote_email_address(to_address.to_string()), options)
).with_code(vec!(250)) {
@@ -310,7 +310,7 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
}
/// Sends a DATA command
pub fn data<S>(&mut self) -> Result<SmtpResponse, SmtpResponse> {
pub fn data<S>(&mut self) -> Result<Response, Response> {
match self.send_command(command::Data).with_code(vec!(354)) {
Ok(response) => {
self.state = transaction::DataSent;
@@ -323,7 +323,7 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
}
/// Sends the message content
pub fn message<S>(&mut self, message_content: String) -> Result<SmtpResponse, SmtpResponse> {
pub fn message<S>(&mut self, message_content: String) -> Result<Response, Response> {
match self.send_message(message_content).with_code(vec!(250)) {
Ok(response) => {
self.state = transaction::HelloSent;
@@ -336,7 +336,7 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
}
/// Sends a QUIT command
pub fn quit<S>(&mut self) -> Result<SmtpResponse, SmtpResponse> {
pub fn quit<S>(&mut self) -> Result<Response, Response> {
match self.send_command(command::Quit).with_code(vec!(221)) {
Ok(response) => {
Ok(response)
@@ -348,7 +348,7 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
}
/// Sends a RSET command
pub fn rset<S>(&mut self) -> Result<SmtpResponse, SmtpResponse> {
pub fn rset<S>(&mut self) -> Result<Response, Response> {
match self.send_command(command::Reset).with_code(vec!(250)) {
Ok(response) => {
if vec!(transaction::MailSent, transaction::RecipientSent,
@@ -364,17 +364,17 @@ impl<S: Connecter + Reader + Writer + Clone> SmtpClient<S> {
}
/// Sends a NOOP commands
pub fn noop<S>(&mut self) -> Result<SmtpResponse, SmtpResponse> {
pub fn noop<S>(&mut self) -> Result<Response, Response> {
self.send_command(command::Noop).with_code(vec!(250))
}
/// Sends a VRFY command
pub fn vrfy<S, T>(&mut self, to_address: String) -> Result<SmtpResponse, SmtpResponse> {
pub fn vrfy<S, T>(&mut self, to_address: String) -> Result<Response, Response> {
self.send_command(command::Verify(to_address, None)).with_code(vec!(250))
}
}
impl<S: Reader + Clone> Reader for SmtpClient<S> {
impl<S: Reader + Clone> Reader for Client<S> {
/// Reads a string from the client socket
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
self.stream.clone().unwrap().read(buf)
@@ -394,7 +394,7 @@ impl<S: Reader + Clone> Reader for SmtpClient<S> {
}
}
impl<S: Writer + Clone> Writer for SmtpClient<S> {
impl<S: Writer + Clone> Writer for Client<S> {
/// Sends a string on the client socket
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
self.stream.clone().unwrap().write(buf)

View File

@@ -12,20 +12,20 @@
use std::fmt;
use std::fmt::{Show, Formatter};
use extension::SmtpExtension;
use response::SmtpResponse;
use extension::Extension;
use response::Response;
use common::CRLF;
/// Information about an SMTP server
#[deriving(Clone)]
pub struct SmtpServerInfo {
pub struct ServerInfo {
/// Server name
pub name: String,
/// ESMTP features supported by the server
pub esmtp_features: Option<Vec<SmtpExtension>>
pub esmtp_features: Option<Vec<Extension>>
}
impl Show for SmtpServerInfo {
impl Show for ServerInfo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write(
format!("{} with {}",
@@ -39,16 +39,16 @@ impl Show for SmtpServerInfo {
}
}
impl SmtpServerInfo {
impl ServerInfo {
/// Parses supported ESMTP features
///
/// TODO: Improve parsing
pub fn parse_esmtp_response(message: String) -> Option<Vec<SmtpExtension>> {
pub fn parse_esmtp_response(message: String) -> Option<Vec<Extension>> {
let mut esmtp_features = Vec::new();
for line in message.as_slice().split_str(CRLF) {
match from_str::<SmtpResponse>(line) {
Some(SmtpResponse{code: 250, message: message}) => {
match from_str::<SmtpExtension>(message.unwrap().as_slice()) {
match from_str::<Response>(line) {
Some(Response{code: 250, message: message}) => {
match from_str::<Extension>(message.unwrap().as_slice()) {
Some(keyword) => esmtp_features.push(keyword),
None => ()
}
@@ -63,7 +63,7 @@ impl SmtpServerInfo {
}
/// Checks if the server supports an ESMTP feature
pub fn supports_feature(&self, keyword: SmtpExtension) -> Result<SmtpExtension, ()> {
pub fn supports_feature(&self, keyword: Extension) -> Result<Extension, ()> {
match self.esmtp_features.clone() {
Some(esmtp_features) => {
for feature in esmtp_features.iter() {
@@ -80,54 +80,54 @@ impl SmtpServerInfo {
#[cfg(test)]
mod test {
use super::SmtpServerInfo;
use super::ServerInfo;
use extension;
#[test]
fn test_smtp_server_info_fmt() {
assert_eq!(format!("{}", SmtpServerInfo{
fn test_fmt() {
assert_eq!(format!("{}", ServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime))
}), "name with [8BITMIME]".to_string());
assert_eq!(format!("{}", SmtpServerInfo{
assert_eq!(format!("{}", ServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime, extension::Size(42)))
}), "name with [8BITMIME, SIZE=42]".to_string());
assert_eq!(format!("{}", SmtpServerInfo{
assert_eq!(format!("{}", ServerInfo{
name: String::from_str("name"),
esmtp_features: None
}), "name with no supported features".to_string());
}
#[test]
fn test_smtp_server_info_parse_esmtp_response() {
assert_eq!(SmtpServerInfo::parse_esmtp_response(String::from_str("me\r\n250-8BITMIME\r\n250 SIZE 42")),
fn test_parse_esmtp_response() {
assert_eq!(ServerInfo::parse_esmtp_response(String::from_str("me\r\n250-8BITMIME\r\n250 SIZE 42")),
Some(vec!(extension::EightBitMime, extension::Size(42))));
assert_eq!(SmtpServerInfo::parse_esmtp_response(String::from_str("me\r\n250-8BITMIME\r\n250 UNKNON 42")),
assert_eq!(ServerInfo::parse_esmtp_response(String::from_str("me\r\n250-8BITMIME\r\n250 UNKNON 42")),
Some(vec!(extension::EightBitMime)));
assert_eq!(SmtpServerInfo::parse_esmtp_response(String::from_str("me\r\n250-9BITMIME\r\n250 SIZE a")),
assert_eq!(ServerInfo::parse_esmtp_response(String::from_str("me\r\n250-9BITMIME\r\n250 SIZE a")),
None);
assert_eq!(SmtpServerInfo::parse_esmtp_response(String::from_str("me\r\n250-SIZE 42\r\n250 SIZE 43")),
assert_eq!(ServerInfo::parse_esmtp_response(String::from_str("me\r\n250-SIZE 42\r\n250 SIZE 43")),
Some(vec!(extension::Size(42), extension::Size(43))));
assert_eq!(SmtpServerInfo::parse_esmtp_response(String::from_str("")),
assert_eq!(ServerInfo::parse_esmtp_response(String::from_str("")),
None);
}
#[test]
fn test_smtp_server_info_supports_feature() {
assert_eq!(SmtpServerInfo{
fn test_supports_feature() {
assert_eq!(ServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime))
}.supports_feature(extension::EightBitMime), Ok(extension::EightBitMime));
assert_eq!(SmtpServerInfo{
assert_eq!(ServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::Size(42), extension::EightBitMime))
}.supports_feature(extension::EightBitMime), Ok(extension::EightBitMime));
assert_eq!(SmtpServerInfo{
assert_eq!(ServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::Size(42), extension::EightBitMime))
}.supports_feature(extension::Size(0)), Ok(extension::Size(42)));
assert!(SmtpServerInfo{
assert!(ServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime))
}.supports_feature(extension::Size(42)).is_err());

View File

@@ -18,7 +18,7 @@ use std::fmt::{Show, Formatter, Result};
/// and must not be used by clients:
/// SEND, SOML, SAML, TURN
#[deriving(PartialEq,Eq,Clone)]
pub enum SmtpCommand {
pub enum Command {
/// A fake command to represent the connection step
Connect,
/// Extended Hello command
@@ -45,7 +45,7 @@ pub enum SmtpCommand {
Quit,
}
impl Show for SmtpCommand {
impl Show for Command {
fn fmt(&self, f: &mut Formatter) -> Result {
f.write(match *self {
Connect => "CONNECT".to_string(),
@@ -85,7 +85,7 @@ mod test {
use command;
#[test]
fn test_command_fmt() {
fn test_fmt() {
assert_eq!(format!("{}", command::Noop), "NOOP".to_string());
assert_eq!(
format!("{}", command::ExtendedHello("this".to_string())),

View File

@@ -16,7 +16,7 @@ use std::fmt::{Show, Formatter, Result};
/// Supported ESMTP keywords
#[deriving(PartialEq,Eq,Clone)]
pub enum SmtpExtension {
pub enum Extension {
/// 8BITMIME keyword
///
/// RFC 6152 : https://tools.ietf.org/html/rfc6152
@@ -31,7 +31,7 @@ pub enum SmtpExtension {
Size(uint)
}
impl Show for SmtpExtension {
impl Show for Extension {
fn fmt(&self, f: &mut Formatter) -> Result {
f.write(
match self {
@@ -43,8 +43,8 @@ impl Show for SmtpExtension {
}
}
impl FromStr for SmtpExtension {
fn from_str(s: &str) -> Option<SmtpExtension> {
impl FromStr for Extension {
fn from_str(s: &str) -> Option<Extension> {
let splitted : Vec<&str> = s.splitn(1, ' ').collect();
match splitted.len() {
1 => match splitted[0] {
@@ -61,9 +61,9 @@ impl FromStr for SmtpExtension {
}
}
impl SmtpExtension {
impl Extension {
/// Checks if the ESMTP keyword is the same
pub fn same_extension_as(&self, other: SmtpExtension) -> bool {
pub fn same_extension_as(&self, other: Extension) -> bool {
if *self == other {
return true;
}
@@ -77,10 +77,10 @@ impl SmtpExtension {
#[cfg(test)]
mod test {
use extension;
use extension::SmtpExtension;
use extension::Extension;
#[test]
fn test_extension_same_extension_as() {
fn test_same_extension_as() {
assert_eq!(extension::EightBitMime.same_extension_as(extension::EightBitMime), true);
assert_eq!(extension::Size(42).same_extension_as(extension::Size(42)), true);
assert_eq!(extension::Size(42).same_extension_as(extension::Size(43)), true);
@@ -88,18 +88,18 @@ mod test {
}
#[test]
fn test_extension_fmt() {
fn test_fmt() {
assert_eq!(format!("{}", extension::EightBitMime), "8BITMIME".to_string());
assert_eq!(format!("{}", extension::Size(42)), "SIZE=42".to_string());
}
#[test]
fn test_extension_from_str() {
assert_eq!(from_str::<SmtpExtension>("8BITMIME"), Some(extension::EightBitMime));
assert_eq!(from_str::<SmtpExtension>("SIZE 42"), Some(extension::Size(42)));
assert_eq!(from_str::<SmtpExtension>("SIZ 42"), None);
assert_eq!(from_str::<SmtpExtension>("SIZE 4a2"), None);
fn test_from_str() {
assert_eq!(from_str::<Extension>("8BITMIME"), Some(extension::EightBitMime));
assert_eq!(from_str::<Extension>("SIZE 42"), Some(extension::Size(42)));
assert_eq!(from_str::<Extension>("SIZ 42"), None);
assert_eq!(from_str::<Extension>("SIZE 4a2"), None);
// TODO: accept trailing spaces ?
assert_eq!(from_str::<SmtpExtension>("SIZE 42 "), None);
assert_eq!(from_str::<Extension>("SIZE 42 "), None);
}
}

View File

@@ -20,14 +20,14 @@ use std::result;
///
/// We do accept messages containing only a code, to comply with RFC5321
#[deriving(PartialEq,Eq,Clone)]
pub struct SmtpResponse {
pub struct Response {
/// Server response code
pub code: u16,
/// Server response string
pub message: Option<String>
}
impl Show for SmtpResponse {
impl Show for Response {
fn fmt(&self, f: &mut Formatter) -> Result {
f.write(
match self.clone().message {
@@ -39,15 +39,15 @@ impl Show for SmtpResponse {
}
// FromStr ?
impl FromStr for SmtpResponse {
fn from_str(s: &str) -> Option<SmtpResponse> {
impl FromStr for Response {
fn from_str(s: &str) -> Option<Response> {
// If the string is too short to be a response code
if s.len() < 3 {
None
// If we have only a code, with or without a trailing space
} else if s.len() == 3 || (s.len() == 4 && s.slice(3,4) == " ") {
match from_str::<u16>(s.slice_to(3)) {
Some(code) => Some(SmtpResponse{
Some(code) => Some(Response{
code: code,
message: None
}),
@@ -61,7 +61,7 @@ impl FromStr for SmtpResponse {
vec!(" ", "-").contains(&s.slice(3,4)),
(remove_trailing_crlf(s.slice_from(4).to_string()))
) {
(Some(code), true, message) => Some(SmtpResponse{
(Some(code), true, message) => Some(Response{
code: code,
message: Some(message)
}),
@@ -72,10 +72,10 @@ impl FromStr for SmtpResponse {
}
}
impl SmtpResponse {
impl Response {
/// Checks the presence of the response code in the array of expected codes.
pub fn with_code(&self,
expected_codes: Vec<u16>) -> result::Result<SmtpResponse,SmtpResponse> {
expected_codes: Vec<u16>) -> result::Result<Response,Response> {
let response = self.clone();
if expected_codes.contains(&self.code) {
Ok(response)
@@ -87,70 +87,70 @@ impl SmtpResponse {
#[cfg(test)]
mod test {
use response::SmtpResponse;
use response::Response;
#[test]
fn test_response_fmt() {
assert_eq!(format!("{}", SmtpResponse{code: 200, message: Some("message".to_string())}),
fn test_fmt() {
assert_eq!(format!("{}", Response{code: 200, message: Some("message".to_string())}),
"200 message".to_string());
}
#[test]
fn test_response_from_str() {
assert_eq!(from_str::<SmtpResponse>("200 response message"),
Some(SmtpResponse{
fn test_from_str() {
assert_eq!(from_str::<Response>("200 response message"),
Some(Response{
code: 200,
message: Some("response message".to_string())
})
);
assert_eq!(from_str::<SmtpResponse>("200-response message"),
Some(SmtpResponse{
assert_eq!(from_str::<Response>("200-response message"),
Some(Response{
code: 200,
message: Some("response message".to_string())
})
);
assert_eq!(from_str::<SmtpResponse>("200"),
Some(SmtpResponse{
assert_eq!(from_str::<Response>("200"),
Some(Response{
code: 200,
message: None
})
);
assert_eq!(from_str::<SmtpResponse>("200 "),
Some(SmtpResponse{
assert_eq!(from_str::<Response>("200 "),
Some(Response{
code: 200,
message: None
})
);
assert_eq!(from_str::<SmtpResponse>("200-response\r\nmessage"),
Some(SmtpResponse{
assert_eq!(from_str::<Response>("200-response\r\nmessage"),
Some(Response{
code: 200,
message: Some("response\r\nmessage".to_string())
})
);
assert_eq!(from_str::<SmtpResponse>("2000response message"), None);
assert_eq!(from_str::<SmtpResponse>("20a response message"), None);
assert_eq!(from_str::<SmtpResponse>("20 "), None);
assert_eq!(from_str::<SmtpResponse>("20"), None);
assert_eq!(from_str::<SmtpResponse>("2"), None);
assert_eq!(from_str::<SmtpResponse>(""), None);
assert_eq!(from_str::<Response>("2000response message"), None);
assert_eq!(from_str::<Response>("20a response message"), None);
assert_eq!(from_str::<Response>("20 "), None);
assert_eq!(from_str::<Response>("20"), None);
assert_eq!(from_str::<Response>("2"), None);
assert_eq!(from_str::<Response>(""), None);
}
#[test]
fn test_response_with_code() {
fn test_with_code() {
assert_eq!(
SmtpResponse{code: 200, message: Some("message".to_string())}.with_code(vec!(200)),
Ok(SmtpResponse{code: 200, message: Some("message".to_string())})
Response{code: 200, message: Some("message".to_string())}.with_code(vec!(200)),
Ok(Response{code: 200, message: Some("message".to_string())})
);
assert_eq!(
SmtpResponse{code: 400, message: Some("message".to_string())}.with_code(vec!(200)),
Err(SmtpResponse{code: 400, message: Some("message".to_string())})
Response{code: 400, message: Some("message".to_string())}.with_code(vec!(200)),
Err(Response{code: 400, message: Some("message".to_string())})
);
assert_eq!(
SmtpResponse{
Response{
code: 200,
message: Some("message".to_string())
}.with_code(vec!(200, 300)),
Ok(SmtpResponse{code: 200, message: Some("message".to_string())})
Ok(Response{code: 200, message: Some("message".to_string())})
);
}
}

View File

@@ -12,7 +12,7 @@
use std::fmt;
use std::fmt::{Show, Formatter};
use command;
use command::SmtpCommand;
use command::Command;
/// Contains the state of the current transaction
#[deriving(PartialEq,Eq,Clone)]
@@ -48,7 +48,7 @@ impl Show for TransactionState {
impl TransactionState {
/// bla bla
pub fn is_command_possible(&self, command: SmtpCommand) -> bool {
pub fn is_command_possible(&self, command: Command) -> bool {
match (*self, command) {
(Unconnected, command::Connect) => true,
(Unconnected, _) => false,
@@ -74,7 +74,7 @@ impl TransactionState {
}
/// a method
pub fn next_state(&mut self, command: SmtpCommand) -> Option<TransactionState> {
pub fn next_state(&mut self, command: Command) -> Option<TransactionState> {
match (*self, command) {
(Unconnected, command::Connect) => Some(Connected),
(Unconnected, _) => None,
@@ -105,7 +105,7 @@ mod test {
use command;
#[test]
fn test_transaction_state_is_command_possible() {
fn test_is_command_possible() {
assert!(!super::Unconnected.is_command_possible(command::Noop));
assert!(!super::DataSent.is_command_possible(command::Noop));
assert!(super::HelloSent.is_command_possible(command::Mail("".to_string(), None)));
@@ -113,7 +113,7 @@ mod test {
}
#[test]
fn test_super_next_state() {
fn test_next_state() {
assert_eq!(super::MailSent.next_state(command::Noop), Some(super::MailSent));
assert_eq!(super::HelloSent.next_state(command::Mail("".to_string(), None)),
Some(super::MailSent));