Use a separate file for SmtpServerInfo

This commit is contained in:
Alexis Mousset
2014-10-19 04:37:13 +02:00
parent 9fd5317b6c
commit da33c0eb39
2 changed files with 138 additions and 121 deletions

View File

@@ -9,8 +9,7 @@
//! SMTP client
use std::fmt;
use std::fmt::{Show, Formatter};
use std::fmt::Show;
use std::str::from_utf8;
use std::result::Result;
use std::string::String;
@@ -20,77 +19,16 @@ use std::io::net::ip::Port;
use common::{get_first_word, unquote_email_address};
use response::SmtpResponse;
use extension;
use extension::SmtpExtension;
use command;
use command::SmtpCommand;
use common::{SMTP_PORT, CRLF};
use transaction;
use transaction::TransactionState;
use client::connecter::Connecter;
use client::server_info::SmtpServerInfo;
mod connecter;
/// Information about an SMTP server
#[deriving(Clone)]
struct SmtpServerInfo {
/// Server name
name: String,
/// ESMTP features supported by the server
esmtp_features: Option<Vec<SmtpExtension>>
}
impl Show for SmtpServerInfo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write(
format!("{} with {}",
self.name,
match self.esmtp_features.clone() {
Some(features) => features.to_string(),
None => format!("no supported features")
}
).as_bytes()
)
}
}
impl SmtpServerInfo {
/// Parses supported ESMTP features
///
/// TODO: Improve parsing
fn parse_esmtp_response(message: String) -> Option<Vec<SmtpExtension>> {
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()) {
Some(keyword) => esmtp_features.push(keyword),
None => ()
}
},
_ => ()
}
}
match esmtp_features.len() {
0 => None,
_ => Some(esmtp_features)
}
}
/// Checks if the server supports an ESMTP feature
fn supports_feature(&self, keyword: SmtpExtension) -> Result<SmtpExtension, ()> {
match self.esmtp_features.clone() {
Some(esmtp_features) => {
for feature in esmtp_features.iter() {
if keyword.same_extension_as(*feature) {
return Ok(*feature);
}
}
Err({})
},
None => Err({})
}
}
}
mod server_info;
/// Structure that implements the SMTP client
pub struct SmtpClient<S> {
@@ -455,59 +393,3 @@ impl<S: Writer + Clone> Writer for SmtpClient<S> {
self.stream.clone().unwrap().write_str(string)
}
}
#[cfg(test)]
mod test {
use super::SmtpServerInfo;
use extension;
#[test]
fn test_smtp_server_info_fmt() {
assert_eq!(format!("{}", SmtpServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime))
}), "name with [8BITMIME]".to_string());
assert_eq!(format!("{}", SmtpServerInfo{
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{
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")),
Some(vec!(extension::EightBitMime, extension::Size(42))));
assert_eq!(SmtpServerInfo::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")),
None);
assert_eq!(SmtpServerInfo::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("")),
None);
}
#[test]
fn test_smtp_server_info_supports_feature() {
assert_eq!(SmtpServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime))
}.supports_feature(extension::EightBitMime), Ok(extension::EightBitMime));
assert_eq!(SmtpServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::Size(42), extension::EightBitMime))
}.supports_feature(extension::EightBitMime), Ok(extension::EightBitMime));
assert_eq!(SmtpServerInfo{
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{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime))
}.supports_feature(extension::Size(42)).is_err());
}
}

135
src/client/server_info.rs Normal file
View File

@@ -0,0 +1,135 @@
// 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.
//! TODO
use std::fmt;
use std::fmt::{Show, Formatter};
use extension::SmtpExtension;
use response::SmtpResponse;
use common::CRLF;
/// Information about an SMTP server
#[deriving(Clone)]
pub struct SmtpServerInfo {
/// Server name
pub name: String,
/// ESMTP features supported by the server
pub esmtp_features: Option<Vec<SmtpExtension>>
}
impl Show for SmtpServerInfo {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.write(
format!("{} with {}",
self.name,
match self.esmtp_features.clone() {
Some(features) => features.to_string(),
None => format!("no supported features")
}
).as_bytes()
)
}
}
impl SmtpServerInfo {
/// Parses supported ESMTP features
///
/// TODO: Improve parsing
pub fn parse_esmtp_response(message: String) -> Option<Vec<SmtpExtension>> {
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()) {
Some(keyword) => esmtp_features.push(keyword),
None => ()
}
},
_ => ()
}
}
match esmtp_features.len() {
0 => None,
_ => Some(esmtp_features)
}
}
/// Checks if the server supports an ESMTP feature
pub fn supports_feature(&self, keyword: SmtpExtension) -> Result<SmtpExtension, ()> {
match self.esmtp_features.clone() {
Some(esmtp_features) => {
for feature in esmtp_features.iter() {
if keyword.same_extension_as(*feature) {
return Ok(*feature);
}
}
Err({})
},
None => Err({})
}
}
}
#[cfg(test)]
mod test {
use super::SmtpServerInfo;
use extension;
#[test]
fn test_smtp_server_info_fmt() {
assert_eq!(format!("{}", SmtpServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime))
}), "name with [8BITMIME]".to_string());
assert_eq!(format!("{}", SmtpServerInfo{
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{
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")),
Some(vec!(extension::EightBitMime, extension::Size(42))));
assert_eq!(SmtpServerInfo::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")),
None);
assert_eq!(SmtpServerInfo::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("")),
None);
}
#[test]
fn test_smtp_server_info_supports_feature() {
assert_eq!(SmtpServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime))
}.supports_feature(extension::EightBitMime), Ok(extension::EightBitMime));
assert_eq!(SmtpServerInfo{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::Size(42), extension::EightBitMime))
}.supports_feature(extension::EightBitMime), Ok(extension::EightBitMime));
assert_eq!(SmtpServerInfo{
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{
name: String::from_str("name"),
esmtp_features: Some(vec!(extension::EightBitMime))
}.supports_feature(extension::Size(42)).is_err());
}
}