diff --git a/src/address.rs b/src/address.rs index 3a2bed5..c743440 100644 --- a/src/address.rs +++ b/src/address.rs @@ -112,21 +112,17 @@ impl FromStr for Address { type Err = AddressError; fn from_str(val: &str) -> Result { - if val.is_empty() || !val.contains('@') { - return Err(AddressError::MissingParts); - } + let mut parts = val.rsplitn(2, '@'); + let domain = parts.next().ok_or(AddressError::MissingParts)?; + let user = parts.next().ok_or(AddressError::MissingParts)?; - let parts: Vec<&str> = val.rsplitn(2, '@').collect(); - let user = parts[1]; - let domain = parts[0]; - - Address::check_user(user) - .and_then(|_| Address::check_domain(domain)) - .map(|_| Address { - user: user.into(), - domain: domain.into(), - complete: val.to_string(), - }) + Address::check_user(user)?; + Address::check_domain(domain)?; + Ok(Address { + user: user.into(), + domain: domain.into(), + complete: val.to_string(), + }) } } diff --git a/src/error.rs b/src/error.rs index 0daa895..1e456a9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -28,18 +28,18 @@ pub enum Error { } impl Display for Error { - fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> { - fmt.write_str(&match self { - Error::MissingFrom => "missing source address, invalid envelope".to_string(), - Error::MissingTo => "missing destination address, invalid envelope".to_string(), - Error::TooManyFrom => "there can only be one source address".to_string(), - Error::EmailMissingAt => "missing @ in email address".to_string(), - Error::EmailMissingLocalPart => "missing local part in email address".to_string(), - Error::EmailMissingDomain => "missing domain in email address".to_string(), - Error::CannotParseFilename => "could not parse attachment filename".to_string(), - Error::NonAsciiChars => "contains non-ASCII chars".to_string(), - Error::Io(e) => e.to_string(), - }) + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { + match self { + Error::MissingFrom => f.write_str("missing source address, invalid envelope"), + Error::MissingTo => f.write_str("missing destination address, invalid envelope"), + Error::TooManyFrom => f.write_str("there can only be one source address"), + Error::EmailMissingAt => f.write_str("missing @ in email address"), + Error::EmailMissingLocalPart => f.write_str("missing local part in email address"), + Error::EmailMissingDomain => f.write_str("missing domain in email address"), + Error::CannotParseFilename => f.write_str("could not parse attachment filename"), + Error::NonAsciiChars => f.write_str("contains non-ASCII chars"), + Error::Io(e) => e.fmt(f), + } } } diff --git a/src/message/header/special.rs b/src/message/header/special.rs index 3803dde..1430a8c 100644 --- a/src/message/header/special.rs +++ b/src/message/header/special.rs @@ -35,15 +35,12 @@ impl Header for MimeVersion { Self: Sized, { raw.one().ok_or(HeaderError::Header).and_then(|r| { - let s: Vec<&str> = from_utf8(r) - .map_err(|_| HeaderError::Header)? - .split('.') - .collect(); - if s.len() != 2 { - return Err(HeaderError::Header); - } - let major = s[0].parse().map_err(|_| HeaderError::Header)?; - let minor = s[1].parse().map_err(|_| HeaderError::Header)?; + let mut s = from_utf8(r).map_err(|_| HeaderError::Header)?.split('.'); + + let major = s.next().ok_or(HeaderError::Header)?; + let minor = s.next().ok_or(HeaderError::Header)?; + let major = major.parse().map_err(|_| HeaderError::Header)?; + let minor = minor.parse().map_err(|_| HeaderError::Header)?; Ok(MimeVersion::new(major, minor)) }) } diff --git a/src/message/mimebody.rs b/src/message/mimebody.rs index 52a3c8a..340cb46 100644 --- a/src/message/mimebody.rs +++ b/src/message/mimebody.rs @@ -209,10 +209,8 @@ fn make_boundary() -> String { } impl MultiPartKind { - fn to_mime>(&self, boundary: Option) -> Mime { - let boundary = boundary - .map(|s| s.as_ref().into()) - .unwrap_or_else(make_boundary); + fn to_mime>(&self, boundary: Option) -> Mime { + let boundary = boundary.map_or_else(make_boundary, |s| s.into()); use self::MultiPartKind::*; format!( diff --git a/src/message/utf8_b.rs b/src/message/utf8_b.rs index 71f7695..3da84d6 100644 --- a/src/message/utf8_b.rs +++ b/src/message/utf8_b.rs @@ -23,15 +23,8 @@ pub fn decode(s: &str) -> Option { let s = s.split_at(10).1; let s = s.split_at(s.len() - 2).0; base64::decode(s) - .map_err(|_| ()) - .and_then(|v| { - if let Ok(s) = from_utf8(&v) { - Ok(Some(s.into())) - } else { - Err(()) - } - }) - .unwrap_or(None) + .ok() + .and_then(|v| from_utf8(&v).ok().map(|s| s.into())) } else { Some(s.into()) } diff --git a/src/transport/smtp/authentication.rs b/src/transport/smtp/authentication.rs index 077ffb0..75e3195 100644 --- a/src/transport/smtp/authentication.rs +++ b/src/transport/smtp/authentication.rs @@ -62,15 +62,11 @@ pub enum Mechanism { impl Display for Mechanism { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!( - f, - "{}", - match *self { - Mechanism::Plain => "PLAIN", - Mechanism::Login => "LOGIN", - Mechanism::Xoauth2 => "XOAUTH2", - } - ) + f.write_str(match *self { + Mechanism::Plain => "PLAIN", + Mechanism::Login => "LOGIN", + Mechanism::Xoauth2 => "XOAUTH2", + }) } } diff --git a/src/transport/smtp/client/mod.rs b/src/transport/smtp/client/mod.rs index 5d3df29..96fc5b3 100644 --- a/src/transport/smtp/client/mod.rs +++ b/src/transport/smtp/client/mod.rs @@ -40,7 +40,7 @@ impl ClientCodec { } /// Adds transparency - fn encode(&mut self, frame: &[u8], buf: &mut Vec) -> Result<(), Error> { + fn encode(&mut self, frame: &[u8], buf: &mut Vec) { match frame.len() { 0 => { match self.escape_count { @@ -50,7 +50,6 @@ impl ClientCodec { _ => unreachable!(), } self.escape_count = 0; - Ok(()) } _ => { let mut start = 0; @@ -69,7 +68,6 @@ impl ClientCodec { } } buf.extend_from_slice(&frame[start..]); - Ok(()) } } } @@ -283,7 +281,7 @@ impl SmtpConnection { pub fn message(&mut self, message: &[u8]) -> Result { let mut out_buf: Vec = vec![]; let mut codec = ClientCodec::new(); - codec.encode(message, &mut out_buf)?; + codec.encode(message, &mut out_buf); self.write(out_buf.as_slice())?; self.write(b"\r\n.\r\n")?; self.read_response() @@ -346,15 +344,15 @@ mod test { let mut codec = ClientCodec::new(); let mut buf: Vec = vec![]; - assert!(codec.encode(b"test\r\n", &mut buf).is_ok()); - assert!(codec.encode(b".\r\n", &mut buf).is_ok()); - assert!(codec.encode(b"\r\ntest", &mut buf).is_ok()); - assert!(codec.encode(b"te\r\n.\r\nst", &mut buf).is_ok()); - assert!(codec.encode(b"test", &mut buf).is_ok()); - assert!(codec.encode(b"test.", &mut buf).is_ok()); - assert!(codec.encode(b"test\n", &mut buf).is_ok()); - assert!(codec.encode(b".test\n", &mut buf).is_ok()); - assert!(codec.encode(b"test", &mut buf).is_ok()); + codec.encode(b"test\r\n", &mut buf); + codec.encode(b".\r\n", &mut buf); + codec.encode(b"\r\ntest", &mut buf); + codec.encode(b"te\r\n.\r\nst", &mut buf); + codec.encode(b"test", &mut buf); + codec.encode(b"test.", &mut buf); + codec.encode(b"test\n", &mut buf); + codec.encode(b".test\n", &mut buf); + codec.encode(b"test", &mut buf); assert_eq!( String::from_utf8(buf).unwrap(), "test\r\n..\r\n\r\ntestte\r\n..\r\nsttesttest.test\n.test\ntest" diff --git a/src/transport/smtp/client/net.rs b/src/transport/smtp/client/net.rs index 5dcf553..c112d29 100644 --- a/src/transport/smtp/client/net.rs +++ b/src/transport/smtp/client/net.rs @@ -99,9 +99,8 @@ impl NetworkStream { ) -> Result { let addrs = server.to_socket_addrs()?; for addr in addrs { - let result = TcpStream::connect_timeout(&addr, timeout); - if result.is_ok() { - return result.map_err(|e| e.into()); + if let Ok(result) = TcpStream::connect_timeout(&addr, timeout) { + return Ok(result); } } Err(Error::Client("Could not connect")) diff --git a/src/transport/smtp/commands.rs b/src/transport/smtp/commands.rs index 5a35c86..f710afe 100644 --- a/src/transport/smtp/commands.rs +++ b/src/transport/smtp/commands.rs @@ -147,8 +147,8 @@ pub struct Help { impl Display for Help { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.write_str("HELP")?; - if self.argument.is_some() { - write!(f, " {}", self.argument.as_ref().unwrap())?; + if let Some(argument) = &self.argument { + write!(f, " {}", argument)?; } f.write_str("\r\n") } diff --git a/src/transport/smtp/extension.rs b/src/transport/smtp/extension.rs index 4346745..f9206c3 100644 --- a/src/transport/smtp/extension.rs +++ b/src/transport/smtp/extension.rs @@ -43,18 +43,17 @@ impl ClientId { /// Defines a `ClientId` with the current hostname, of `localhost` if hostname could not be /// found - #[cfg(feature = "hostname")] pub fn hostname() -> ClientId { - ClientId::Domain( + #[cfg(feature = "hostname")] + return ClientId::Domain( hostname::get() - .map_err(|_| ()) - .and_then(|s| s.into_string().map_err(|_| ())) - .unwrap_or_else(|_| DEFAULT_DOMAIN_CLIENT_ID.to_string()), - ) - } - #[cfg(not(feature = "hostname"))] - pub fn hostname() -> ClientId { - ClientId::Domain(DEFAULT_DOMAIN_CLIENT_ID.to_string()) + .ok() + .and_then(|s| s.into_string().ok()) + .unwrap_or_else(|| DEFAULT_DOMAIN_CLIENT_ID.to_string()), + ); + + #[cfg(not(feature = "hostname"))] + return ClientId::Domain(DEFAULT_DOMAIN_CLIENT_ID.to_string()); } } @@ -81,9 +80,9 @@ pub enum Extension { impl Display for Extension { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match *self { - Extension::EightBitMime => write!(f, "8BITMIME"), - Extension::SmtpUtfEight => write!(f, "SMTPUTF8"), - Extension::StartTls => write!(f, "STARTTLS"), + Extension::EightBitMime => f.write_str("8BITMIME"), + Extension::SmtpUtfEight => f.write_str("SMTPUTF8"), + Extension::StartTls => f.write_str("STARTTLS"), Extension::Authentication(ref mechanism) => write!(f, "AUTH {}", mechanism), } } @@ -105,16 +104,12 @@ pub struct ServerInfo { impl Display for ServerInfo { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!( - f, - "{} with {}", - self.name, - if self.features.is_empty() { - "no supported features".to_string() - } else { - format!("{:?}", self.features) - } - ) + let features = if self.features.is_empty() { + "no supported features".to_string() + } else { + format!("{:?}", self.features) + }; + write!(f, "{} with {}", self.name, features) } } diff --git a/src/transport/smtp/response.rs b/src/transport/smtp/response.rs index b266073..bd20145 100644 --- a/src/transport/smtp/response.rs +++ b/src/transport/smtp/response.rs @@ -237,25 +237,19 @@ pub(crate) fn parse_response(i: &str) -> IResult<&str, Response> { let (i, _) = complete(tag("\r\n"))(i)?; // Check that all codes are equal. - if !lines.iter().all(|&(ref code, _, _)| *code == last_code) { + if !lines.iter().all(|&(code, _, _)| code == last_code) { return Err(nom::Err::Failure(("", nom::error::ErrorKind::Not))); } // Extract text from lines, and append last line. - let mut lines: Vec<&str> = lines - .into_iter() - .map(|(_, text, _)| text) - .collect::>(); - lines.push(last_line); + let mut lines: Vec = lines.into_iter().map(|(_, text, _)| text.into()).collect(); + lines.push(last_line.into()); Ok(( i, Response { code: last_code, - message: lines - .iter() - .map(ToString::to_string) - .collect::>(), + message: lines, }, )) } diff --git a/src/transport/stub/mod.rs b/src/transport/stub/mod.rs index 3129719..24bbf4e 100644 --- a/src/transport/stub/mod.rs +++ b/src/transport/stub/mod.rs @@ -36,15 +36,11 @@ pub struct Error; impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "stub error") + f.write_str("stub error") } } -impl StdError for Error { - fn source(&self) -> Option<&(dyn StdError + 'static)> { - None - } -} +impl StdError for Error {} /// This transport logs the message envelope and returns the given response #[derive(Debug, Clone, Copy)]