Follow master

This commit is contained in:
Alexis Mousset
2014-05-11 11:36:49 +02:00
parent 8974c6808d
commit 2e2e70a533
4 changed files with 53 additions and 55 deletions

View File

@@ -22,20 +22,20 @@ fn main() {
//! TODO: use parameters, flexible syntax
let args = os::args();
match args.len() {
6 => sendmail(args[1], args[2], args[3], args[4], args[5]),
6 => sendmail(args.get(1), args.get(2), args.get(3), args.get(4), args.get(5)),
_ => {
println!("Usage: {} source_address recipient_address message server port", args[0]);
println!("Usage: {} source_address recipient_address message server port", args.get(0));
return;
},
};
}
fn sendmail(source_address: &str, recipient_address: &str, message: &str, server: &str, port: &str) {
fn sendmail(source_address: &~str, recipient_address: &~str, message: &~str, server: &~str, port: &~str) {
let mut email_client: SmtpClient<StrBuf, TcpStream> =
SmtpClient::new(StrBuf::from_str(server), from_str::<Port>(port), None);
SmtpClient::new(StrBuf::from_str(*server), from_str::<Port>(*port), None);
email_client.send_mail(
StrBuf::from_str(source_address),
vec!(StrBuf::from_str(recipient_address)),
StrBuf::from_str(message)
StrBuf::from_str(*source_address),
vec!(StrBuf::from_str(*recipient_address)),
StrBuf::from_str(*message)
);
}

View File

@@ -59,21 +59,21 @@ impl FromStr for SmtpResponse<StrBuf> {
message: None
}),
None => None
}
// If we have a code and a message
} else {
match (
from_str::<uint>(s.slice_to(3)),
vec!(" ", "-").contains(&s.slice(3,4)),
remove_trailing_crlf(s.slice_from(4))
remove_trailing_crlf(StrBuf::from_str(s.slice_from(4)))
) {
(Some(code), true, message) => Some(SmtpResponse{
code: code,
message: Some(message)
}),
_ => None
}
}
}
@@ -120,7 +120,7 @@ impl<T: Str> SmtpServerInfo<T> {
/// TODO: Improve parsing
fn parse_esmtp_response(message: T) -> Option<Vec<EsmtpParameter>> {
let mut esmtp_features = Vec::new();
for line in message.into_owned().split_str(CRLF) {
for line in message.as_slice().split_str(CRLF) {
match from_str::<SmtpResponse<StrBuf>>(line) {
Some(SmtpResponse{code: 250, message: message}) => {
match from_str::<EsmtpParameter>(message.unwrap().into_owned()) {
@@ -235,17 +235,17 @@ impl SmtpClient<StrBuf, TcpStream> {
fail!("The connection is already established");
}
let ip = match get_host_addresses(self.host.clone().into_owned()) {
Ok(ip_vector) => ip_vector[0], // TODO : select a random ip
Ok(ip_vector) => *ip_vector.get(0), // TODO : select a random ip
Err(..) => fail!("Cannot resolve {:s}", self.host)
};
self.stream = match TcpStream::connect(SocketAddr{ip: ip, port: self.port}) {
Ok(stream) => Some(stream),
Err(..) => fail!("Cannot connect to {:s}:{:u}", self.host, self.port)
};
// Log the connection
info!("Connection established to {}[{}]:{}", self.my_hostname.clone(), ip, self.port);
match self.get_reply() {
Some(response) => match response.with_code(vec!(220)) {
Ok(response) => {
@@ -268,7 +268,7 @@ impl SmtpClient<StrBuf, TcpStream> {
match self.connect() {
Ok(_) => {},
Err(response) => fail!("Cannot connect to {:s}:{:u}. Server says: {}",
self.host,
self.host,
self.port, response
)
}
@@ -296,8 +296,7 @@ impl SmtpClient<StrBuf, TcpStream> {
// Mail
smtp_fail_if_err!(self.mail(from_address.clone(), None));
// Log the mail command
info!("from=<{}>, size={}, nrcpt={}", from_address, 42, to_addresses.len());
@@ -311,13 +310,13 @@ impl SmtpClient<StrBuf, TcpStream> {
// Data
smtp_fail_if_err!(self.data());
// Message content
// Message content
let sent = self.message(message);
if sent.clone().is_err() {
self.smtp_fail(sent.clone().err().unwrap())
}
info!("to=<{}>, status=sent ({})", to_addresses.clone().connect(">, to=<"), sent.clone().ok().unwrap());
// Quit
@@ -377,7 +376,7 @@ impl<S: Writer + Reader + Clone> SmtpClient<StrBuf, S> {
pub fn is_connected(&mut self) -> bool {
self.noop().is_ok()
}
/// Closes the TCP stream
pub fn close(&mut self) {
drop(self.stream.clone().unwrap());
@@ -386,12 +385,12 @@ impl<S: Writer + Reader + Clone> SmtpClient<StrBuf, S> {
/// Send a HELO command
pub fn helo(&mut self, my_hostname: StrBuf) -> Result<SmtpResponse<StrBuf>, SmtpResponse<StrBuf>> {
check_state_in!(vec!(Connected));
match self.send_command(commands::Hello(my_hostname.clone())).with_code(vec!(250)) {
Ok(response) => {
self.server_info = Some(
SmtpServerInfo{
name: get_first_word(response.message.clone().unwrap()),
name: get_first_word(response.message.clone().unwrap()),
esmtp_features: None
}
);
@@ -405,7 +404,7 @@ impl<S: Writer + Reader + Clone> SmtpClient<StrBuf, S> {
/// Sends a EHLO command
pub fn ehlo(&mut self, my_hostname: StrBuf) -> Result<SmtpResponse<StrBuf>, SmtpResponse<StrBuf>> {
check_state_not_in!(vec!(Unconnected));
match self.send_command(commands::ExtendedHello(my_hostname.clone())).with_code(vec!(250)) {
Ok(response) => {
self.server_info = Some(
@@ -424,7 +423,7 @@ impl<S: Writer + Reader + Clone> SmtpClient<StrBuf, S> {
/// Sends a MAIL command
pub fn mail(&mut self, from_address: StrBuf, options: Option<Vec<StrBuf>>) -> Result<SmtpResponse<StrBuf>, SmtpResponse<StrBuf>> {
check_state_in!(vec!(HeloSent));
match self.send_command(commands::Mail(unquote_email_address(from_address), options)).with_code(vec!(250)) {
Ok(response) => {
self.state = MailSent;
@@ -439,7 +438,7 @@ impl<S: Writer + Reader + Clone> SmtpClient<StrBuf, S> {
/// Sends a RCPT command
pub fn rcpt(&mut self, to_address: StrBuf, options: Option<Vec<StrBuf>>) -> Result<SmtpResponse<StrBuf>, SmtpResponse<StrBuf>> {
check_state_in!(vec!(MailSent, RcptSent));
match self.send_command(commands::Recipient(unquote_email_address(to_address), options)).with_code(vec!(250)) {
Ok(response) => {
self.state = RcptSent;
@@ -454,7 +453,7 @@ impl<S: Writer + Reader + Clone> SmtpClient<StrBuf, S> {
/// Sends a DATA command
pub fn data(&mut self) -> Result<SmtpResponse<StrBuf>, SmtpResponse<StrBuf>> {
check_state_in!(vec!(RcptSent));
match self.send_command(commands::Data).with_code(vec!(354)) {
Ok(response) => {
self.state = DataSent;
@@ -469,7 +468,7 @@ impl<S: Writer + Reader + Clone> SmtpClient<StrBuf, S> {
/// Sends the message content
pub fn message(&mut self, message_content: StrBuf) -> Result<SmtpResponse<StrBuf>, SmtpResponse<StrBuf>> {
check_state_in!(vec!(DataSent));
match self.send_message(message_content).with_code(vec!(250)) {
Ok(response) => {
self.state = HeloSent;
@@ -565,36 +564,36 @@ mod test {
fn test_smtp_response_fmt() {
assert_eq!(format!("{}", SmtpResponse{code: 200, message: Some("message")}), "200 message".to_owned());
}
#[test]
fn test_smtp_response_from_str() {
assert_eq!(from_str::<SmtpResponse<StrBuf>>("200 response message"),
Some(SmtpResponse{
code: 200,
code: 200,
message: Some(StrBuf::from_str("response message"))
})
);
assert_eq!(from_str::<SmtpResponse<StrBuf>>("200-response message"),
Some(SmtpResponse{
code: 200,
code: 200,
message: Some(StrBuf::from_str("response message"))
})
);
assert_eq!(from_str::<SmtpResponse<StrBuf>>("200"),
Some(SmtpResponse{
code: 200,
code: 200,
message: None
})
);
assert_eq!(from_str::<SmtpResponse<StrBuf>>("200 "),
Some(SmtpResponse{
code: 200,
code: 200,
message: None
})
);
assert_eq!(from_str::<SmtpResponse<StrBuf>>("200-response\r\nmessage"),
Some(SmtpResponse{
code: 200,
code: 200,
message: Some(StrBuf::from_str("response\r\nmessage"))
})
);
@@ -643,7 +642,7 @@ mod test {
assert_eq!(SmtpServerInfo::parse_esmtp_response("me\r\n250-SIZE 42\r\n250 SIZE 43"),
Some(vec!(commands::Size(42), commands::Size(43))));
}
#[test]
fn test_smtp_server_info_supports_feature() {
assert_eq!(SmtpServerInfo{

View File

@@ -106,13 +106,13 @@ impl Show for EsmtpParameter {
impl FromStr for EsmtpParameter {
fn from_str(s: &str) -> Option<EsmtpParameter> {
let splitted : ~[&str] = s.splitn(' ', 1).collect();
let splitted : Vec<&str> = s.splitn(' ', 1).collect();
match splitted.len() {
1 => match splitted[0] {
1 => match *splitted.get(0) {
"8BITMIME" => Some(EightBitMime),
_ => None
},
2 => match (splitted[0], from_str::<uint>(splitted[1])) {
2 => match (*splitted.get(0), from_str::<uint>(*splitted.get(1))) {
("SIZE", Some(size)) => Some(Size(size)),
_ => None
},

View File

@@ -17,7 +17,7 @@ pub static SP: &'static str = " ";
pub static CRLF: &'static str = "\r\n";
/// Adds quotes to emails if needed
pub fn quote_email_address<T: Str>(address: T) -> StrBuf {
pub fn quote_email_address(address: StrBuf) -> StrBuf {
match (address.as_slice().slice_to(1), address.as_slice().slice_from(address.as_slice().len()-1)) {
("<", ">") => address.into_strbuf(),
_ => StrBuf::from_str(format!("<{:s}>", address))
@@ -25,7 +25,7 @@ pub fn quote_email_address<T: Str>(address: T) -> StrBuf {
}
/// Removes quotes from emails if needed
pub fn unquote_email_address<T: Str>(address: T) -> StrBuf {
pub fn unquote_email_address(address: StrBuf) -> StrBuf {
match (address.as_slice().slice_to(1), address.as_slice().slice_from(address.as_slice().len() - 1)) {
("<", ">") => address.as_slice().slice(1, address.as_slice().len() - 1).into_strbuf(),
_ => address.into_strbuf()
@@ -33,7 +33,7 @@ pub fn unquote_email_address<T: Str>(address: T) -> StrBuf {
}
/// Removes the trailing line return at the end of a string
pub fn remove_trailing_crlf<T: Str>(string: T) -> StrBuf {
pub fn remove_trailing_crlf(string: StrBuf) -> StrBuf {
if string.as_slice().slice_from(string.as_slice().len() - 2) == CRLF {
StrBuf::from_str(string.as_slice().slice_to(string.as_slice().len() - 2))
} else if string.as_slice().slice_from(string.as_slice().len() - 1) == "\r" {
@@ -44,7 +44,7 @@ pub fn remove_trailing_crlf<T: Str>(string: T) -> StrBuf {
}
/// Returns the first word of a string, or the string if it contains no space
pub fn get_first_word<T: Str>(string: T) -> StrBuf {
pub fn get_first_word(string: StrBuf) -> StrBuf {
StrBuf::from_str(string.into_owned().split_str(CRLF).next().unwrap().splitn(' ', 1).next().unwrap())
}
@@ -52,30 +52,29 @@ pub fn get_first_word<T: Str>(string: T) -> StrBuf {
mod test {
#[test]
fn test_quote_email_address() {
assert_eq!(super::quote_email_address("plop"), StrBuf::from_str("<plop>"));
assert_eq!(super::quote_email_address("<plop>"), StrBuf::from_str("<plop>"));
assert_eq!(super::quote_email_address(StrBuf::from_str("plop")), StrBuf::from_str("<plop>"));
assert_eq!(super::quote_email_address(StrBuf::from_str("<plop>")), StrBuf::from_str("<plop>"));
}
#[test]
fn test_unquote_email_address() {
assert_eq!(super::unquote_email_address("<plop>"), StrBuf::from_str("plop"));
assert_eq!(super::unquote_email_address("plop"), StrBuf::from_str("plop"));
assert_eq!(super::unquote_email_address("<plop"), StrBuf::from_str("<plop"));
assert_eq!(super::unquote_email_address(StrBuf::from_str("<plop>")), StrBuf::from_str("plop"));
assert_eq!(super::unquote_email_address(StrBuf::from_str("plop")), StrBuf::from_str("plop"));
assert_eq!(super::unquote_email_address(StrBuf::from_str("<plop")), StrBuf::from_str("<plop"));
}
#[test]
fn test_remove_trailing_crlf() {
assert_eq!(super::remove_trailing_crlf("word"), StrBuf::from_str("word"));
assert_eq!(super::remove_trailing_crlf("word\r\n"), StrBuf::from_str("word"));
assert_eq!(super::remove_trailing_crlf("word\r\n "), StrBuf::from_str("word\r\n "));
assert_eq!(super::remove_trailing_crlf("word\r"), StrBuf::from_str("word"));
assert_eq!(super::remove_trailing_crlf(StrBuf::from_str("word")), StrBuf::from_str("word"));
assert_eq!(super::remove_trailing_crlf(StrBuf::from_str("word\r\n")), StrBuf::from_str("word"));
assert_eq!(super::remove_trailing_crlf(StrBuf::from_str("word\r\n ")), StrBuf::from_str("word\r\n "));
assert_eq!(super::remove_trailing_crlf(StrBuf::from_str("word\r")), StrBuf::from_str("word"));
}
#[test]
fn test_get_first_word() {
assert_eq!(super::get_first_word("first word"), StrBuf::from_str("first"));
assert_eq!(super::get_first_word("first word\r\ntest"), StrBuf::from_str("first"));
assert_eq!(super::get_first_word("first"), StrBuf::from_str("first"));
assert_eq!(super::get_first_word(StrBuf::from_str("first word")), StrBuf::from_str("first"));
assert_eq!(super::get_first_word(StrBuf::from_str("first word\r\ntest")), StrBuf::from_str("first"));
assert_eq!(super::get_first_word(StrBuf::from_str("first")), StrBuf::from_str("first"));
}
}