1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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>;