feat(all): Improve sendmail transport error handling

This commit is contained in:
Alexis Mousset
2019-06-11 19:40:36 +02:00
parent 0ead3cde09
commit 5f75afe05c
7 changed files with 30 additions and 38 deletions

View File

@@ -2,6 +2,7 @@
use self::Error::*;
use std::io;
use std::string::FromUtf8Error;
use std::{
error::Error as StdError,
fmt::{self, Display, Formatter},
@@ -11,7 +12,9 @@ use std::{
#[derive(Debug)]
pub enum Error {
/// Internal client error
Client(&'static str),
Client(String),
/// Error parsing UTF8in response
Utf8Parsing(FromUtf8Error),
/// IO error
Io(io::Error),
}
@@ -25,7 +28,8 @@ impl Display for Error {
impl StdError for Error {
fn description(&self) -> &str {
match *self {
Client(err) => err,
Client(ref err) => err,
Utf8Parsing(ref err) => err.description(),
Io(ref err) => err.description(),
}
}
@@ -33,6 +37,7 @@ impl StdError for Error {
fn cause(&self) -> Option<&StdError> {
match *self {
Io(ref err) => Some(&*err),
Utf8Parsing(ref err) => Some(&*err),
_ => None,
}
}
@@ -44,9 +49,9 @@ impl From<io::Error> for Error {
}
}
impl From<&'static str> for Error {
fn from(string: &'static str) -> Error {
Error::Client(string)
impl From<FromUtf8Error> for Error {
fn from(err: FromUtf8Error) -> Error {
Utf8Parsing(err)
}
}

View File

@@ -70,8 +70,7 @@ impl<'a> Transport<'a> for SendmailTransport {
if output.status.success() {
Ok(())
} else {
// TODO display stderr
Err(error::Error::Client("The message could not be sent"))?
Err(error::Error::Client(String::from_utf8(output.stderr)?))
}
}
}

View File

@@ -10,7 +10,7 @@ pub const DEFAULT_ENCRYPTED_MECHANISMS: &[Mechanism] = &[Mechanism::Plain, Mecha
/// Accepted authentication mechanisms on an unencrypted connection
pub const DEFAULT_UNENCRYPTED_MECHANISMS: &[Mechanism] = &[];
/// Convertable to user credentials
/// Convertible to user credentials
pub trait IntoCredentials {
/// Converts to a `Credentials` struct
fn into_credentials(self) -> Credentials;

View File

@@ -123,22 +123,19 @@ impl<S: Connector + Write + Read + Timeout + Debug> InnerClient<S> {
/// Tells if the underlying stream is currently encrypted
pub fn is_encrypted(&self) -> bool {
match self.stream {
Some(ref stream) => stream.get_ref().is_encrypted(),
None => false,
}
self.stream
.as_ref()
.map(|s| s.get_ref().is_encrypted())
.unwrap_or(false)
}
/// Set timeout
pub fn set_timeout(&mut self, duration: Option<Duration>) -> io::Result<()> {
match self.stream {
Some(ref mut stream) => {
stream.get_mut().set_read_timeout(duration)?;
stream.get_mut().set_write_timeout(duration)?;
Ok(())
}
None => Ok(()),
if let Some(ref mut stream) = self.stream {
stream.get_mut().set_read_timeout(duration)?;
stream.get_mut().set_write_timeout(duration)?;
}
Ok(())
}
/// Connects to the configured server

View File

@@ -92,8 +92,11 @@ impl Write for NetworkStream {
/// A trait for the concept of opening a stream
pub trait Connector: Sized {
/// Opens a connection to the given IP socket
fn connect(addr: &SocketAddr, timeout: Option<Duration>, tls_parameters: Option<&ClientTlsParameters>)
-> io::Result<Self>;
fn connect(
addr: &SocketAddr,
timeout: Option<Duration>,
tls_parameters: Option<&ClientTlsParameters>,
) -> io::Result<Self>;
/// Upgrades to TLS connection
fn upgrade_tls(&mut self, tls_parameters: &ClientTlsParameters) -> io::Result<()>;
/// Is the NetworkStream encrypted

View File

@@ -174,7 +174,7 @@ impl Response {
/// Returns only the first word of the message if possible
pub fn first_word(&self) -> Option<&str> {
self.message
.get(0)
.first()
.and_then(|line| line.split_whitespace().next())
}

View File

@@ -297,10 +297,7 @@ impl EmailBuilder {
pub fn text<S: Into<String>>(self, body: S) -> EmailBuilder {
let text = PartBuilder::new()
.body(body)
.header((
"Content-Type",
mime::TEXT_PLAIN_UTF_8.to_string(),
))
.header(("Content-Type", mime::TEXT_PLAIN_UTF_8.to_string()))
.build();
self.child(text)
}
@@ -309,10 +306,7 @@ impl EmailBuilder {
pub fn html<S: Into<String>>(self, body: S) -> EmailBuilder {
let html = PartBuilder::new()
.body(body)
.header((
"Content-Type",
mime::TEXT_HTML_UTF_8.to_string(),
))
.header(("Content-Type", mime::TEXT_HTML_UTF_8.to_string()))
.build();
self.child(html)
}
@@ -325,18 +319,12 @@ impl EmailBuilder {
) -> EmailBuilder {
let text = PartBuilder::new()
.body(body_text)
.header((
"Content-Type",
mime::TEXT_PLAIN_UTF_8.to_string(),
))
.header(("Content-Type", mime::TEXT_PLAIN_UTF_8.to_string()))
.build();
let html = PartBuilder::new()
.body(body_html)
.header((
"Content-Type",
mime::TEXT_HTML_UTF_8.to_string(),
))
.header(("Content-Type", mime::TEXT_HTML_UTF_8.to_string()))
.build();
let alternate = PartBuilder::new()