Merge upstream v0.16.23

Five conflicts, resolved:

- crates/common/src/auth/authentication.rs: upstream's get_directory_for_token
  and JwtClaims replace extract_jwt_domain; the per-domain directory code
  (DIR-1, DIR-5 to DIR-7) is kept, and the token lookup routes through it.
  The release's one new Enterprise snippet was the body of
  get_directory_for_issuer, which stays returning None: a token naming no
  address gets the server default, as DIR-2 specifies and as v0.16.22 did.
- crates/common/src/manager/application.rs: upstream's rewrite of the tests,
  with the temp directory names renamed again, and the 5(a) notice the
  name-purge change should have added.
- crates/common/src/network/mta.rs: both sides' imports.
- crates/main/Cargo.toml: the AGPL-only license kept, version 0.16.23.
- Cargo.lock: upstream's, with the fork's crates added by Cargo.
This commit is contained in:
2026-09-22 16:57:06 -07:00
82 changed files with 1527 additions and 611 deletions
+30 -1
View File
@@ -11,7 +11,11 @@ use crate::{
use common::{Server, auth::AccessToken};
use email::{
cache::{MessageCacheFetch, email::MessageCacheAccess, mailbox::MailboxCacheAccess},
message::copy::{CopyMessageError, EmailCopy},
mailbox::JUNK_ID,
message::{
copy::{CopyMessageError, EmailCopy},
ingest::EmailIngest,
},
};
use http_proto::HttpSessionData;
use jmap_proto::{
@@ -29,6 +33,7 @@ use jmap_proto::{
};
use jmap_tools::{Key, Value};
use std::future::Future;
use store::write::BatchBuilder;
use trc::AddContext;
use types::acl::Acl;
use utils::map::vec_map::VecMap;
@@ -87,6 +92,9 @@ impl JmapEmailCopy for Server {
};
let on_success_delete = request.on_success_destroy_original.unwrap_or(false);
let mut destroy_ids = Vec::new();
let mut train_batch = BatchBuilder::new();
let mut did_train = false;
train_batch.with_account_id(from_account_id);
'create: for (id, create) in request.create.into_valid() {
let mut from_message_id = None;
@@ -208,6 +216,7 @@ impl JmapEmailCopy for Server {
}
// Add response
let train_spam = mailboxes.contains(&JUNK_ID);
match self
.copy_message(
from_account_id,
@@ -221,6 +230,20 @@ impl JmapEmailCopy for Server {
.await?
{
Ok(email) => {
if train_spam {
self.add_account_spam_sample(
&mut train_batch,
from_account_id,
from_message_id.document_id(),
true,
session.session_id,
)
.await
.caused_by(trc::location!())?;
train_batch.commit_point();
did_train = true;
}
response
.created
.append(id, ingested_into_object(email).into());
@@ -245,6 +268,12 @@ impl JmapEmailCopy for Server {
}
}
if did_train {
self.commit_batch(train_batch)
.await
.caused_by(trc::location!())?;
}
// Update state
if !response.created.is_empty() {
response.new_state = self.get_cached_messages(account_id).await?.get_state(false);