diff --git a/lettre/Cargo.toml b/lettre/Cargo.toml index f80e1e3..b1e3f5a 100644 --- a/lettre/Cargo.toml +++ b/lettre/Cargo.toml @@ -28,8 +28,6 @@ hostname = { version = "^0.1", optional = true } serde = { version = "^1.0", optional = true } serde_json = { version = "^1.0", optional = true } serde_derive = { version = "^1.0", optional = true } -failure = "^0.1" -failure_derive = "^0.1" fast_chemail = "^0.9" r2d2 = { version = "^0.8", optional = true} diff --git a/lettre/src/error.rs b/lettre/src/error.rs index d33b98a..c8ceabc 100644 --- a/lettre/src/error.rs +++ b/lettre/src/error.rs @@ -1,18 +1,35 @@ -use failure; +use std::{ + error::Error as StdError, + fmt::{self, Display, Formatter}, +}; +use self::Error::*; /// Error type for email content -#[derive(Fail, Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub enum Error { /// Missing from in envelope - #[fail(display = "missing source address, invalid envelope")] MissingFrom, /// Missing to in envelope - #[fail(display = "missing destination address, invalid envelope")] MissingTo, /// Invalid email - #[fail(display = "invalid email address")] InvalidEmailAddress, } +impl Display for Error { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> { + fmt.write_str(&match *self { + MissingFrom => "missing source address, invalid envelope".to_owned(), + MissingTo => "missing destination address, invalid envelope".to_owned(), + InvalidEmailAddress => "invalid email address".to_owned(), + }) + } +} + +impl StdError for Error { + fn cause(&self) -> Option<&dyn StdError> { + None + } +} + /// Email result type -pub type EmailResult = Result; +pub type EmailResult = Result; diff --git a/lettre/src/file/error.rs b/lettre/src/file/error.rs index e24c540..704be4f 100644 --- a/lettre/src/file/error.rs +++ b/lettre/src/file/error.rs @@ -1,40 +1,65 @@ //! Error and result type for file transport -use failure; +use std::{ + error::Error as StdError, + fmt::{self, Display, Formatter}, +}; use serde_json; use std::io; +use self::Error::*; /// An enum of all error kinds. -#[derive(Fail, Debug)] +#[derive(Debug)] pub enum Error { /// Internal client error - #[fail(display = "Internal client error: {}", error)] - Client { error: &'static str }, + Client(&'static str), /// IO error - #[fail(display = "IO error: {}", error)] - Io { error: io::Error }, + Io(io::Error), /// JSON serialization error - #[fail(display = "JSON serialization error: {}", error)] - JsonSerialization { error: serde_json::Error }, + JsonSerialization(serde_json::Error), +} + +impl Display for Error { + fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { + fmt.write_str(self.description()) + } +} + +impl StdError for Error { + fn description(&self) -> &str { + match *self { + Client(err) => err, + Io(ref err) => err.description(), + JsonSerialization(ref err) => err.description(), + } + } + + fn cause(&self) -> Option<&StdError> { + match *self { + Io(ref err) => Some(&*err), + JsonSerialization(ref err) => Some(&*err), + _ => None, + } + } } impl From for Error { fn from(err: io::Error) -> Error { - Error::Io { error: err } + Error::Io(err) } } impl From for Error { fn from(err: serde_json::Error) -> Error { - Error::JsonSerialization { error: err } + Error::JsonSerialization(err) } } impl From<&'static str> for Error { fn from(string: &'static str) -> Error { - Error::Client { error: string } + Error::Client(string) } } /// SMTP result type -pub type FileResult = Result<(), failure::Error>; +pub type FileResult = Result<(), Error>; diff --git a/lettre/src/lib.rs b/lettre/src/lib.rs index 42d8735..ac485d2 100644 --- a/lettre/src/lib.rs +++ b/lettre/src/lib.rs @@ -30,11 +30,8 @@ extern crate serde; #[cfg(feature = "serde-impls")] #[macro_use] extern crate serde_derive; -extern crate failure; #[cfg(feature = "file-transport")] extern crate serde_json; -#[macro_use] -extern crate failure_derive; extern crate fast_chemail; #[cfg(feature = "connection-pool")] extern crate r2d2; @@ -49,8 +46,7 @@ pub mod smtp; pub mod stub; use error::EmailResult; -use error::Error as EmailError; -use failure::Error; +use error::Error; use fast_chemail::is_valid_email; #[cfg(feature = "file-transport")] pub use file::FileTransport; @@ -77,7 +73,7 @@ pub struct EmailAddress(String); impl EmailAddress { pub fn new(address: String) -> EmailResult { if !is_valid_email(&address) && !address.ends_with("localhost") { - Err(EmailError::InvalidEmailAddress)?; + Err(Error::InvalidEmailAddress)?; } Ok(EmailAddress(address)) } @@ -127,7 +123,7 @@ impl Envelope { /// Creates a new envelope, which may fail if `to` is empty. pub fn new(from: Option, to: Vec) -> EmailResult { if to.is_empty() { - Err(EmailError::MissingTo)?; + Err(Error::MissingTo)?; } Ok(Envelope { forward_path: to, diff --git a/lettre/src/sendmail/error.rs b/lettre/src/sendmail/error.rs index 5a5e64c..856a2f6 100644 --- a/lettre/src/sendmail/error.rs +++ b/lettre/src/sendmail/error.rs @@ -1,30 +1,54 @@ //! Error and result type for sendmail transport -use failure; +use std::{ + error::Error as StdError, + fmt::{self, Display, Formatter}, +}; +use self::Error::*; use std::io; /// An enum of all error kinds. -#[derive(Fail, Debug)] +#[derive(Debug)] pub enum Error { /// Internal client error - #[fail(display = "Internal client error: {}", error)] - Client { error: &'static str }, + Client(&'static str), /// IO error - #[fail(display = "IO error: {}", error)] - Io { error: io::Error }, + Io(io::Error), +} + +impl Display for Error { + fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> { + fmt.write_str(self.description()) + } +} + +impl StdError for Error { + fn description(&self) -> &str { + match *self { + Client(err) => err, + Io(ref err) => err.description(), + } + } + + fn cause(&self) -> Option<&StdError> { + match *self { + Io(ref err) => Some(&*err), + _ => None, + } + } } impl From for Error { fn from(err: io::Error) -> Error { - Error::Io { error: err } + Error::Io(err) } } impl From<&'static str> for Error { fn from(string: &'static str) -> Error { - Error::Client { error: string } + Error::Client(string) } } /// sendmail result type -pub type SendmailResult = Result<(), failure::Error>; +pub type SendmailResult = Result<(), Error>; diff --git a/lettre/src/sendmail/mod.rs b/lettre/src/sendmail/mod.rs index 36090ae..dc2ba80 100644 --- a/lettre/src/sendmail/mod.rs +++ b/lettre/src/sendmail/mod.rs @@ -72,9 +72,7 @@ impl<'a> Transport<'a> for SendmailTransport { Ok(()) } else { // TODO display stderr - Err(error::Error::Client { - error: "The message could not be sent", - })? + Err(error::Error::Client("The message could not be sent"))? } } } diff --git a/lettre_email/Cargo.toml b/lettre_email/Cargo.toml index dc7f2c8..d11e117 100644 --- a/lettre_email/Cargo.toml +++ b/lettre_email/Cargo.toml @@ -29,5 +29,3 @@ time = "^0.1" uuid = { version = "^0.7", features = ["v4"] } lettre = { version = "^0.9", path = "../lettre", default-features = false } base64 = "^0.10" -failure = "^0.1" -failure_derive = "^0.1" diff --git a/lettre_email/src/error.rs b/lettre_email/src/error.rs index 84508f8..d762680 100644 --- a/lettre_email/src/error.rs +++ b/lettre_email/src/error.rs @@ -2,35 +2,52 @@ use lettre; use std::io; +use std::{ + error::Error as StdError, + fmt::{self, Display, Formatter}, +}; +use self::Error::*; /// An enum of all error kinds. -#[derive(Debug, Fail)] +#[derive(Debug)] pub enum Error { /// Envelope error - #[fail(display = "lettre error: {}", error)] - Envelope { - /// inner error - error: lettre::error::Error, - }, + Envelope(lettre::error::Error), /// Unparseable filename for attachment - #[fail(display = "the attachment filename could not be parsed")] CannotParseFilename, /// IO error - #[fail(display = "IO error: {}", error)] - Io { - /// inner error - error: io::Error, - }, + Io(io::Error), +} + +impl Display for Error { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> { + fmt.write_str(&match *self { + CannotParseFilename => "Could not parse attachment filename".to_owned(), + Io(ref err) => err.to_string(), + Envelope(ref err) => err.to_string(), + }) + } +} + +impl StdError for Error { + fn cause(&self) -> Option<&dyn StdError> { + match *self { + Envelope(ref err) => Some(err), + Io(ref err) => Some(err), + _ => None, + } + } } impl From for Error { fn from(err: io::Error) -> Error { - Error::Io { error: err } + Error::Io(err) + } } impl From for Error { fn from(err: lettre::error::Error) -> Error { - Error::Envelope { error: err } + Error::Envelope(err) } } diff --git a/lettre_email/src/lib.rs b/lettre_email/src/lib.rs index b06303f..35d9c35 100644 --- a/lettre_email/src/lib.rs +++ b/lettre_email/src/lib.rs @@ -13,10 +13,6 @@ unused_import_braces )] -extern crate failure; -#[macro_use] -extern crate failure_derive; - extern crate base64; extern crate email as email_format; extern crate lettre; @@ -27,8 +23,7 @@ extern crate uuid; pub mod error; pub use email_format::{Address, Header, Mailbox, MimeMessage, MimeMultipartType}; -use error::Error as EmailError; -use failure::Error; +use error::Error; use lettre::{error::Error as LettreError, EmailAddress, Envelope, SendableEmail}; use mime::Mime; use std::fs; @@ -263,7 +258,7 @@ impl EmailBuilder { filename.unwrap_or( path.file_name() .and_then(|x| x.to_str()) - .ok_or(EmailError::CannotParseFilename)?, + .ok_or(Error::CannotParseFilename)?, ), content_type, ) @@ -416,15 +411,15 @@ impl EmailBuilder { // if it's an author group, use the first author Some(mailbox) => Ok(mailbox.address.clone()), // for an empty author group (the rarest of the rare cases) - None => Err(EmailError::Envelope { - error: LettreError::MissingFrom, - }), // empty envelope sender + None => Err(Error::Envelope( + LettreError::MissingFrom, + )), // empty envelope sender }, }, // if we don't have a from header - None => Err(EmailError::Envelope { - error: LettreError::MissingFrom, - }), // empty envelope sender + None => Err(Error::Envelope( + LettreError::MissingFrom, + )), // empty envelope sender } } }?)?); @@ -448,9 +443,9 @@ impl EmailBuilder { .message .header(Header::new_with_value("From".into(), from).unwrap()); } else { - Err(EmailError::Envelope { - error: LettreError::MissingFrom, - })?; + Err(Error::Envelope( + LettreError::MissingFrom, + ))?; } if !self.cc.is_empty() { self.message = self