From cee4149ef4d693dc0d53898b20da496065f8d541 Mon Sep 17 00:00:00 2001 From: mdecimus Date: Fri, 16 May 2025 16:44:37 +0200 Subject: [PATCH] RFC9698 - JMAPACCESS Extension for IMAP --- crates/cli/src/modules/import.rs | 4 +--- crates/common/src/listener/acme/directory.rs | 2 +- crates/common/src/telemetry/tracers/journald.rs | 3 +-- crates/directory/src/core/principal.rs | 2 +- crates/imap-proto/src/protocol/capability.rs | 3 +++ crates/imap/src/op/fetch.rs | 4 ++-- crates/imap/src/op/status.rs | 3 +-- crates/jmap/src/blob/get.rs | 3 +-- crates/smtp/src/inbound/mail.rs | 6 +----- crates/smtp/src/outbound/client.rs | 1 + crates/smtp/src/reporting/mod.rs | 2 +- crates/store/src/backend/azure/mod.rs | 2 +- crates/store/src/backend/mysql/write.rs | 3 +-- crates/store/src/backend/s3/mod.rs | 2 +- crates/utils/src/codec/base32_custom.rs | 2 +- 15 files changed, 18 insertions(+), 24 deletions(-) diff --git a/crates/cli/src/modules/import.rs b/crates/cli/src/modules/import.rs index d34175bc..f0fb1448 100644 --- a/crates/cli/src/modules/import.rs +++ b/crates/cli/src/modules/import.rs @@ -1019,9 +1019,7 @@ impl Iterator for Mailbox { internal_date: m.internal_date(), contents: m.unwrap_contents(), }) - .map_err(|_| { - io::Error::new(io::ErrorKind::Other, "Failed to parse from mbox file.") - }) + .map_err(|_| std::io::Error::other("Failed to parse from mbox file.")) }), Mailbox::Maildir(it) => it.next().map(|r| { r.map(|m| Message { diff --git a/crates/common/src/listener/acme/directory.rs b/crates/common/src/listener/acme/directory.rs index 024e15c2..3dda1677 100644 --- a/crates/common/src/listener/acme/directory.rs +++ b/crates/common/src/listener/acme/directory.rs @@ -347,7 +347,7 @@ async fn https( } fn get_header(response: &Response, header: &'static str) -> trc::Result { - match response.headers().get_all(header).iter().last() { + match response.headers().get_all(header).iter().next_back() { Some(value) => Ok(value .to_str() .map_err(|err| trc::EventType::Acme(trc::AcmeEvent::Error).from_http_str_error(err))? diff --git a/crates/common/src/telemetry/tracers/journald.rs b/crates/common/src/telemetry/tracers/journald.rs index c252fc58..670ba906 100644 --- a/crates/common/src/telemetry/tracers/journald.rs +++ b/crates/common/src/telemetry/tracers/journald.rs @@ -258,8 +258,7 @@ impl Subscriber { #[cfg(all(unix, not(target_os = "linux")))] fn send_large_payload(&self, _payload: &[u8]) -> io::Result { - Err(io::Error::new( - io::ErrorKind::Other, + Err(std::io::Error::other( "Large payloads not supported on non-Linux OS", )) } diff --git a/crates/directory/src/core/principal.rs b/crates/directory/src/core/principal.rs index bff4f417..0b9c51d8 100644 --- a/crates/directory/src/core/principal.rs +++ b/crates/directory/src/core/principal.rs @@ -602,7 +602,7 @@ impl PrincipalSet { pub fn has_int_value(&self, key: PrincipalField, value: u64) -> bool { self.fields.get(&key).is_some_and(|v| match v { PrincipalValue::Integer(v) => *v == value, - PrincipalValue::IntegerList(l) => l.iter().any(|v| *v == value), + PrincipalValue::IntegerList(l) => l.contains(&value), PrincipalValue::String(_) | PrincipalValue::StringList(_) => false, }) } diff --git a/crates/imap-proto/src/protocol/capability.rs b/crates/imap-proto/src/protocol/capability.rs index 4c8ef088..c0ff30f0 100644 --- a/crates/imap-proto/src/protocol/capability.rs +++ b/crates/imap-proto/src/protocol/capability.rs @@ -52,6 +52,7 @@ pub enum Capability { Quota, QuotaResource(QuotaResourceName), QuotaSet, + JmapAccess, } /* @@ -126,6 +127,7 @@ impl Capability { return; } Capability::QuotaSet => b"QUOTA=SET", + Capability::JmapAccess => b"JMAPACCESS", }); } @@ -138,6 +140,7 @@ impl Capability { Capability::LiteralPlus, Capability::Id, Capability::Utf8Accept, + Capability::JmapAccess, ]; if is_authenticated { diff --git a/crates/imap/src/op/fetch.rs b/crates/imap/src/op/fetch.rs index c7de2ee2..803fa711 100644 --- a/crates/imap/src/op/fetch.rs +++ b/crates/imap/src/op/fetch.rs @@ -500,12 +500,12 @@ impl SessionData { } Attribute::EmailId => { items.push(DataItem::EmailId { - email_id: Id::from_parts(account_id, id).to_string(), + email_id: Id::from_parts(data.thread_id, id).to_string(), }); } Attribute::ThreadId => { items.push(DataItem::ThreadId { - thread_id: Id::from_parts(account_id, data.thread_id).to_string(), + thread_id: Id::from_parts(0, data.thread_id).to_string(), }); } } diff --git a/crates/imap/src/op/status.rs b/crates/imap/src/op/status.rs index b574497f..b1f2df23 100644 --- a/crates/imap/src/op/status.rs +++ b/crates/imap/src/op/status.rs @@ -192,8 +192,7 @@ impl SessionData { items_response.push(( *item, StatusItemType::String( - Id::from_parts(mailbox.account_id, mailbox.mailbox_id) - .to_string(), + Id::from_parts(0, mailbox.mailbox_id).to_string(), ), )); } diff --git a/crates/jmap/src/blob/get.rs b/crates/jmap/src/blob/get.rs index 563a31db..4a6794bd 100644 --- a/crates/jmap/src/blob/get.rs +++ b/crates/jmap/src/blob/get.rs @@ -85,8 +85,7 @@ impl BlobOperations for Server { } else { range_to }; - let bytes_range = bytes.get(range_from..range_to).unwrap_or_default(); - bytes_range + bytes.get(range_from..range_to).unwrap_or_default() }; for property in &properties { diff --git a/crates/smtp/src/inbound/mail.rs b/crates/smtp/src/inbound/mail.rs index 23dc6987..87a4bb7f 100644 --- a/crates/smtp/src/inbound/mail.rs +++ b/crates/smtp/src/inbound/mail.rs @@ -392,11 +392,7 @@ impl Session { let now = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .map_or(0, |d| d.as_secs()); - if from.hold_until > now { - from.hold_until - now - } else { - 0 - } + from.hold_until.saturating_sub(now) }; if hold_for <= max_hold { self.data.future_release = hold_for; diff --git a/crates/smtp/src/outbound/client.rs b/crates/smtp/src/outbound/client.rs index 78245720..be5ca6e9 100644 --- a/crates/smtp/src/outbound/client.rs +++ b/crates/smtp/src/outbound/client.rs @@ -604,6 +604,7 @@ impl SmtpClient> { } } +#[allow(clippy::large_enum_variant)] pub enum StartTlsResult { Success { smtp_client: SmtpClient>, diff --git a/crates/smtp/src/reporting/mod.rs b/crates/smtp/src/reporting/mod.rs index 3c8be044..db313d3b 100644 --- a/crates/smtp/src/reporting/mod.rs +++ b/crates/smtp/src/reporting/mod.rs @@ -321,7 +321,7 @@ impl io::Write for SerializedSize { self.bytes_left -= buf_len; Ok(buf_len) } else { - Err(io::Error::new(io::ErrorKind::Other, "Size exceeded")) + Err(io::Error::other("Size exceeded")) } } diff --git a/crates/store/src/backend/azure/mod.rs b/crates/store/src/backend/azure/mod.rs index e154a1ab..8bbaea07 100644 --- a/crates/store/src/backend/azure/mod.rs +++ b/crates/store/src/backend/azure/mod.rs @@ -193,7 +193,7 @@ impl AzureStore { fn build_key(&self, key: &[u8]) -> String { if let Some(prefix) = &self.prefix { let mut writer = - Base32Writer::with_raw_capacity(prefix.len() + ((key.len() + 3) / 4 * 5)); + Base32Writer::with_raw_capacity(prefix.len() + (key.len().div_ceil(4) * 5)); writer.push_string(prefix); writer.write_all(key).unwrap(); writer.finalize() diff --git a/crates/store/src/backend/mysql/write.rs b/crates/store/src/backend/mysql/write.rs index 2fd10b1d..afaae2ea 100644 --- a/crates/store/src/backend/mysql/write.rs +++ b/crates/store/src/backend/mysql/write.rs @@ -174,8 +174,7 @@ impl MysqlStore { result.push_counter_id( trx.exec_first::(&s, ()).await?.ok_or_else(|| { mysql_async::Error::Io(mysql_async::IoError::Io( - std::io::Error::new( - std::io::ErrorKind::Other, + std::io::Error::other( "LAST_INSERT_ID() did not return a value", ), )) diff --git a/crates/store/src/backend/s3/mod.rs b/crates/store/src/backend/s3/mod.rs index bdb54dd8..f0e4d87c 100644 --- a/crates/store/src/backend/s3/mod.rs +++ b/crates/store/src/backend/s3/mod.rs @@ -179,7 +179,7 @@ impl S3Store { fn build_key(&self, key: &[u8]) -> String { if let Some(prefix) = &self.prefix { let mut writer = - Base32Writer::with_raw_capacity(prefix.len() + ((key.len() + 3) / 4 * 5)); + Base32Writer::with_raw_capacity(prefix.len() + (key.len().div_ceil(4) * 5)); writer.push_string(prefix); writer.write_all(key).unwrap(); writer.finalize() diff --git a/crates/utils/src/codec/base32_custom.rs b/crates/utils/src/codec/base32_custom.rs index b6609b4a..497cb8fa 100644 --- a/crates/utils/src/codec/base32_custom.rs +++ b/crates/utils/src/codec/base32_custom.rs @@ -40,7 +40,7 @@ impl Base32Writer { } pub fn with_capacity(capacity: usize) -> Self { - Self::with_raw_capacity((capacity + 3) / 4 * 5) + Self::with_raw_capacity(capacity.div_ceil(4) * 5) } pub fn with_raw_capacity(capacity: usize) -> Self {