style(all): improve the code thanks to rust-clippy

This commit is contained in:
Alexis Mousset
2016-05-17 00:50:22 +02:00
parent 0acc57d36d
commit 97da0c0869
10 changed files with 67 additions and 154 deletions

View File

@@ -382,10 +382,9 @@ impl EmailBuilder {
let message_id = Uuid::new_v4();
match Header::new_with_value("Message-ID".to_string(),
format!("<{}.lettre@localhost>", message_id)) {
Ok(header) => self.message.add_header(header),
Err(_) => (),
if let Ok(header) = Header::new_with_value("Message-ID".to_string(),
format!("<{}.lettre@localhost>", message_id)) {
self.message.add_header(header)
}
Ok(Email {

View File

@@ -15,21 +15,21 @@ pub enum Error {
/// Transient SMTP error, 4xx reply code
///
/// [RFC 5321, section 4.2.1](https://tools.ietf.org/html/rfc5321#section-4.2.1)
TransientError(Response),
Transient(Response),
/// Permanent SMTP error, 5xx reply code
///
/// [RFC 5321, section 4.2.1](https://tools.ietf.org/html/rfc5321#section-4.2.1)
PermanentError(Response),
Permanent(Response),
/// Error parsing a response
ResponseParsingError(&'static str),
ResponseParsing(&'static str),
/// Error parsing a base64 string in response
ChallengeParsingError(FromBase64Error),
ChallengeParsing(FromBase64Error),
/// Internal client error
ClientError(&'static str),
Client(&'static str),
/// DNS resolution error
ResolutionError,
Resolution,
/// IO error
IoError(io::Error),
Io(io::Error),
}
impl Display for Error {
@@ -41,19 +41,19 @@ impl Display for Error {
impl StdError for Error {
fn description(&self) -> &str {
match *self {
TransientError(_) => "a transient error occured during the SMTP transaction",
PermanentError(_) => "a permanent error occured during the SMTP transaction",
ResponseParsingError(_) => "an error occured while parsing an SMTP response",
ChallengeParsingError(_) => "an error occured while parsing a CRAM-MD5 challenge",
ResolutionError => "could not resolve hostname",
ClientError(_) => "an unknown error occured",
IoError(_) => "an I/O error occured",
Transient(_) => "a transient error occured during the SMTP transaction",
Permanent(_) => "a permanent error occured during the SMTP transaction",
ResponseParsing(_) => "an error occured while parsing an SMTP response",
ChallengeParsing(_) => "an error occured while parsing a CRAM-MD5 challenge",
Resolution => "could not resolve hostname",
Client(_) => "an unknown error occured",
Io(_) => "an I/O error occured",
}
}
fn cause(&self) -> Option<&StdError> {
match *self {
IoError(ref err) => Some(&*err as &StdError),
Io(ref err) => Some(&*err as &StdError),
_ => None,
}
}
@@ -61,23 +61,23 @@ impl StdError for Error {
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
IoError(err)
Io(err)
}
}
impl From<Response> for Error {
fn from(response: Response) -> Error {
match response.severity() {
Severity::TransientNegativeCompletion => TransientError(response),
Severity::PermanentNegativeCompletion => PermanentError(response),
_ => ClientError("Unknown error code"),
Severity::TransientNegativeCompletion => Transient(response),
Severity::PermanentNegativeCompletion => Permanent(response),
_ => Client("Unknown error code"),
}
}
}
impl From<&'static str> for Error {
fn from(string: &'static str) -> Error {
ClientError(string)
Client(string)
}
}

View File

@@ -38,7 +38,7 @@ impl EmailTransport for FileEmailTransport {
email.to_addresses().join("> to=<"));
try!(f.write_all(log_line.as_bytes()));
try!(f.write_all(format!("{}", email.message()).as_bytes()));
try!(f.write_all(email.message().clone().as_bytes()));
info!("{} status=<written>", log_line);

View File

@@ -1,75 +0,0 @@
//! This transport creates a file for each email, containing the enveloppe information and the email
//! itself.
use transport::EmailTransport;
use transport::error::EmailResult;
use transport::smtp::response::Response;
use transport::smtp::response::{Category, Code, Severity};
use email::SendableEmail;
/// Writes the content and the enveloppe information to a file
pub struct SendmailEmailTransport {
command: String,
}
impl SendmailEmailTransport {
/// Creates a new transport to the default "sendmail" command
pub fn new() -> SendmailEmailTransport {
SendmailEmailTransport { command: "sendmail".to_string() }
}
/// Creates a new transport with a custom sendmail command
pub fn new_with_command(command: &str) -> SendmailEmailTransport {
SendmailEmailTransport { command: command.to_string() }
}
}
impl EmailTransport for SendmailEmailTransport {
fn send<T: SendableEmail>(&mut self, email: T) -> EmailResult {
// Build TO list
// Set FROM
// Send content
let sendmail_sh_frist_half = "sendmail ".to_string() + &to_address;
let sendmail_sh_second_half = " < email.txt".to_string();
let sendmail_sh = sendmail_sh_frist_half + &sendmail_sh_second_half;
let output = Command::new(self.command)
.arg("-c")
.arg(sendmail_sh)
.output()
.unwrap_or_else(|e| panic!("failed to execute process: {}", e));
println!("status: {}", output.status);
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
let mut file = self.path.clone();
file.push(format!("{}.txt", email.message_id()));
let mut f = try!(File::create(file.as_path()));
let log_line = format!("{}: from=<{}> to=<{}>\n",
email.message_id(),
email.from_address(),
email.to_addresses().join("> to=<"));
try!(f.write_all(log_line.as_bytes()));
try!(f.write_all(format!("{}", email.message()).as_bytes()));
info!("{} status=<written>", log_line);
Ok(Response::new(Code::new(Severity::PositiveCompletion, Category::MailSystem, 0),
vec![format!("Ok: email written to {}",
file.to_str().unwrap_or("non-UTF-8 path"))]))
}
fn close(&mut self) {
()
}
}

View File

@@ -53,9 +53,7 @@ impl Mechanism {
match *self {
Mechanism::Plain => {
match challenge {
Some(_) => {
Err(Error::ClientError("This mechanism does not expect a challenge"))
}
Some(_) => Err(Error::Client("This mechanism does not expect a challenge")),
None => {
Ok(format!("{}{}{}{}", NUL, username, NUL, password)
.as_bytes()
@@ -66,14 +64,12 @@ impl Mechanism {
Mechanism::CramMd5 => {
let encoded_challenge = match challenge {
Some(challenge) => challenge,
None => {
return Err(Error::ClientError("This mechanism does expect a challenge"))
}
None => return Err(Error::Client("This mechanism does expect a challenge")),
};
let decoded_challenge = match encoded_challenge.from_base64() {
Ok(challenge) => challenge,
Err(error) => return Err(Error::ChallengeParsingError(error)),
Err(error) => return Err(Error::ChallengeParsing(error)),
};
let mut hmac = Hmac::new(Md5::new(), password.as_bytes());

View File

@@ -22,7 +22,7 @@ pub mod net;
/// Reference : https://tools.ietf.org/html/rfc5321#page-62 (4.5.2. Transparency)
#[inline]
fn escape_dot(string: &str) -> String {
if string.starts_with(".") {
if string.starts_with('.') {
format!(".{}", string)
} else {
string.to_string()
@@ -193,7 +193,7 @@ impl<S: Connector + Write + Read + Debug + Clone> Client<S> {
} else {
let encoded_challenge = match try!(self.command("AUTH CRAM-MD5")).first_word() {
Some(challenge) => challenge,
None => return Err(Error::ResponseParsingError("Could not read CRAM challenge")),
None => return Err(Error::ResponseParsing("Could not read CRAM challenge")),
};
debug!("CRAM challenge: {}", encoded_challenge);
@@ -202,7 +202,7 @@ impl<S: Connector + Write + Read + Debug + Clone> Client<S> {
password,
Some(&encoded_challenge)));
self.command(&format!("{}", cram_response))
self.command(&cram_response.clone())
}
}
@@ -233,7 +233,7 @@ impl<S: Connector + Write + Read + Debug + Clone> Client<S> {
/// Gets the SMTP response
fn get_reply(&mut self) -> EmailResult {
let mut parser = ResponseParser::new();
let mut parser = ResponseParser::default();
let mut line = String::new();
try!(self.stream.as_mut().unwrap().read_line(&mut line));
@@ -247,10 +247,12 @@ impl<S: Connector + Write + Read + Debug + Clone> Client<S> {
let response = try!(parser.response());
match response.is_positive() {
true => Ok(response),
false => Err(From::from(response)),
if response.is_positive() {
Ok(response)
} else {
Err(From::from(response))
}
}
}

View File

@@ -66,9 +66,9 @@ pub enum NetworkStream {
impl Clone for NetworkStream {
#[inline]
fn clone(&self) -> NetworkStream {
match self {
&NetworkStream::Plain(ref stream) => NetworkStream::Plain(stream.try_clone().unwrap()),
&NetworkStream::Ssl(ref stream) => NetworkStream::Ssl(stream.try_clone().unwrap()),
match *self {
NetworkStream::Plain(ref stream) => NetworkStream::Plain(stream.try_clone().unwrap()),
NetworkStream::Ssl(ref stream) => NetworkStream::Ssl(stream.try_clone().unwrap()),
}
}
}

View File

@@ -69,7 +69,7 @@ impl ServerInfo {
pub fn from_response(response: &Response) -> Result<ServerInfo, Error> {
let name = match response.first_word() {
Some(name) => name,
None => return Err(Error::ResponseParsingError("Could not read server name")),
None => return Err(Error::ResponseParsing("Could not read server name")),
};
let mut features: HashSet<Extension> = HashSet::new();
@@ -77,7 +77,7 @@ impl ServerInfo {
for line in response.message() {
let splitted: Vec<&str> = line.split_whitespace().collect();
let _ = match splitted[0] {
match splitted[0] {
"8BITMIME" => {
features.insert(Extension::EightBitMime);
}

View File

@@ -87,7 +87,7 @@ pub struct SmtpTransportBuilder {
authentication_mechanism: Option<Mechanism>,
}
/// Builder for the SMTP SmtpTransport
/// Builder for the SMTP `SmtpTransport`
impl SmtpTransportBuilder {
/// Creates a new local SMTP client
pub fn new<A: ToSocketAddrs>(addr: A) -> Result<SmtpTransportBuilder, Error> {
@@ -280,10 +280,8 @@ impl EmailTransport for SmtpTransport {
let message = email.message();
// Check if the connection is still available
if self.state.connection_reuse_count > 0 {
if !self.client.is_connected() {
self.reset();
}
if (self.state.connection_reuse_count > 0) && (!self.client.is_connected()) {
self.reset();
}
if self.state.connection_reuse_count == 0 {
@@ -329,12 +327,13 @@ impl EmailTransport for SmtpTransport {
let accepted_mechanisms = match self.client_info.authentication_mechanism {
Some(mechanism) => vec![mechanism],
None => {
match self.client.is_encrypted() {
if self.client.is_encrypted() {
// If encrypted, allow all mechanisms, with a preference for the
// simplest
true => vec![Mechanism::Plain, Mechanism::CramMd5],
vec![Mechanism::Plain, Mechanism::CramMd5]
} else {
// If not encrypted, do not all clear-text passwords
false => vec![Mechanism::CramMd5],
vec![Mechanism::CramMd5]
}
}
};
@@ -373,7 +372,7 @@ impl EmailTransport for SmtpTransport {
info!("{}: from=<{}>", message_id, from_address);
// Recipient
for to_address in to_addresses.iter() {
for to_address in &to_addresses {
try_smtp!(self.client.rcpt(&to_address), self);
// Log the rcpt command
info!("{}: to=<{}>", message_id, to_address);
@@ -387,7 +386,7 @@ impl EmailTransport for SmtpTransport {
if result.is_ok() {
// Increment the connection reuse counter
self.state.connection_reuse_count = self.state.connection_reuse_count + 1;
self.state.connection_reuse_count += 1;
// Log the message
info!("{}: conn_use={}, size={}, status=sent ({})",

View File

@@ -30,7 +30,7 @@ impl FromStr for Severity {
"3" => Ok(PositiveIntermediate),
"4" => Ok(TransientNegativeCompletion),
"5" => Ok(PermanentNegativeCompletion),
_ => Err(Error::ResponseParsingError("First digit must be between 2 and 5")),
_ => Err(Error::ResponseParsing("First digit must be between 2 and 5")),
}
}
}
@@ -75,7 +75,7 @@ impl FromStr for Category {
"3" => Ok(Unspecified3),
"4" => Ok(Unspecified4),
"5" => Ok(MailSystem),
_ => Err(Error::ResponseParsingError("Second digit must be between 0 and 5")),
_ => Err(Error::ResponseParsing("Second digit must be between 0 and 5")),
}
}
}
@@ -122,10 +122,10 @@ impl FromStr for Code {
detail: detail,
})
}
_ => return Err(Error::ResponseParsingError("Could not parse response code")),
_ => Err(Error::ResponseParsing("Could not parse response code")),
}
} else {
Err(Error::ResponseParsingError("Wrong code length (should be 3 digit)"))
Err(Error::ResponseParsing("Wrong code length (should be 3 digit)"))
}
}
}
@@ -147,7 +147,7 @@ impl Code {
}
/// Parses an SMTP response
#[derive(PartialEq,Eq,Clone,Debug)]
#[derive(PartialEq,Eq,Clone,Debug,Default)]
pub struct ResponseParser {
/// Response code
code: Option<Code>,
@@ -157,25 +157,17 @@ pub struct ResponseParser {
}
impl ResponseParser {
/// Creates a new parser
pub fn new() -> ResponseParser {
ResponseParser {
code: None,
message: vec![],
}
}
/// Parses a line and return a `bool` indicating if there are more lines to come
pub fn read_line(&mut self, line: &str) -> result::Result<bool, Error> {
if line.len() < 3 {
return Err(Error::ResponseParsingError("Wrong code length (should be 3 digit)"));
return Err(Error::ResponseParsing("Wrong code length (should be 3 digit)"));
}
match self.code {
Some(ref code) => {
if code.code() != line[0..3] {
return Err(Error::ResponseParsingError("Response code has changed during a \
return Err(Error::ResponseParsing("Response code has changed during a \
reponse"));
}
}
@@ -184,7 +176,7 @@ impl ResponseParser {
if line.len() > 4 {
self.message.push(line[4..].to_string());
Ok(line.as_bytes()[3] == '-' as u8)
Ok(line.as_bytes()[3] == b'-')
} else {
Ok(false)
}
@@ -195,7 +187,7 @@ impl ResponseParser {
match self.code {
Some(code) => Ok(Response::new(code, self.message)),
None => {
Err(Error::ResponseParsingError("Incomplete response, could not read response \
Err(Error::ResponseParsing("Incomplete response, could not read response \
code"))
}
}
@@ -264,15 +256,15 @@ impl Response {
/// Returns only the first word of the message if possible
pub fn first_word(&self) -> Option<String> {
match self.message.is_empty() {
true => None,
false => {
match self.message[0].split_whitespace().next() {
Some(word) => Some(word.to_string()),
None => None,
}
if self.message.is_empty() {
None
} else {
match self.message[0].split_whitespace().next() {
Some(word) => Some(word.to_string()),
None => None,
}
}
}
}
@@ -377,7 +369,7 @@ mod test {
#[test]
fn test_response_parser() {
let mut parser = ResponseParser::new();
let mut parser = ResponseParser::default();
assert!(parser.read_line("250-me").unwrap());
assert!(parser.read_line("250-8BITMIME").unwrap());