security: seal Campaign delivery inputs

This commit is contained in:
2026-07-21 17:53:43 +02:00
parent 9f4eab07f6
commit 50c509d161
8 changed files with 350 additions and 44 deletions

View File

@@ -1063,11 +1063,10 @@ def reconcile_job_outcome(
note=note,
commit=commit,
)
if job.send_status not in {
JobSendStatus.OUTCOME_UNKNOWN.value,
JobSendStatus.SENDING.value,
JobSendStatus.CLAIMED.value,
}:
evidence_note = (note or "").strip()
if not evidence_note:
raise QueueingError("SMTP reconciliation requires an evidence note")
if job.send_status != JobSendStatus.OUTCOME_UNKNOWN.value:
raise QueueingError(f"Job status {job.send_status} does not require reconciliation")
version = _get_version_for_campaign(session, campaign, version_id=job.campaign_version_id)
snapshot = ensure_execution_snapshot(session, version)
@@ -1079,7 +1078,7 @@ def reconcile_job_outcome(
job.sent_at = job.sent_at or now
job.outcome_unknown_at = None
job.claim_token = None
job.last_error = note or "Operator confirmed SMTP acceptance after an uncertain outcome."
job.last_error = evidence_note
job.imap_status = JobImapStatus.PENDING.value if snapshot.delivery.imap_append_sent.enabled else JobImapStatus.NOT_REQUESTED.value
files_integration().mark_job_attachment_uses_sent(session, job)
attempt_status = "reconciled_smtp_accepted"
@@ -1088,7 +1087,7 @@ def reconcile_job_outcome(
job.queue_status = JobQueueStatus.DRAFT.value
job.outcome_unknown_at = None
job.claim_token = None
job.last_error = note or "Operator confirmed that SMTP did not accept this message."
job.last_error = evidence_note
attempt_status = "reconciled_not_sent"
else:
raise QueueingError("decision must be 'smtp_accepted' or 'not_sent'")
@@ -1131,10 +1130,7 @@ def _reconcile_imap_append_outcome(
raise QueueingError("IMAP reconciliation requires an evidence note")
if job.send_status not in SMTP_ACCEPTED_STATUSES:
raise QueueingError("Only an SMTP-accepted job can reconcile a Sent-folder append")
if job.imap_status not in {
JobImapStatus.OUTCOME_UNKNOWN.value,
JobImapStatus.APPENDING.value,
}:
if job.imap_status != JobImapStatus.OUTCOME_UNKNOWN.value:
raise QueueingError(f"IMAP status {job.imap_status} does not require reconciliation")
attempt = (
@@ -1516,7 +1512,7 @@ def _send_job_delivery_context(session: Session, job: CampaignJob) -> _SendJobDe
if not version:
raise SendJobError("Campaign version not found")
try:
snapshot = ensure_execution_snapshot(session, version)
snapshot = ensure_execution_snapshot(session, version, effect_job=job)
except ExecutionSnapshotError as exc:
raise SendJobError(str(exc)) from exc
@@ -2044,7 +2040,7 @@ def append_sent_for_job(session: Session, *, job_id: str, dry_run: bool = False)
if not version:
raise SendJobError("Campaign version not found")
try:
snapshot = ensure_execution_snapshot(session, version)
snapshot = ensure_execution_snapshot(session, version, effect_job=job)
except ExecutionSnapshotError as exc:
raise SendJobError(str(exc)) from exc
if not snapshot.delivery.imap_append_sent.enabled: