imap_patch_for_async_imap_lite/
error.rs

1//! IMAP error types.
2
3use std::error::Error as StdError;
4use std::fmt;
5use std::io::Error as IoError;
6#[cfg(feature = "tls")]
7use std::net::TcpStream;
8use std::result;
9use std::str::Utf8Error;
10
11use base64::DecodeError;
12use bufstream::IntoInnerError as BufError;
13use imap_proto::Response;
14#[cfg(feature = "tls")]
15use native_tls::Error as TlsError;
16#[cfg(feature = "tls")]
17use native_tls::HandshakeError as TlsHandshakeError;
18
19/// A convenience wrapper around `Result` for `imap::Error`.
20pub type Result<T> = result::Result<T, Error>;
21
22/// A set of errors that can occur in the IMAP client
23#[derive(Debug)]
24pub enum Error {
25    /// An `io::Error` that occurred while trying to read or write to a network stream.
26    Io(IoError),
27    /// An error from the `native_tls` library during the TLS handshake.
28    #[cfg(feature = "tls")]
29    TlsHandshake(TlsHandshakeError<TcpStream>),
30    /// An error from the `native_tls` library while managing the socket.
31    #[cfg(feature = "tls")]
32    Tls(TlsError),
33    /// A BAD response from the IMAP server.
34    Bad(String),
35    /// A NO response from the IMAP server.
36    No(String),
37    /// The connection was terminated unexpectedly.
38    ConnectionLost,
39    /// Error parsing a server response.
40    Parse(ParseError),
41    /// Command inputs were not valid [IMAP
42    /// strings](https://tools.ietf.org/html/rfc3501#section-4.3).
43    Validate(ValidateError),
44    /// Error appending an e-mail.
45    Append,
46    #[doc(hidden)]
47    __Nonexhaustive,
48}
49
50impl From<IoError> for Error {
51    fn from(err: IoError) -> Error {
52        Error::Io(err)
53    }
54}
55
56impl From<ParseError> for Error {
57    fn from(err: ParseError) -> Error {
58        Error::Parse(err)
59    }
60}
61
62impl<T> From<BufError<T>> for Error {
63    fn from(err: BufError<T>) -> Error {
64        Error::Io(err.into())
65    }
66}
67
68#[cfg(feature = "tls")]
69impl From<TlsHandshakeError<TcpStream>> for Error {
70    fn from(err: TlsHandshakeError<TcpStream>) -> Error {
71        Error::TlsHandshake(err)
72    }
73}
74
75#[cfg(feature = "tls")]
76impl From<TlsError> for Error {
77    fn from(err: TlsError) -> Error {
78        Error::Tls(err)
79    }
80}
81
82impl<'a> From<Response<'a>> for Error {
83    fn from(err: Response<'a>) -> Error {
84        Error::Parse(ParseError::Unexpected(format!("{:?}", err)))
85    }
86}
87
88impl fmt::Display for Error {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        match *self {
91            Error::Io(ref e) => fmt::Display::fmt(e, f),
92            #[cfg(feature = "tls")]
93            Error::Tls(ref e) => fmt::Display::fmt(e, f),
94            #[cfg(feature = "tls")]
95            Error::TlsHandshake(ref e) => fmt::Display::fmt(e, f),
96            Error::Validate(ref e) => fmt::Display::fmt(e, f),
97            Error::Parse(ref e) => fmt::Display::fmt(e, f),
98            Error::No(ref data) => write!(f, "No Response: {}", data),
99            Error::Bad(ref data) => write!(f, "Bad Response: {}", data),
100            Error::ConnectionLost => f.write_str("Connection Lost"),
101            Error::Append => f.write_str("Could not append mail to mailbox"),
102            Error::__Nonexhaustive => f.write_str("Unknown"),
103        }
104    }
105}
106
107impl StdError for Error {
108    #[allow(deprecated)]
109    fn description(&self) -> &str {
110        match *self {
111            Error::Io(ref e) => e.description(),
112            #[cfg(feature = "tls")]
113            Error::Tls(ref e) => e.description(),
114            #[cfg(feature = "tls")]
115            Error::TlsHandshake(ref e) => e.description(),
116            Error::Parse(ref e) => e.description(),
117            Error::Validate(ref e) => e.description(),
118            Error::Bad(_) => "Bad Response",
119            Error::No(_) => "No Response",
120            Error::ConnectionLost => "Connection lost",
121            Error::Append => "Could not append mail to mailbox",
122            Error::__Nonexhaustive => "Unknown",
123        }
124    }
125
126    fn cause(&self) -> Option<&dyn StdError> {
127        match *self {
128            Error::Io(ref e) => Some(e),
129            #[cfg(feature = "tls")]
130            Error::Tls(ref e) => Some(e),
131            #[cfg(feature = "tls")]
132            Error::TlsHandshake(ref e) => Some(e),
133            Error::Parse(ParseError::DataNotUtf8(_, ref e)) => Some(e),
134            _ => None,
135        }
136    }
137}
138
139/// An error occured while trying to parse a server response.
140#[derive(Debug)]
141pub enum ParseError {
142    /// Indicates an error parsing the status response. Such as OK, NO, and BAD.
143    Invalid(Vec<u8>),
144    /// An unexpected response was encountered.
145    Unexpected(String),
146    /// The client could not find or decode the server's authentication challenge.
147    Authentication(String, Option<DecodeError>),
148    /// The client received data that was not UTF-8 encoded.
149    DataNotUtf8(Vec<u8>, Utf8Error),
150}
151
152impl fmt::Display for ParseError {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        match *self {
155            ParseError::Invalid(_) => f.write_str("Unable to parse status response"),
156            ParseError::Unexpected(_) => f.write_str("Encountered unexpected parse response"),
157            ParseError::Authentication(_, _) => {
158                f.write_str("Unable to parse authentication response")
159            }
160            ParseError::DataNotUtf8(_, _) => f.write_str("Unable to parse data as UTF-8 text"),
161        }
162    }
163}
164
165impl StdError for ParseError {
166    fn description(&self) -> &str {
167        match *self {
168            ParseError::Invalid(_) => "Unable to parse status response",
169            ParseError::Unexpected(_) => "Encountered unexpected parsed response",
170            ParseError::Authentication(_, _) => "Unable to parse authentication response",
171            ParseError::DataNotUtf8(_, _) => "Unable to parse data as UTF-8 text",
172        }
173    }
174
175    fn cause(&self) -> Option<&dyn StdError> {
176        match *self {
177            ParseError::Authentication(_, Some(ref e)) => Some(e),
178            _ => None,
179        }
180    }
181}
182
183/// An [invalid character](https://tools.ietf.org/html/rfc3501#section-4.3) was found in an input
184/// string.
185#[derive(Debug)]
186pub struct ValidateError(pub char);
187
188impl fmt::Display for ValidateError {
189    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
190        // print character in debug form because invalid ones are often whitespaces
191        write!(f, "Invalid character in input: {:?}", self.0)
192    }
193}
194
195impl StdError for ValidateError {
196    fn description(&self) -> &str {
197        "Invalid character in input"
198    }
199
200    fn cause(&self) -> Option<&dyn StdError> {
201        None
202    }
203}