How InboxDuty handles your correspondence
InboxDuty sorts the mail in a shared inbox and writes the result back as the provider's own labels. It reads correspondence. It does not keep it. This page exists so a data protection officer can check that claim against what the software actually does, and see plainly what is not finished yet.
Email content is never stored.
A message is read transiently, judged from text that has had personal data stripped out of it, and discarded. The durable record is a decision against a keyed message identifier, not the message.
What happens to one message
One path, and the message sits in memory only for the length of it.
- 1.InboxDuty polls the mailbox through the provider's own change feed (Gmail history, Microsoft Graph delta) and receives message identifiers, not bodies.
- 2.For a changed identifier it fetches the few fields it needs into memory: the text and the sender identity.
- 3.Personal data is replaced with typed placeholders before anything external sees the text: [PERSON_1], [EMAIL_1], [PHONE_2]. The same real value maps to the same placeholder inside one message, so “the sender asks for data about the sender” stays decidable.
- 4.Placeholders are deliberately not comparable between messages. Numbering is salted with a fresh random value for every message, so a placeholder in one message says nothing about another. Cross-message stability would build a linkable profile, which is still personal data.
- 5.If identity cannot be confidently removed, the message is not sent anywhere and is not judged. Redaction fails safe.
- 6.Only the stripped text reaches the classifier. The classifier returns typed weights over the agreed categories; it does not generate text.
- 7.The message body is dropped. Only the content-free decision is kept.
Statutory signals survive stripping because the signal is the relationship, not the identity. “The sender asks for all data held about the sender” is a subject access request with no name attached, so first-person grammar and statutory vocabulary are preserved verbatim.
The durable record
A decision against a keyed message identifier. Not the message.
- The decision, and the full weight distribution behind it, not just the winning answer
- The confidence, the classifier and model version, and the immutable shape version that was judged
- Counts of the categories of personal data that were removed, and the statutory flags that were detected
- Whether the sender was an individual or an organisation — a category, never the sender
- A keyed message identifier and the time of the decision
- A processing ledger: whether a label was written, the triage decision, and whether InboxDuty is waiting to recognise its own write
- Human corrections: the old and new decision, the shape version and who made the change. There is no free-text rationale
- Configuration: the organisation, its members, mailbox settings, the labels InboxDuty provisioned and the trial clock
- Message bodies or attachments
- Subjects or sender addresses
- Mailbox OAuth refresh tokens — those are held by self-hosted Nango, not by InboxDuty's database
- Any plain-hash identifier. The message key is HMAC-SHA-256 keyed with a per-tenant secret, so holding the database is not enough to confirm guessed content
Who is inside the trust boundary
Named, not implied. There is no unnamed model watching your mail.
Your Microsoft 365 or Google Workspace tenant holds the mailbox. You grant InboxDuty access, and you can end it.
The operator's own infrastructure, not a third-party service. It performs the OAuth exchange and holds the mailbox refresh tokens. InboxDuty's database stores what it knows about the connection — scopes, consent type, provider mailbox identifier and cursor — but never a token. The self-hosted build we run encrypts those tokens under a single environment key; per-tenant envelope encryption and a managed secret store are not built yet.
The runtime classifier and a named third party. It receives the stripped text only, never the original message, and returns typed weights. It sits behind one seam, so another model could serve instead.
Used only in the set-up conversation that helps a team describe its classification rules. It sees the team's own typed descriptions and examples — never mailbox correspondence, which that feature cannot reach.
How you revoke access
The primary kill switch is in your own admin console, and it takes effect immediately. InboxDuty cannot override it, and it holds no credential that survives it.
- 1.Sign in to the Microsoft Entra admin center (entra.microsoft.com) as a Global Administrator, or as an administrator with the Application Administrator role.
- 2.Open Identity, then Applications, then Enterprise applications.
- 3.Select the InboxDuty application.
- 4.Open Permissions and revoke the admin consent for the organisation, or select Delete to remove the service principal entirely. Either revokes the consent and the tokens for every mailbox it was granted.
- 1.Sign in to the Google Admin console (admin.google.com) as a super administrator.
- 2.Open Security, then Access and data control, then API controls.
- 3.Under App access control, open Manage third-party app access.
- 4.Find InboxDuty (the app you approved), open its row and choose Change access.
- 5.Set the access to Blocked and save.
The next time InboxDuty polls, the provider refuses the token. InboxDuty marks the mailbox disconnected, stops reading and says so. Revoking stops InboxDuty reading; it does not undo a label already applied. Delete those labels in Gmail or Outlook if you want them gone.
Where we ask for more than we want
Scope minimisation is not absolute, and it is better you hear it from us than from your IT department.
Gmail has no scope that can manage labels without also being able to send and trash mail. That is the narrowest scope that can apply a label. Google also has no tenant-wide admin-consent screen separate from sign-in, so the administrator-granted route cannot be limited to a single shared mailbox.
The delegated permission InboxDuty uses reads mail in the shared mailbox and manages its categories. Admin consent is tenant-wide, so an administrator approves it for the whole tenant rather than one mailbox.
Before any customer mail is judged
These conditions must exist before InboxDuty judges a customer's mail. None of them are in place yet.
The code is built to the content promise on this page, and that promise is covered by tests. The paperwork above is not done. Do not connect a live mailbox until it is.
What is not yet proven
A precise statement of the build, so you can weigh the claims above.
- The mailbox connection and the polling loop are verified against fakes and a real database, not yet against a live Microsoft 365 or Google Workspace tenant.
- No live TypeSafe call has been made. Without a configured key a deterministic local classifier runs instead so the loop can be exercised; it is not the product classifier.
- Redaction is heuristic and deliberately conservative. It is verified for plain-text English and Latin-script mail, including signatures, quoted chains, sender-only headers and the common identifier forms. A message written in raw HTML or MIME structure, or in a script the heuristics cannot read, is refused before anything external sees it rather than sent on a guess.
- Redaction is a backstop, not a proof that every identifier form is caught. A message it cannot confidently strip is refused and not judged; the refusal rate is a real limit of the product today.
- The agent SDK's tracing and model-data logging are disabled through the SDK's own controls before any model run, so a hostile environment default cannot re-enable exporting. This is verified by observing the SDK's own tracing and logging configuration, not by a live model call.
- Per-tenant message-key secrets are read from configuration, not yet from a managed secret store.
- Sign-in against a live Google or Microsoft provider has not been exercised end to end.