diff --git a/Cargo.lock b/Cargo.lock index e8b500f..1b7c730 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -103,9 +103,9 @@ checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +checksum = "f02882884d3e1bc524fb12c79f107f6ad0e1cfd498c536ffb494301740995dfe" [[package]] name = "assert-json-diff" @@ -384,9 +384,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.64" +version = "1.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", "jobserver", @@ -1487,9 +1487,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" [[package]] name = "mail-builder" @@ -1499,9 +1499,9 @@ checksum = "900998f307338c4013a28ab14d760b784067324b164448c6d98a89e44810473b" [[package]] name = "mail-parser" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a2420e9ce11c2b0583ca97ddff7ab2398c8a613154e9b72e3bafdbf767f1d7" +checksum = "f2c0e7e0704500930be5b6c629f30d23fd1dde4d1800e138e04b3fa302e64d51" dependencies = [ "hashify", ] diff --git a/src/dav/discover.rs b/src/dav/discover.rs index eab0d4f..d87f851 100644 --- a/src/dav/discover.rs +++ b/src/dav/discover.rs @@ -131,6 +131,10 @@ fn try_treat_url_as_home_or_collection( { return Ok(None); } + Err(DiscoveryError::Transport(JmapError::Malformed(_))) + | Err(DiscoveryError::Transport(JmapError::RetriesExhausted(_))) => { + return Ok(None); + } Err(e) => return Err(e), }; if collections.is_empty() { @@ -158,7 +162,7 @@ fn resolve_principal_url( Err(JmapError::HttpStatus { status, .. }) if (400..600).contains(&status) => { return Ok(None); } - Err(JmapError::RetriesExhausted(_)) => return Ok(None), + Err(JmapError::RetriesExhausted(_)) | Err(JmapError::Malformed(_)) => return Ok(None), Err(e) => return Err(DiscoveryError::Transport(e)), }; let final_url = ms.final_url.clone(); @@ -186,7 +190,7 @@ fn try_via_principal( Err(JmapError::HttpStatus { status, .. }) if (400..600).contains(&status) => { return Ok(None); } - Err(JmapError::RetriesExhausted(_)) => return Ok(None), + Err(JmapError::RetriesExhausted(_)) | Err(JmapError::Malformed(_)) => return Ok(None), Err(e) => return Err(DiscoveryError::Transport(e)), }; let first_final_url = first_ms.final_url.clone(); @@ -217,7 +221,9 @@ fn try_via_principal( Err(JmapError::HttpStatus { status, .. }) if (400..600).contains(&status) => { return Ok(None); } - Err(JmapError::RetriesExhausted(_)) => return Ok(None), + Err(JmapError::RetriesExhausted(_)) | Err(JmapError::Malformed(_)) => { + return Ok(None) + } Err(e) => return Err(DiscoveryError::Transport(e)), }; let principal_after_redirect = home_ms.final_url.clone(); diff --git a/tests/seed_smoke.rs b/tests/seed_smoke.rs index fba196f..5475b25 100644 --- a/tests/seed_smoke.rs +++ b/tests/seed_smoke.rs @@ -14,6 +14,7 @@ use serde_json::{Value, json}; const CORE: &str = "urn:ietf:params:jmap:core"; const MAIL: &str = "urn:ietf:params:jmap:mail"; +const SUBMISSION: &str = "urn:ietf:params:jmap:submission"; const SIEVE: &str = "urn:ietf:params:jmap:sieve"; const CONTACTS: &str = "urn:ietf:params:jmap:contacts"; const CALENDARS: &str = "urn:ietf:params:jmap:calendars"; @@ -110,7 +111,7 @@ fn verify_account(label: &str, user: &Jmap, account_id: &str, s: &SeedStats) { let identities = user .call( - &[CORE, MAIL], + &[CORE, SUBMISSION], "Identity/get", account_id, json!({ "properties": ["id", "name"] }), diff --git a/tests/seeder/data.rs b/tests/seeder/data.rs index c693059..e7ee39c 100644 --- a/tests/seeder/data.rs +++ b/tests/seeder/data.rs @@ -35,10 +35,11 @@ pub fn load_mbox(limit: usize) -> SeedResult> { for item in MessageIterator::new(reader) { let message = item.map_err(|e| SeedError::Resource(format!("mbox parse: {e}")))?; let received_at = message.internal_date() as i64; - out.push(MboxMessage { - raw: message.unwrap_contents(), - received_at, - }); + let raw = message.unwrap_contents(); + if !starts_with_header(&raw) { + continue; + } + out.push(MboxMessage { raw, received_at }); if out.len() >= limit { break; } @@ -49,6 +50,27 @@ pub fn load_mbox(limit: usize) -> SeedResult> { Ok(out) } +fn starts_with_header(raw: &[u8]) -> bool { + let mut rest = raw; + if rest.starts_with(b"From ") { + match rest.iter().position(|b| *b == b'\n') { + Some(nl) => rest = &rest[nl + 1..], + None => return false, + } + } + let line_end = rest.iter().position(|b| *b == b'\n').unwrap_or(rest.len()); + let line = &rest[..line_end]; + let Some(colon) = line.iter().position(|b| *b == b':') else { + return false; + }; + if colon == 0 { + return false; + } + line[..colon] + .iter() + .all(|b| b.is_ascii_graphic() && *b != b':') +} + fn read_dir_sorted(sub: &str, ext: &str) -> SeedResult> { let dir = resources_dir().join(sub); let mut paths: Vec = std::fs::read_dir(&dir)?