Update to rust master

This commit is contained in:
Alexis Mousset
2014-02-10 16:40:20 +01:00
parent 0646476a9c
commit c81117921c
5 changed files with 86 additions and 43 deletions

View File

@@ -5,5 +5,5 @@ use smtp::client::SmtpClient;
fn main() {
let mut email_client: SmtpClient = SmtpClient::new("localhost", None, None);
email_client.send_mail("user@example.org", [&"user@localhost"], "plop");
email_client.send_mail("moostik@minet.net", [&"moostik@localhost"], "plop");
}

View File

@@ -1,3 +0,0 @@
[Dolphin]
Timestamp=2014,2,3,2,12,31
Version=3

View File

@@ -27,7 +27,7 @@ use std::str::from_utf8;
use std::io::net::ip::{SocketAddr, Port};
use std::io::net::tcp::TcpStream;
use std::io::net::addrinfo::get_host_addresses;
use common::SMTP_PORT;
use common::{SMTP_PORT, CRLF};
use commands::SmtpCommand;
/// Contains an SMTP reply, with separed code and message
@@ -63,13 +63,16 @@ impl SmtpClient {
/// Connect to the configured server
pub fn connect(&mut self) -> SmtpResponse {
let ips = get_host_addresses(self.host.clone());
let ip = ips.expect(format!("Cannot resolve {}", self.host))[0];
let ip = match get_host_addresses(self.host.clone()) {
Ok(ip_vector) => ip_vector[0],
Err(error) => fail!("Cannot resolve {}", self.host)
};
match TcpStream::connect(SocketAddr{ip: ip, port: self.port}) {
None => fail!("Cannot connect to {}:{}", self.host, self.port),
Some(s) => self.socket = Some(s)
}
self.socket = match TcpStream::connect(SocketAddr{ip: ip, port: self.port}) {
Err(error) => fail!("Cannot connect to {}:{}", self.host, self.port),
Ok(socket) => Some(socket)
};
match self.get_reply() {
None => fail!("No banner on {}", self.host),
@@ -79,11 +82,19 @@ impl SmtpClient {
/// Send an SMTP command
pub fn send_command(&mut self, command: ~str, option: Option<~str>) -> SmtpResponse {
self.send_and_get_response(SmtpCommand::new(command, option).get_formatted_command())
}
self.send(SmtpCommand::new(command, option).get_formatted_command());
let response = self.get_reply();
/// Send an email
pub fn send_message(&mut self, message: ~str) -> SmtpResponse {
self.send_and_get_response(format!("{}{}.", message, CRLF))
}
match response {
/// Send a complete message or a command to the server and get the response
fn send_and_get_response(&mut self, string: ~str) -> SmtpResponse {
self.send(format!("{}{}", string, CRLF));
match self.get_reply() {
None => fail!("No answer on {}", self.host),
Some(response) => response
}
@@ -91,25 +102,32 @@ impl SmtpClient {
/// Send a string on the client socket
fn send(&mut self, string: ~str) {
self.socket.write_str(string);
self.socket.clone().unwrap().write_str(string);
debug!("{:s}", string);
}
/// Read a string from the client socket
fn read(&mut self) -> ~str {
self.buf = [0u8, ..1000];
let response = match self.socket.clone().unwrap().read(self.buf) {
Err(error) => fail!("Read error"),
Ok(bytes_read) => from_utf8(self.buf.slice_to(bytes_read - 1)).unwrap()
};
debug!("{:s}", response);
return response.to_owned();
}
/// Get the SMTP response
fn get_reply(&mut self) -> Option<SmtpResponse> {
self.buf = [0u8, ..1000];
let response = match self.socket.read(self.buf) {
None => fail!("Read error"),
Some(bytes_read) => self.buf.slice_to(bytes_read - 1)
};
debug!("{:s}", from_utf8(response).unwrap());
let response = self.read();
if response.len() > 4 {
Some(SmtpResponse {
code: from_str(from_utf8(response.slice_to(3)).unwrap()).unwrap(),
message: from_utf8(response.slice_from(4)).unwrap().to_owned()
code: from_str(response.slice_to(3)).unwrap(),
message: response.slice_from(4).to_owned()
})
} else {
None
@@ -130,15 +148,14 @@ impl SmtpClient {
/// Send an email
pub fn send_mail(&mut self, from_addr: &str, to_addrs: &[&str], message: &str) {
let my_hostname = self.my_hostname.clone();
self.connect();
self.send_command(~"HELO", Some(my_hostname));
self.send_command(~"MAIL", Some(from_addr.to_owned()));
let mut server_response: SmtpResponse = self.connect();
server_response = self.send_command(~"HELO", Some(my_hostname));
server_response= self.send_command(~"MAIL", Some(from_addr.to_owned()));
for &to_addr in to_addrs.iter() {
self.send_command(~"RCPT", Some(to_addr.to_owned()));
server_response = self.send_command(~"RCPT", Some(to_addr.to_owned()));
}
self.send_command(~"DATA", None);
self.send(message.to_owned());
self.send(~"\r\n.\r\n");
self.send_command(~"QUIT", None);
server_response = self.send_command(~"DATA", None);
server_response = self.send_message(message.to_owned());
server_response = self.send_command(~"QUIT", None);
}
}

View File

@@ -5,7 +5,7 @@
*/
use std::fmt;
use common::CRLF;
use std::io;
/*
* HELO <SP> <domain> <CRLF>
@@ -139,10 +139,10 @@ impl FromStr for Command {
}
}
impl fmt::Default for Command {
impl fmt::Show for Command {
/// Format SMTP command display
fn fmt(s: &Command, f: &mut fmt::Formatter) {
f.buf.write(match *s {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), io::IoError> {
f.buf.write(match *self {
Ehello => "EHLO".as_bytes(),
Hello => "HELO".as_bytes(),
Mail => "MAIL FROM:".as_bytes(),
@@ -186,8 +186,8 @@ impl SmtpCommand {
/// Return the formatted command, ready to be used in an SMTP session.
pub fn get_formatted_command(&self) -> ~str {
match (self.command.takes_argument(), self.command.needs_argument(), self.argument.clone()) {
(true, _, Some(argument)) => format!("{} {}{}", self.command, argument, CRLF),
(_, false, None) => format!("{}{}", self.command, CRLF),
(true, _, Some(argument)) => format!("{} {}", self.command, argument),
(_, false, None) => format!("{}", self.command),
_ => fail!("Wrong SMTP syntax")
}
}
@@ -206,11 +206,11 @@ mod test {
#[test]
fn test_get_simple_command() {
assert!(SmtpCommand::new(~"TURN", None).get_formatted_command() == format!("TURN{}", ::common::CRLF));
assert!(SmtpCommand::new(~"TURN", None).get_formatted_command() == ~"TURN");
}
#[test]
fn test_get_argument_command() {
assert!(SmtpCommand::new(~"EHLO", Some(~"example.example")).get_formatted_command() == format!("EHLO example.example{}", ::common::CRLF));
assert!(SmtpCommand::new(~"EHLO", Some(~"example.example")).get_formatted_command() == ~"EHLO example.example");
}
}

View File

@@ -1,5 +1,7 @@
/*!
/*!
* Common definitions for SMTP
*
* Needs to be organized later.
*/
use std::io::net::ip::Port;
@@ -14,5 +16,32 @@ pub static CRLF: &'static str = "\r\n";
/// Add quotes to emails
pub fn quote_email_address(addr: &str) -> ~str {
return format!("<{:s}>", addr).to_owned();
match (addr.slice_to(1), addr.slice_from(addr.len()-1)) {
("<", ">") => addr.to_owned(),
_ => format!("<{:s}>", addr)
}
}
/// Remove quotes from emails
pub fn unquote_email_address(addr: &str) -> ~str {
match (addr.slice_to(1), addr.slice_from(addr.len() - 1)) {
("<", ">") => addr.slice(1, addr.len() - 1).to_owned(),
_ => addr.to_owned()
}
}
#[cfg(test)]
mod test {
#[test]
fn test_quote_email_address() {
assert!(super::quote_email_address("plop") == ~"<plop>");
assert!(super::quote_email_address("<plop>") == ~"<plop>");
}
#[test]
fn test_unquote_email_address() {
assert!(super::unquote_email_address("<plop>") == ~"plop");
assert!(super::unquote_email_address("plop") == ~"plop");
}
}