Import upstream v0.16.22, stripped

Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f
Enterprise-only files removed or emptied: 63
Enterprise-only snippets removed: 117 in 50 files
Dangling module declarations removed: 5
Cargo edits turning enterprise off: 14
Verification: clean
Enterprise feature gates left for rebuilt features: 19 in 18 files

Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
2026-09-18 10:21:56 -07:00
commit 7dae9b29fd
1650 changed files with 485521 additions and 0 deletions
+251
View File
@@ -0,0 +1,251 @@
/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use crate::{ResponseCode, StatusResponse};
use super::{ImapResponse, ObjectId, Sequence, list::ListItem};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Arguments {
pub tag: String,
pub mailbox_name: String,
pub condstore: bool,
pub qresync: Option<QResync>,
pub objectid: Option<ObjectId>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct QResync {
pub uid_validity: u32,
pub modseq: u64,
pub known_uids: Option<Sequence>,
pub seq_match: Option<(Sequence, Sequence)>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HighestModSeq(u64);
#[derive(Debug, Clone)]
pub struct Response {
pub mailbox: ListItem,
pub total_messages: usize,
pub recent_messages: usize,
pub unseen_seq: u32,
pub uid_validity: u32,
pub uid_next: u32,
pub is_rev2: bool,
pub is_utf8: bool,
pub closed_previous: bool,
pub highest_modseq: Option<HighestModSeq>,
pub objectid: Option<ObjectId>,
}
#[derive(Debug, Clone)]
pub struct Exists {
pub total_messages: usize,
}
impl ImapResponse for Response {
fn serialize(self) -> Vec<u8> {
let mut buf = Vec::with_capacity(100);
if self.closed_previous {
buf = StatusResponse::ok("Closed previous mailbox")
.with_code(ResponseCode::Closed)
.serialize(buf);
}
buf.extend_from_slice(b"* ");
buf.extend_from_slice(self.total_messages.to_string().as_bytes());
if !self.is_rev2 && self.recent_messages > 0 {
buf.extend_from_slice(
b" EXISTS\r\n* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft \\Recent)\r\n",
);
} else {
buf.extend_from_slice(
b" EXISTS\r\n* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n",
);
}
if self.is_rev2 {
self.mailbox
.serialize(&mut buf, self.is_rev2, self.is_utf8, false);
} else {
buf.extend_from_slice(b"* ");
buf.extend_from_slice(self.recent_messages.to_string().as_bytes());
buf.extend_from_slice(b" RECENT\r\n");
if self.unseen_seq > 0 {
buf.extend_from_slice(b"* OK [UNSEEN ");
buf.extend_from_slice(self.unseen_seq.to_string().as_bytes());
buf.extend_from_slice(b"] Unseen messages\r\n");
}
}
buf.extend_from_slice(
b"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
);
buf.extend_from_slice(b"* OK [UIDVALIDITY ");
buf.extend_from_slice(self.uid_validity.to_string().as_bytes());
buf.extend_from_slice(b"] UIDs valid\r\n* OK [UIDNEXT ");
buf.extend_from_slice(self.uid_next.to_string().as_bytes());
buf.extend_from_slice(b"] Next predicted UID\r\n");
if let Some(highest_modseq) = self.highest_modseq {
highest_modseq.serialize(&mut buf);
}
if let Some(objectid) = &self.objectid {
buf.extend_from_slice(b"* OK [");
objectid.serialize(&mut buf);
buf.extend_from_slice(b"] Object identifiers\r\n");
}
buf
}
}
impl HighestModSeq {
pub fn new(modseq: u64) -> Self {
Self(modseq)
}
pub fn serialize(&self, buf: &mut Vec<u8>) {
buf.extend_from_slice(b"* OK [HIGHESTMODSEQ ");
buf.extend_from_slice(self.0.to_string().as_bytes());
buf.extend_from_slice(b"] Highest Modseq\r\n");
}
pub fn into_bytes(self) -> Vec<u8> {
let mut buf = Vec::with_capacity(40);
self.serialize(&mut buf);
buf
}
}
impl Exists {
pub fn serialize(&self, buf: &mut Vec<u8>) {
buf.extend_from_slice(b"* ");
buf.extend_from_slice(self.total_messages.to_string().as_bytes());
buf.extend_from_slice(b" EXISTS\r\n");
}
pub fn into_bytes(self) -> Vec<u8> {
let mut buf = Vec::with_capacity(15);
self.serialize(&mut buf);
buf
}
}
#[cfg(test)]
mod tests {
use crate::protocol::{ImapResponse, ObjectId, list::ListItem};
use types::id::Id;
use super::HighestModSeq;
#[test]
fn serialize_select() {
let objectid = ObjectId {
mailbox_id: Some(Id::from(1u32)),
account_id: Some(Id::from(2u32)),
..Default::default()
};
let mut objectid_line = b"* OK [".to_vec();
objectid.serialize(&mut objectid_line);
objectid_line.extend_from_slice(b"] Object identifiers\r\n");
let objectid_line = String::from_utf8(objectid_line).unwrap();
for (mut response, _tag, expected_v2, expected_v1) in [
(
super::Response {
mailbox: ListItem::new("INBOX"),
total_messages: 172,
recent_messages: 5,
unseen_seq: 3,
uid_validity: 3857529045,
uid_next: 4392,
closed_previous: false,
is_rev2: true,
is_utf8: true,
highest_modseq: HighestModSeq::new(100).into(),
objectid: Some(objectid.clone()),
},
"A142",
format!(
concat!(
"* 172 EXISTS\r\n",
"* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n",
"* LIST () \"/\" \"INBOX\"\r\n",
"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
"* OK [UIDVALIDITY 3857529045] UIDs valid\r\n",
"* OK [UIDNEXT 4392] Next predicted UID\r\n",
"* OK [HIGHESTMODSEQ 100] Highest Modseq\r\n",
"{}"
),
objectid_line
),
format!(
concat!(
"* 172 EXISTS\r\n",
"* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft \\Recent)\r\n",
"* 5 RECENT\r\n",
"* OK [UNSEEN 3] Unseen messages\r\n",
"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
"* OK [UIDVALIDITY 3857529045] UIDs valid\r\n",
"* OK [UIDNEXT 4392] Next predicted UID\r\n",
"* OK [HIGHESTMODSEQ 100] Highest Modseq\r\n",
"{}"
),
objectid_line
),
),
(
super::Response {
mailbox: ListItem::new("~peter/mail/台北/日本語"),
total_messages: 172,
recent_messages: 5,
unseen_seq: 3,
uid_validity: 3857529045,
uid_next: 4392,
closed_previous: true,
is_rev2: true,
is_utf8: true,
highest_modseq: None,
objectid: Some(objectid.clone()),
},
"A142",
format!(
concat!(
"* OK [CLOSED] Closed previous mailbox\r\n",
"* 172 EXISTS\r\n",
"* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n",
"* LIST () \"/\" \"~peter/mail/台北/日本語\" (\"OLDNAME\" ",
"(\"~peter/mail/&U,BTFw-/&ZeVnLIqe-\"))\r\n",
"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
"* OK [UIDVALIDITY 3857529045] UIDs valid\r\n",
"* OK [UIDNEXT 4392] Next predicted UID\r\n",
"{}"
),
objectid_line
),
format!(
concat!(
"* OK [CLOSED] Closed previous mailbox\r\n",
"* 172 EXISTS\r\n",
"* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft \\Recent)\r\n",
"* 5 RECENT\r\n",
"* OK [UNSEEN 3] Unseen messages\r\n",
"* OK [PERMANENTFLAGS (\\Deleted \\Seen \\Answered \\Flagged \\Draft \\*)] All allowed\r\n",
"* OK [UIDVALIDITY 3857529045] UIDs valid\r\n",
"* OK [UIDNEXT 4392] Next predicted UID\r\n",
"{}"
),
objectid_line
),
),
] {
let response_v2 = String::from_utf8(response.clone().serialize()).unwrap();
response.is_rev2 = false;
let response_v1 = String::from_utf8(response.serialize()).unwrap();
assert_eq!(response_v2, expected_v2);
assert_eq!(response_v1, expected_v1);
}
}
}