Legal holds, step 3: deleted items in a held account are kept

Every way of deleting mail (JMAP, IMAP EXPUNGE, POP3, mailbox removal,
Trash emptying) and Sieve scripts, events, contacts and files now asks
how the account's deletions are kept: a hold keeps them with no expiry
(archivedUntil 9999-12-31), even with undelete off; otherwise undelete's
period applies as before (LH-4).

A hold's date range decides by the item's own date (LH-3). Mail is noted
as held at deletion and settled when it's archived, once its received
date is known; outside the range it gets undelete's deadline or isn't
kept. Events go by their start, with a day's slack for time zones;
recurring events, contacts, files and scripts are held whole.

A groupware item's note now stays until its archive succeeds, and a
failure retries the task instead of being logged and lost (LH-5).
This commit is contained in:
2026-09-27 19:33:07 -07:00
parent 318783f444
commit 7b97efbb7f
11 changed files with 350 additions and 42 deletions
+4 -6
View File
@@ -243,10 +243,8 @@ impl<T: SessionStream> SessionData<T> {
let mut fully_deleted = RoaringBitmap::new();
let mut thread_ids = RoaringBitmap::new();
// inbuxa: UD-1, UD-6a: the retention in force now
let retention = inbuxa_features::undelete::settings::retention(self.server.registry())
.await?
.items;
// inbuxa: UD-1, UD-6a, LH-4: how this account's deletions are kept
let keeping = self.server.keeping(account_id).await?;
self.server
.archives(
account_id,
@@ -270,10 +268,10 @@ impl<T: SessionStream> SessionData<T> {
fully_deleted.insert(document_id);
thread_ids.insert(metadata.inner.thread_id.to_native());
// inbuxa: UD-1, UD-4: a deleted message is noted for archiving
if let Some(retention) = retention {
if keeping.keeps_anything() {
inbuxa_features::undelete::email::note(
batch,
retention,
&keeping,
account_id,
document_id,
metadata.inner.size.to_native() as u64,