#[cfg(feature = "builder")]
use crate::SpfBuilder;
#[cfg(test)]
mod tests;
#[cfg(feature = "builder")]
mod validate_builder;
mod validate_string;
use crate::core::{self, spf_check_whitespace};
use crate::spf::SpfError;
pub trait Validate {
fn validate_version(&self) -> Result<(), SpfError> {
Ok(())
}
fn validate_length(&self) -> Result<(), SpfError>;
fn validate_ptr(&self) -> Result<(), SpfError> {
Ok(())
}
fn validate_redirect_all(&self) -> Result<(), SpfError>;
fn validate_lookup_count(&self) -> Result<(), SpfError>;
}
pub(crate) fn check_start_of_spf(spf_string: &str) -> Result<(), SpfError> {
if spf_string.starts_with(core::SPF1)
|| spf_string.starts_with(core::SPF2_PRA)
|| spf_string.starts_with(core::SPF2_MFROM)
|| spf_string.starts_with(core::SPF2_PRA_MFROM)
|| spf_string.starts_with(core::SPF2_MFROM_PRA)
{
Ok(())
} else {
Err(SpfError::InvalidVersion)
}
}
#[test]
fn valid_versions() {
let input = vec![
core::SPF1,
core::SPF2_PRA,
core::SPF2_MFROM,
core::SPF2_PRA_MFROM,
core::SPF2_MFROM_PRA,
];
for v in input.into_iter() {
assert_eq!(check_start_of_spf(v), Ok(()))
}
}
pub(crate) fn check_whitespaces(spf_string: &str) -> Result<(), SpfError> {
if spf_check_whitespace(spf_string) {
return Err(SpfError::WhiteSpaceSyntaxError);
};
Ok(())
}
pub(crate) fn check_spf_length(spf_string: &str) -> Result<(), SpfError> {
if spf_string.len() > core::MAX_SPF_STRING_LENGTH {
return Err(SpfError::SourceLengthExceeded);
};
Ok(())
}
#[cfg(feature = "ptr")]
#[cfg(feature = "builder")]
#[allow(dead_code)]
pub(crate) fn check_ptr(spf: &SpfBuilder) -> Result<(), SpfError> {
match spf.ptr() {
Some(_) => Err(SpfError::DeprecatedPtrDetected),
None => Ok(()),
}
}
#[cfg(feature = "builder")]
#[allow(dead_code)]
pub(crate) fn check_redirect_all(spf: &SpfBuilder) -> Result<(), SpfError> {
if spf.redirect().is_some() && spf.all().is_some() {
return Err(SpfError::RedirectWithAllMechanism);
}
Ok(())
}
#[cfg(feature = "builder")]
#[allow(dead_code)]
pub(crate) fn check_lookup_count(spf: &SpfBuilder) -> usize {
let mut lookup_count: usize = 0;
if spf.redirect().is_some() {
lookup_count += 1;
}
if let Some(a) = spf.a() {
lookup_count += a.len();
}
if let Some(mx) = spf.mx() {
lookup_count += mx.len();
}
if let Some(includes) = spf.includes() {
lookup_count += includes.len();
}
lookup_count
}