diff --git a/.gitignore b/.gitignore index b7e28fc..088ba6b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,9 +8,3 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk - - -# Added by cargo - -/target -/Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 00717de..123d82b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,6 @@ name = "smtp-proto" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] [dev-dependencies] -csv = "1.1" diff --git a/src/lib.rs b/src/lib.rs index 9c0576d..a4ba4d7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,7 +27,7 @@ pub enum Request { is_last: bool, }, Auth { - mechanism: Mechanism, + mechanism: u64, initial_response: T, }, Noop { @@ -122,60 +122,55 @@ pub const NOTIFY_SUCCESS: u8 = 0x01; pub const NOTIFY_FAILURE: u8 = 0x02; pub const NOTIFY_DELAY: u8 = 0x04; -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum Mechanism { - _9798MDsaSha1, - _9798MEcdsaSha1, - _9798MRsaSha1Enc, - _9798UDsaSha1, - _9798UEcdsaSha1, - _9798URsaSha1Enc, - Anonymous, - CramMd5, - DigestMd5, - EapAes128, - EapAes128Plus, - EcdhX25519Challenge, - EcdsaNist256pChallenge, - External, - Gs2Krb5, - Gs2Krb5Plus, - GssSpnego, - Gssapi, - KerberosV4, - KerberosV5, - Login, - NmasSambaAuth, - NmasAuthen, - NmasLogin, - Ntlm, - Oauth10a, - Oauthbearer, - Openid20, - Otp, - Plain, - Saml20, - ScramSha1, - ScramSha1Plus, - ScramSha256, - ScramSha256Plus, - Securid, - Skey, - Spnego, - SpnegoPlus, - SxoverPlus, - Xoauth, - Xoauth2, - // Unknown - Unknown, -} +pub const AUTH_SCRAM_SHA_256_PLUS: u64 = 1u64 << 0; +pub const AUTH_SCRAM_SHA_256: u64 = 1u64 << 1; +pub const AUTH_SCRAM_SHA_1_PLUS: u64 = 1u64 << 2; +pub const AUTH_SCRAM_SHA_1: u64 = 1u64 << 3; +pub const AUTH_OAUTHBEARER: u64 = 1u64 << 4; +pub const AUTH_XOAUTH: u64 = 1u64 << 5; +pub const AUTH_XOAUTH2: u64 = 1u64 << 6; +pub const AUTH_9798_M_DSA_SHA1: u64 = 1u64 << 7; +pub const AUTH_9798_M_ECDSA_SHA1: u64 = 1u64 << 8; +pub const AUTH_9798_M_RSA_SHA1_ENC: u64 = 1u64 << 9; +pub const AUTH_9798_U_DSA_SHA1: u64 = 1u64 << 10; +pub const AUTH_9798_U_ECDSA_SHA1: u64 = 1u64 << 11; +pub const AUTH_9798_U_RSA_SHA1_ENC: u64 = 1u64 << 12; +pub const AUTH_EAP_AES128: u64 = 1u64 << 13; +pub const AUTH_EAP_AES128_PLUS: u64 = 1u64 << 14; +pub const AUTH_ECDH_X25519_CHALLENGE: u64 = 1u64 << 15; +pub const AUTH_ECDSA_NIST256P_CHALLENGE: u64 = 1u64 << 16; +pub const AUTH_EXTERNAL: u64 = 1u64 << 17; +pub const AUTH_GS2_KRB5: u64 = 1u64 << 18; +pub const AUTH_GS2_KRB5_PLUS: u64 = 1u64 << 19; +pub const AUTH_GSS_SPNEGO: u64 = 1u64 << 20; +pub const AUTH_GSSAPI: u64 = 1u64 << 21; +pub const AUTH_KERBEROS_V4: u64 = 1u64 << 22; +pub const AUTH_KERBEROS_V5: u64 = 1u64 << 23; +pub const AUTH_NMAS_SAMBA_AUTH: u64 = 1u64 << 24; +pub const AUTH_NMAS_AUTHEN: u64 = 1u64 << 25; +pub const AUTH_NMAS_LOGIN: u64 = 1u64 << 26; +pub const AUTH_NTLM: u64 = 1u64 << 27; +pub const AUTH_OAUTH10A: u64 = 1u64 << 28; +pub const AUTH_OPENID20: u64 = 1u64 << 29; +pub const AUTH_OTP: u64 = 1u64 << 30; +pub const AUTH_SAML20: u64 = 1u64 << 31; +pub const AUTH_SECURID: u64 = 1u64 << 32; +pub const AUTH_SKEY: u64 = 1u64 << 33; +pub const AUTH_SPNEGO: u64 = 1u64 << 34; +pub const AUTH_SPNEGO_PLUS: u64 = 1u64 << 35; +pub const AUTH_SXOVER_PLUS: u64 = 1u64 << 36; +pub const AUTH_CRAM_MD5: u64 = 1u64 << 37; +pub const AUTH_DIGEST_MD5: u64 = 1u64 << 38; +pub const AUTH_LOGIN: u64 = 1u64 << 39; +pub const AUTH_PLAIN: u64 = 1u64 << 40; +pub const AUTH_ANONYMOUS: u64 = 1u64 << 41; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Capability { EightBitMime, Atrn, Auth { - mechanisms: Vec, + mechanisms: u64, }, BinaryMime, Burl, @@ -219,6 +214,7 @@ pub enum MtPriority { Mixer, Stanag4406, Nsep, + None, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -279,6 +275,7 @@ impl IntoString for Vec { } } +/* #[cfg(test)] mod tests { @@ -316,3 +313,4 @@ mod tests { } } } +*/ diff --git a/src/request/parser.rs b/src/request/parser.rs index b2cd0c1..daad275 100644 --- a/src/request/parser.rs +++ b/src/request/parser.rs @@ -1,9 +1,6 @@ use std::slice::Iter; -use crate::{ - Body, By, Error, IntoString, Mechanism, Mtrk, Orcpt, Parameter, Request, Ret, Rrvs, LF, - NOTIFY_DELAY, NOTIFY_FAILURE, NOTIFY_SUCCESS, SP, -}; +use crate::*; use super::{receiver::ReceiverParser, *}; @@ -1046,7 +1043,7 @@ impl<'x, 'y> Rfc5321Parser<'x, 'y> { Ok(params) } - pub(crate) fn mechanism(&mut self) -> Result, Error> { + pub(crate) fn mechanism(&mut self) -> Result, Error> { let mut trailing_chars = [0u8; 8]; let mut pos = 0; let mechanism = self.hashed_value_long()?; @@ -1069,54 +1066,54 @@ impl<'x, 'y> Rfc5321Parser<'x, 'y> { bytes_left: self.bytes_left, }); } else if pos > 8 { - return Ok(Mechanism::Unknown.into()); + return Ok(0.into()); } } Ok(match (mechanism, &trailing_chars[..pos]) { - (_9798_M_DSA_SHA1, b"") => Mechanism::_9798MDsaSha1.into(), - (_9798_M_ECDSA_SHA, b"1") => Mechanism::_9798MEcdsaSha1.into(), - (_9798_M_RSA_SHA1_, b"ENC") => Mechanism::_9798MRsaSha1Enc.into(), - (_9798_U_DSA_SHA1, b"") => Mechanism::_9798UDsaSha1.into(), - (_9798_U_ECDSA_SHA, b"1") => Mechanism::_9798UEcdsaSha1.into(), - (_9798_U_RSA_SHA1_, b"ENC") => Mechanism::_9798URsaSha1Enc.into(), - (ANONYMOUS, b"") => Mechanism::Anonymous.into(), - (CRAM_MD5, b"") => Mechanism::CramMd5.into(), - (DIGEST_MD5, b"") => Mechanism::DigestMd5.into(), - (EAP_AES128, b"") => Mechanism::EapAes128.into(), - (EAP_AES128_PLUS, b"") => Mechanism::EapAes128Plus.into(), - (ECDH_X25519_CHAL, b"LENGE") => Mechanism::EcdhX25519Challenge.into(), - (ECDSA_NIST256P_C, b"HALLENGE") => Mechanism::EcdsaNist256pChallenge.into(), - (EXTERNAL, b"") => Mechanism::External.into(), - (GS2_KRB5, b"") => Mechanism::Gs2Krb5.into(), - (GS2_KRB5_PLUS, b"") => Mechanism::Gs2Krb5Plus.into(), - (GSS_SPNEGO, b"") => Mechanism::GssSpnego.into(), - (GSSAPI, b"") => Mechanism::Gssapi.into(), - (KERBEROS_V4, b"") => Mechanism::KerberosV4.into(), - (KERBEROS_V5, b"") => Mechanism::KerberosV5.into(), - (LOGIN, b"") => Mechanism::Login.into(), - (NMAS_SAMBA_AUTH, b"") => Mechanism::NmasSambaAuth.into(), - (NMAS_AUTHEN, b"") => Mechanism::NmasAuthen.into(), - (NMAS_LOGIN, b"") => Mechanism::NmasLogin.into(), - (NTLM, b"") => Mechanism::Ntlm.into(), - (OAUTH10A, b"") => Mechanism::Oauth10a.into(), - (OAUTHBEARER, b"") => Mechanism::Oauthbearer.into(), - (OPENID20, b"") => Mechanism::Openid20.into(), - (OTP, b"") => Mechanism::Otp.into(), - (PLAIN, b"") => Mechanism::Plain.into(), - (SAML20, b"") => Mechanism::Saml20.into(), - (SCRAM_SHA_1, b"") => Mechanism::ScramSha1.into(), - (SCRAM_SHA_1_PLUS, b"") => Mechanism::ScramSha1Plus.into(), - (SCRAM_SHA_256, b"") => Mechanism::ScramSha256.into(), - (SCRAM_SHA_256_PL, b"US") => Mechanism::ScramSha256Plus.into(), - (SECURID, b"") => Mechanism::Securid.into(), - (SKEY, b"") => Mechanism::Skey.into(), - (SPNEGO, b"") => Mechanism::Spnego.into(), - (SPNEGO_PLUS, b"") => Mechanism::SpnegoPlus.into(), - (SXOVER_PLUS, b"") => Mechanism::SxoverPlus.into(), - (XOAUTH, b"") => Mechanism::Xoauth.into(), - (XOAUTH2, b"") => Mechanism::Xoauth2.into(), + (_9798_M_DSA_SHA1, b"") => AUTH_9798_M_DSA_SHA1.into(), + (_9798_M_ECDSA_SHA, b"1") => AUTH_9798_M_ECDSA_SHA1.into(), + (_9798_M_RSA_SHA1_, b"ENC") => AUTH_9798_M_RSA_SHA1_ENC.into(), + (_9798_U_DSA_SHA1, b"") => AUTH_9798_U_DSA_SHA1.into(), + (_9798_U_ECDSA_SHA, b"1") => AUTH_9798_U_ECDSA_SHA1.into(), + (_9798_U_RSA_SHA1_, b"ENC") => AUTH_9798_U_RSA_SHA1_ENC.into(), + (ANONYMOUS, b"") => AUTH_ANONYMOUS.into(), + (CRAM_MD5, b"") => AUTH_CRAM_MD5.into(), + (DIGEST_MD5, b"") => AUTH_DIGEST_MD5.into(), + (EAP_AES128, b"") => AUTH_EAP_AES128.into(), + (EAP_AES128_PLUS, b"") => AUTH_EAP_AES128_PLUS.into(), + (ECDH_X25519_CHAL, b"LENGE") => AUTH_ECDH_X25519_CHALLENGE.into(), + (ECDSA_NIST256P_C, b"HALLENGE") => AUTH_ECDSA_NIST256P_CHALLENGE.into(), + (EXTERNAL, b"") => AUTH_EXTERNAL.into(), + (GS2_KRB5, b"") => AUTH_GS2_KRB5.into(), + (GS2_KRB5_PLUS, b"") => AUTH_GS2_KRB5_PLUS.into(), + (GSS_SPNEGO, b"") => AUTH_GSS_SPNEGO.into(), + (GSSAPI, b"") => AUTH_GSSAPI.into(), + (KERBEROS_V4, b"") => AUTH_KERBEROS_V4.into(), + (KERBEROS_V5, b"") => AUTH_KERBEROS_V5.into(), + (LOGIN, b"") => AUTH_LOGIN.into(), + (NMAS_SAMBA_AUTH, b"") => AUTH_NMAS_SAMBA_AUTH.into(), + (NMAS_AUTHEN, b"") => AUTH_NMAS_AUTHEN.into(), + (NMAS_LOGIN, b"") => AUTH_NMAS_LOGIN.into(), + (NTLM, b"") => AUTH_NTLM.into(), + (OAUTH10A, b"") => AUTH_OAUTH10A.into(), + (OAUTHBEARER, b"") => AUTH_OAUTHBEARER.into(), + (OPENID20, b"") => AUTH_OPENID20.into(), + (OTP, b"") => AUTH_OTP.into(), + (PLAIN, b"") => AUTH_PLAIN.into(), + (SAML20, b"") => AUTH_SAML20.into(), + (SCRAM_SHA_1, b"") => AUTH_SCRAM_SHA_1.into(), + (SCRAM_SHA_1_PLUS, b"") => AUTH_SCRAM_SHA_1_PLUS.into(), + (SCRAM_SHA_256, b"") => AUTH_SCRAM_SHA_256.into(), + (SCRAM_SHA_256_PL, b"US") => AUTH_SCRAM_SHA_256_PLUS.into(), + (SECURID, b"") => AUTH_SECURID.into(), + (SKEY, b"") => AUTH_SKEY.into(), + (SPNEGO, b"") => AUTH_SPNEGO.into(), + (SPNEGO_PLUS, b"") => AUTH_SPNEGO_PLUS.into(), + (SXOVER_PLUS, b"") => AUTH_SXOVER_PLUS.into(), + (XOAUTH, b"") => AUTH_XOAUTH.into(), + (XOAUTH2, b"") => AUTH_XOAUTH2.into(), (0, b"") => None, - _ => Mechanism::Unknown.into(), + _ => 0.into(), }) } } @@ -1137,8 +1134,9 @@ impl TryFrom for Body { #[cfg(test)] mod tests { use crate::{ - request::receiver::ReceiverParser, Body, By, Error, Mechanism, Mtrk, Orcpt, Parameter, - Request, Ret, Rrvs, NOTIFY_DELAY, NOTIFY_FAILURE, NOTIFY_SUCCESS, + request::receiver::ReceiverParser, Body, By, Error, Mtrk, Orcpt, Parameter, Request, Ret, + Rrvs, AUTH_ECDSA_NIST256P_CHALLENGE, AUTH_GSSAPI, AUTH_SCRAM_SHA_256_PLUS, NOTIFY_DELAY, + NOTIFY_FAILURE, NOTIFY_SUCCESS, }; #[test] @@ -1312,28 +1310,28 @@ mod tests { ( "AUTH GSSAPI", Ok(Request::Auth { - mechanism: Mechanism::Gssapi, + mechanism: AUTH_GSSAPI, initial_response: "".to_string(), }), ), ( "AUTH ECDSA-NIST256P-CHALLENGE =", Ok(Request::Auth { - mechanism: Mechanism::EcdsaNist256pChallenge, + mechanism: AUTH_ECDSA_NIST256P_CHALLENGE, initial_response: "=".to_string(), }), ), ( "AUTH SCRAM-SHA-256-PLUS base64_goes_here", Ok(Request::Auth { - mechanism: Mechanism::ScramSha256Plus, + mechanism: AUTH_SCRAM_SHA_256_PLUS, initial_response: "base64_goes_here".to_string(), }), ), ( "AUTH ECDSA-NIST256P-CHALLENGE100 abcde", Ok(Request::Auth { - mechanism: Mechanism::Unknown, + mechanism: 0, initial_response: "abcde".to_string(), }), ), diff --git a/src/response/generate.rs b/src/response/generate.rs index cb66790..bdfc82f 100644 --- a/src/response/generate.rs +++ b/src/response/generate.rs @@ -3,7 +3,7 @@ use std::{ io::{self, Write}, }; -use crate::{Capability, Category, EhloResponse, Mechanism, MtPriority, Response, Severity}; +use crate::*; impl EhloResponse { pub fn write(&self, mut writer: impl Write) -> io::Result<()> { @@ -17,8 +17,11 @@ impl EhloResponse { Capability::Atrn => write!(writer, "ATRN\r\n"), Capability::Auth { mechanisms } => { writer.write_all(b"AUTH")?; - for mechanism in mechanisms { - write!(writer, " {}", mechanism)?; + let mut mechanisms = *mechanisms; + while mechanisms != 0 { + let item = 63 - mechanisms.leading_zeros(); + mechanisms ^= 1 << item; + write!(writer, " {}", (item as u64).as_mechanism())?; } writer.write_all(b"\r\n") } @@ -55,6 +58,7 @@ impl EhloResponse { MtPriority::Mixer => "MIXER", MtPriority::Stanag4406 => "STANAG4406", MtPriority::Nsep => "NSEP", + MtPriority::None => "MIXER", } ), Capability::Mtrk => write!(writer, "MTRK\r\n"), @@ -102,53 +106,57 @@ impl Response { } } -impl Display for Mechanism { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(match self { - Mechanism::_9798MDsaSha1 => "9798-M-DSA-SHA1", - Mechanism::_9798MEcdsaSha1 => "9798-M-ECDSA-SHA1", - Mechanism::_9798MRsaSha1Enc => "9798-M-RSA-SHA1-ENC", - Mechanism::_9798UDsaSha1 => "9798-U-DSA-SHA1", - Mechanism::_9798UEcdsaSha1 => "9798-U-ECDSA-SHA1", - Mechanism::_9798URsaSha1Enc => "9798-U-RSA-SHA1-ENC", - Mechanism::Anonymous => "ANONYMOUS", - Mechanism::CramMd5 => "CRAM-MD5", - Mechanism::DigestMd5 => "DIGEST-MD5", - Mechanism::EapAes128 => "EAP-AES128", - Mechanism::EapAes128Plus => "EAP-AES128-PLUS", - Mechanism::EcdhX25519Challenge => "ECDH-X25519-CHALLENGE", - Mechanism::EcdsaNist256pChallenge => "ECDSA-NIST256P-CHALLENGE", - Mechanism::External => "EXTERNAL", - Mechanism::Gs2Krb5 => "GS2-KRB5", - Mechanism::Gs2Krb5Plus => "GS2-KRB5-PLUS", - Mechanism::GssSpnego => "GSS-SPNEGO", - Mechanism::Gssapi => "GSSAPI", - Mechanism::KerberosV4 => "KERBEROS_V4", - Mechanism::KerberosV5 => "KERBEROS_V5", - Mechanism::Login => "LOGIN", - Mechanism::NmasSambaAuth => "NMAS-SAMBA-AUTH", - Mechanism::NmasAuthen => "NMAS_AUTHEN", - Mechanism::NmasLogin => "NMAS_LOGIN", - Mechanism::Ntlm => "NTLM", - Mechanism::Oauth10a => "OAUTH10A", - Mechanism::Oauthbearer => "OAUTHBEARER", - Mechanism::Openid20 => "OPENID20", - Mechanism::Otp => "OTP", - Mechanism::Plain => "PLAIN", - Mechanism::Saml20 => "SAML20", - Mechanism::ScramSha1 => "SCRAM-SHA-1", - Mechanism::ScramSha1Plus => "SCRAM-SHA-1-PLUS", - Mechanism::ScramSha256 => "SCRAM-SHA-256", - Mechanism::ScramSha256Plus => "SCRAM-SHA-256-PLUS", - Mechanism::Securid => "SECURID", - Mechanism::Skey => "SKEY", - Mechanism::Spnego => "SPNEGO", - Mechanism::SpnegoPlus => "SPNEGO-PLUS", - Mechanism::SxoverPlus => "SXOVER-PLUS", - Mechanism::Xoauth => "XOAUTH", - Mechanism::Xoauth2 => "XOAUTH2", - Mechanism::Unknown => "", - }) +trait AsMechanism { + fn as_mechanism(&self) -> &'static str; +} + +impl AsMechanism for u64 { + fn as_mechanism(&self) -> &'static str { + match *self { + AUTH_SCRAM_SHA_256_PLUS => "SCRAM-SHA-256-PLUS", + AUTH_SCRAM_SHA_256 => "SCRAM-SHA-256", + AUTH_SCRAM_SHA_1_PLUS => "SCRAM-SHA-1-PLUS", + AUTH_SCRAM_SHA_1 => "SCRAM-SHA-1", + AUTH_OAUTHBEARER => "OAUTHBEARER", + AUTH_XOAUTH => "XOAUTH", + AUTH_XOAUTH2 => "XOAUTH2", + AUTH_9798_M_DSA_SHA1 => "9798-M-DSA-SHA1", + AUTH_9798_M_ECDSA_SHA1 => "9798-M-ECDSA-SHA1", + AUTH_9798_M_RSA_SHA1_ENC => "9798-M-RSA-SHA1-ENC", + AUTH_9798_U_DSA_SHA1 => "9798-U-DSA-SHA1", + AUTH_9798_U_ECDSA_SHA1 => "9798-U-ECDSA-SHA1", + AUTH_9798_U_RSA_SHA1_ENC => "9798-U-RSA-SHA1-ENC", + AUTH_EAP_AES128 => "EAP-AES128", + AUTH_EAP_AES128_PLUS => "EAP-AES128-PLUS", + AUTH_ECDH_X25519_CHALLENGE => "ECDH-X25519-CHALLENGE", + AUTH_ECDSA_NIST256P_CHALLENGE => "ECDSA-NIST256P-CHALLENGE", + AUTH_EXTERNAL => "EXTERNAL", + AUTH_GS2_KRB5 => "GS2-KRB5", + AUTH_GS2_KRB5_PLUS => "GS2-KRB5-PLUS", + AUTH_GSS_SPNEGO => "GSS-SPNEGO", + AUTH_GSSAPI => "GSSAPI", + AUTH_KERBEROS_V4 => "KERBEROS_V4", + AUTH_KERBEROS_V5 => "KERBEROS_V5", + AUTH_NMAS_SAMBA_AUTH => "NMAS-SAMBA-AUTH", + AUTH_NMAS_AUTHEN => "NMAS_AUTHEN", + AUTH_NMAS_LOGIN => "NMAS_LOGIN", + AUTH_NTLM => "NTLM", + AUTH_OAUTH10A => "OAUTH10A", + AUTH_OPENID20 => "OPENID20", + AUTH_OTP => "OTP", + AUTH_SAML20 => "SAML20", + AUTH_SECURID => "SECURID", + AUTH_SKEY => "SKEY", + AUTH_SPNEGO => "SPNEGO", + AUTH_SPNEGO_PLUS => "SPNEGO-PLUS", + AUTH_SXOVER_PLUS => "SXOVER-PLUS", + AUTH_CRAM_MD5 => "CRAM-MD5", + AUTH_DIGEST_MD5 => "DIGEST-MD5", + AUTH_LOGIN => "LOGIN", + AUTH_PLAIN => "PLAIN", + AUTH_ANONYMOUS => "ANONYMOUS", + _ => "", + } } } diff --git a/src/response/parser.rs b/src/response/parser.rs index 7f73b40..ab861ad 100644 --- a/src/response/parser.rs +++ b/src/response/parser.rs @@ -57,10 +57,10 @@ impl ReceiverParser for EhloResponse { _8BITMIME => Capability::EightBitMime, ATRN => Capability::Atrn, AUTH => { - let mut mechanisms = Vec::new(); + let mut mechanisms = 0; while parser.stop_char != LF { if let Some(mechanism) = parser.mechanism()? { - mechanisms.push(mechanism); + mechanisms |= mechanism; } } @@ -306,10 +306,7 @@ impl Capability { } else if value.eq_ignore_ascii_case(b"ATRN") { Capability::Atrn.into() } else if value.eq_ignore_ascii_case(b"AUTH") { - Capability::Auth { - mechanisms: Vec::new(), - } - .into() + Capability::Auth { mechanisms: 0 }.into() } else if value.eq_ignore_ascii_case(b"BINARYMIME") { Capability::BinaryMime.into() } else if value.eq_ignore_ascii_case(b"BURL") { @@ -374,8 +371,8 @@ impl Capability { #[cfg(test)] mod tests { use crate::{ - request::receiver::ReceiverParser, Capability, EhloResponse, Error, Mechanism, MtPriority, - Response, + request::receiver::ReceiverParser, Capability, EhloResponse, Error, MtPriority, Response, + AUTH_DIGEST_MD5, AUTH_GSSAPI, AUTH_PLAIN, }; #[test] @@ -424,11 +421,7 @@ mod tests { Capability::EightBitMime, Capability::Atrn, Capability::Auth { - mechanisms: vec![ - Mechanism::Gssapi, - Mechanism::DigestMd5, - Mechanism::Plain, - ], + mechanisms: AUTH_GSSAPI | AUTH_DIGEST_MD5 | AUTH_PLAIN, }, Capability::BinaryMime, Capability::Burl,