use self::Error::*;
use crate::smtp::response::{Response, Severity};
use base64::DecodeError;
use std::io;
use std::string::FromUtf8Error;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("transient: {}", .0.first_line().unwrap_or("undetailed error during SMTP transaction"))]
Transient(Response),
#[error("permanent: {}", .0.first_line().unwrap_or("undetailed error during SMTP transaction"))]
Permanent(Response),
#[error("{0}")]
ResponseParsing(&'static str),
#[error("challenge parsing: {0}")]
ChallengeParsing(#[from] DecodeError),
#[error("utf8: {0}")]
Utf8Parsing(#[from] FromUtf8Error),
#[error("client: {0}")]
Client(&'static str),
#[error("could not resolve hostname")]
Resolution,
#[error("io: {0}")]
Io(#[from] io::Error),
#[error("tls: {0}")]
Tls(#[from] async_native_tls::Error),
#[error("parsing: {0:?}")]
Parsing(nom::error::ErrorKind),
#[error("timeout: {0}")]
Timeout(#[from] async_std::future::TimeoutError),
#[error("no stream")]
NoStream,
#[error("no server info")]
NoServerInfo,
}
impl From<nom::Err<(&str, nom::error::ErrorKind)>> for Error {
fn from(err: nom::Err<(&str, nom::error::ErrorKind)>) -> Error {
Parsing(match err {
nom::Err::Incomplete(_) => nom::error::ErrorKind::Complete,
nom::Err::Failure((_, k)) => k,
nom::Err::Error((_, k)) => k,
})
}
}
impl From<Response> for Error {
fn from(response: Response) -> Error {
match response.code.severity {
Severity::TransientNegativeCompletion => Transient(response),
Severity::PermanentNegativeCompletion => Permanent(response),
_ => Client("Unknown error code"),
}
}
}
impl From<&'static str> for Error {
fn from(string: &'static str) -> Error {
Client(string)
}
}
pub type SmtpResult = Result<Response, Error>;