Skip to main content

Inbox

Email for agents. Inbound and outbound flow through Firestore collections and the Inbox Cloud Functions.

Tables​

TablePurpose
postbox.domainsVerified sending domains (SPF/DKIM/DMARC state).
postbox.addressesagent_id → address mapping with aliasing.
postbox.messagesEvery inbound and outbound row.
postbox.inbound_rulesPer-agent move/forward/auto-reply rules.
postbox.outbound_suppressionsHard-bounce block list.
postbox.send_quotasPer-agent per-window rate limits.
postbox.inbound_webhooksSigned callback endpoints.

Inbound flow​

  1. MTA POSTs parsed MIME to postboxIngest with the bridge key.
  2. postboxIngest resolves to → agentId, scores for prompt injection, inserts, and applies matching rules.
  3. Raw MIME is uploaded to the postbox-mime bucket; the row is stamped via stamp_body_ref().
  4. Registered webhooks fire through Cloud Functions fetch with an HMAC signature and an x-ujex-webhook-timestamp header.

Outbound flow​

  1. Agent calls postboxSend with a stable sessionId. The callable checks auth, quotas, suppressions, approval policy, and writes an outbound row.
  2. The bridge dispatch path ships queued rows and records delivery or bounce.
  3. is_hard_bounce(reason) auto-suppresses addresses on terminal codes.

Prompt injection scoring​

postbox.detect_prompt_injection(body) returns a 0–1 float. Every inbound row carries injection_score and quarantined = (score > 0.8). Agents that auto-act on mail should gate behavior on the score.

Routes​

MethodPathPurpose
CallablePurpose
------
postboxIngestIngest parsed MIME (bridge key).
postboxSendSend outbound mail with required sessionId.
postboxListMessagesList messages for the authenticated agent.
postboxReadMessageRead one message.
postboxListInboxesList provisioned inboxes.
postboxBounceRecord bounce events.

Bounce handling​

Postmark (or any bounce-emitting provider) POSTs to the postboxBounce webhook with an HMAC-SHA256 signature of the raw body using the shared POSTBOX_BOUNCE_SECRET. The handler:

  1. Verifies the signature in constant time and rejects mismatches with 401 — never an explanation that would aid forgery.
  2. Looks up the outbound row by messageId (or MessageID) and writes a bouncedAt / bounceType / bounceDetail triple.
  3. Updates the recipient's reputation in owners/{uid}/emailReputation/{address}. HardBounce and SpamComplaint block future sends to that address for 30 days.
  4. Appends a postbox.bounce audit row.

This is the single source of truth for "don't email this person again." Deliverability dashboards read from emailReputation; the sender-side send call checks it before debiting the quota.

Retention​

ujex_postbox_retention (03:17 UTC daily) hard-deletes rows past postbox_retention_days (default 90). MIME blobs are reaped alongside.