diff --git a/crates/jmap-proto/src/object/email_submission.rs b/crates/jmap-proto/src/object/email_submission.rs index f16c4c7..792a246 100644 --- a/crates/jmap-proto/src/object/email_submission.rs +++ b/crates/jmap-proto/src/object/email_submission.rs @@ -45,6 +45,9 @@ pub enum EmailSubmissionProperty { // inbuxa: DLP (dlp-and-mail-flow-rules spec, §2.5): `{"reason": ...}` // to send despite a warning DlpOverride, + // inbuxa: in a create's response, true when DLP held the message for + // review (§2.6) + DlpHeld, Pointer(JsonPointer), } @@ -96,6 +99,7 @@ impl Property for EmailSubmissionProperty { EmailSubmissionProperty::IdentityId => "identityId", EmailSubmissionProperty::MdnBlobIds => "mdnBlobIds", EmailSubmissionProperty::DlpOverride => "inbuxa:dlpOverride", + EmailSubmissionProperty::DlpHeld => "inbuxa:held", EmailSubmissionProperty::SendAt => "sendAt", EmailSubmissionProperty::ThreadId => "threadId", EmailSubmissionProperty::UndoStatus => "undoStatus", @@ -188,6 +192,7 @@ impl EmailSubmissionProperty { "dsnBlobIds" => EmailSubmissionProperty::DsnBlobIds, "mdnBlobIds" => EmailSubmissionProperty::MdnBlobIds, "inbuxa:dlpOverride" => EmailSubmissionProperty::DlpOverride, + "inbuxa:held" => EmailSubmissionProperty::DlpHeld, ) .or_else(|| { if allow_patch && value.contains('/') { diff --git a/crates/jmap/src/submission/set.rs b/crates/jmap/src/submission/set.rs index 055ab30..2f83dfe 100644 --- a/crates/jmap/src/submission/set.rs +++ b/crates/jmap/src/submission/set.rs @@ -91,6 +91,13 @@ impl EmailSubmissionSet for Server { ); let send_at = submission.send_at; + // inbuxa: DLP (§2.6): the sender learns it's held + let held = match submission.queue_id { + Some(queue_id) => { + inbuxa_features::mailflow::held::is_held(self.store(), queue_id).await? + } + None => false, + }; let undo_status = match submission.undo_status { UndoStatus::Pending => email_submission::UndoStatus::Pending, UndoStatus::Final => email_submission::UndoStatus::Final, @@ -128,7 +135,8 @@ impl EmailSubmissionSet for Server { .with_key_value( EmailSubmissionProperty::UndoStatus, Value::Element(EmailSubmissionValue::UndoStatus(undo_status)), - ), + ) + .with_key_value(EmailSubmissionProperty::DlpHeld, Value::Bool(held)), ), ); } diff --git a/tests/src/system/mail_rules.rs b/tests/src/system/mail_rules.rs index 842d8f5..faff97e 100644 --- a/tests/src/system/mail_rules.rs +++ b/tests/src/system/mail_rules.rs @@ -312,6 +312,7 @@ pub async fn dlp(test: &mut TestServer) { response["created"].get("s").is_some(), "no rules: {response}" ); + assert_eq!(response["created"]["s"]["inbuxa:held"], false, "{response}"); // A warning: refused with the rule and its notice, then sent with a reason let (_, response) = call( @@ -833,6 +834,7 @@ pub async fn hold(test: &mut TestServer) { .as_str() .unwrap_or_else(|| panic!("held, not refused: {response}")) .to_string(); + assert_eq!(response["created"]["s"]["inbuxa:held"], true, "{response}"); let (_, response) = call(&admin, "inbuxa:HeldMessage/get", json!({"ids": null})).await; let list = response["list"] .as_array()