Remove Smtp from type names
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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())),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user