postulo-thunderbird: bind a mail to a listing from the client, with no mailbox credentials on the server #271
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Postulo/postulo#271
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A Thunderbird MailExtension that sends the message you are reading to Postulo, bound to
the listing or application it is about. One click, one message, from the client.
Its own repository,
postulo/postulo-thunderbird, following the shape the browser extensionsalready have rather than the Python plugin shape — it never appears in the plugin registry,
because it runs on the person's machine and talks to the API.
Why this is not
postulo-imapThey answer the same question and make opposite trades, and both should exist.
postulo-imappostulo-thunderbirdGiving a job tracker the keys to your mailbox is a real decision, and plenty of people will
not make it. This asks for nothing: the mail never leaves Thunderbird except the message the
person deliberately sends, and the server learns nothing about the rest of the mailbox — not
its size, not its folders, not who else writes to them.
Why it is not a third build of
postulo-chromiumpostulo-firefoxis not a separate extension:source.jsonpins apostulo-chromiumcommit and
npm run check:pinrefuses anything that moves, so the two build to the samebytes on purpose. Thunderbird cannot join that arrangement. A MailExtension has
messageDisplayandmessages.*where the browser extension has tabs and a page DOM; thehalf that reads a job advert out of HTML has no counterpart here.
What it can share, and should, is the Postulo-facing half the browser extensions already
solved: storing a token, configuring the instance URL, calling the API, and asking whether
this is already known before sending. That half is worth lifting out rather than writing a
third time.
It depends on #270, and should not start before it
There is no way to bind a mail to a listing today. #270 is the issue that decides whether
that binding is an event, an attachment, or a separate model, and what happens to it when a
listing becomes an application.
This plugin is a consumer of whatever #270 settles. Starting it first would mean inventing
the shape in an extension repository and then having core disagree with it.
What it needs from the API, and one thing that is missing
Bearer tokens with scopes are already there (
api/auth.py,api/models.py). The currentscopes are
captures,read,writeanddocuments:read.None of them fits. Binding a mail is not capturing, and
writeis far more than a mailclient should hold — that scope covers "applications, listings, notes, reminders, letters".
A token that can attach a message should not also be able to change an application's status.
So #270, or this issue, should add a narrower scope. Worth deciding with #270 rather than
bolting one on afterwards.
Message-IDis the idempotency key, and the machinery existsapi/idempotency.pyalready lets a capture carry anIdempotency-Key, so that a clientwhich never saw the
201can retry without making a second record — and the key belongs tothe account rather than the token, "because a person retrying from a second tool is retrying
the same gesture".
A mail's
Message-IDis globally unique and stable by design. Using it as the key means thesame message sent twice — from two folders, from two machines, after a failed send — is one
binding, with no new mechanism. It also means the extension does not need to remember what it
has already sent.
Scope
Sends: the headers that identify the message (
From,To,Subject,Date,Message-ID), the body as text, and — chosen, never automatically — attachments.messages.listAttachmentsandgetAttachmentFileare how. A forwarded job description PDFis #270's own first example.
Never sends: anything the person did not select. No folder scan, no background sync, no
address book, no credentials.
Shows: which listing or application the message would attach to, found by asking the API,
with the person confirming. Never guessed silently.
What it inherits
exports to CSV and ICS and serves an MCP client. That is exactly #218, and everything bound
through this path is inside its blast radius.
plugin strings; an extension's own interface strings are its own to ship.
To check before starting
the target is ESR or release.
postulo-firefoxalready carries the reproducible-source discipline a review wants.depend on, or copied once and kept in step by hand. The browser extensions chose pinning;
this is the moment to decide whether that scales to three.