Inbox Filter ← Privacy policy

Check our work.

Three pieces of code that prove what happens to your email data. This is the actual code running on our servers.

Lines marked [redacted — proprietary] contain scoring logic that has no bearing on data handling. Every line that touches your email data is shown in full.

The only database table that records anything about your emails.
This is the filter_log table schema. Every column is listed. There are no other tables that store email data.
CREATE TABLE IF NOT EXISTS filter_log (
    id        SERIAL PRIMARY KEY,
    user_id   INTEGER NOT NULL REFERENCES users(id),
    timestamp TEXT NOT NULL,
    verdict   TEXT NOT NULL
);
-- Possible verdicts: 'junk', 'review', 'legit', 'whitelist'
-- No subject, sender, body, score, or reason column exists.
1 Four columns. user_id (an integer — not your email address), timestamp, and verdict. That's the entire record for every email ever processed. No subject, no sender, no content.
The exact API call made to score each email.
The system prompt contains proprietary scoring logic and is redacted. The user message — what actually contains your email data — is shown in full.
rel_msg = client.messages.create(
    model="claude-haiku-4-5-20251001",
    max_tokens=200,
    system=RELEVANCE_PROMPT,
    messages=[{
        "role": "user",
        "content": f"Sender: {sender}\n"
                   f"Subject: {subject}\n\n"
                   f"Body:\n{body[:1500]}"
    }],
)

# Only the score is kept from the response
rel_score = rel.get("relevance_score", 50)  # a number, 0-100
# sender, subject, and body are not stored after this point.
1 body[:1500] — only the first 1,500 characters of the email body are sent to Anthropic. The rest is never read.
2 rel_score — a single integer is all that comes back and all that is retained. The full response object is discarded immediately.
3 Anthropic's retention: API request data is held for up to 7 days for abuse monitoring then permanently deleted. Never used for model training. See Anthropic's privacy policy.
The function that writes the result of filtering an email.
This function accepts subject, sender, and scores as arguments. None of them are written to the database.
def _log_filter_result(
        user_id,
        subject,    # received — never stored
        sender,     # received — never stored
        verdict,
        rel_score,  # received — never stored
        ai_score,   # received — never stored
        reason      # received — never stored
):
    """
    Only verdict and timestamp are written.
    The operator has zero knowledge of inbox contents.
    """
    ph   = _ph()
    conn = get_db()
    _execute(conn,
        f"INSERT INTO filter_log (user_id, timestamp, verdict)"
        f" VALUES ({ph}, {ph}, {ph})",
        (user_id,
         datetime.now(timezone.utc).isoformat(),
         verdict)
    )
    conn.commit()
    conn.close()
1 7 arguments received, 3 written. subject, sender, rel_score, ai_score, and reason are accepted by the function and immediately discarded. Cross-reference with the schema above — no columns exist to store them in anyway.
2 This function is called as _log_filter_result(user_id, None, None, verdict, 0, 0, "") — subject and sender are explicitly passed as None, making it structurally impossible for them to be stored.