X-GM-EXT-1 Gmail Label Extension for Proton Bridge#450
Conversation
|
@bolausson any plan to add QUOTA COMMAND |
I don't see why paperless-ngx would need that. The sole purpose of this patch is to make the bride compatible with the way paperless-ngx tags (applies labels) to eMails. Cheers, |
Implement the X-GM-EXT-1 IMAP extension to support Gmail-style label operations via STORE X-GM-LABELS commands. This allows IMAP clients like Paperless-NGX to apply/remove labels without moving messages between folders. Changes: - Advertise X-GM-EXT-1 capability in IMAP sessions - Extend STORE command parser to handle X-GM-LABELS data item - Add StoreGmailLabels method to state Mailbox - Add SetGmailLabels to connector interface - Route Gmail label STORE through connector to backend
Extend the FETCH command to recognize X-GM-LABELS as a fetch attribute,
allowing IMAP clients to read Gmail-style labels on messages. This
complements the existing STORE X-GM-LABELS support.
Changes:
- Parse X-GM-LABELS in FETCH attribute handler
- Add GetGmailLabels to connector interface for label retrieval
- Format response as X-GM-LABELS ("Label1" "Label2")
Python's imaplib sends CAPABILITY before LOGIN and never re-reads capabilities after authentication. Moving X-GM-EXT-1 to the pre-auth capability list so clients like paperless-ngx can detect Gmail label support.
Parse X-GM-LABELS as a search key so clients like paperless-ngx can filter messages by Gmail-style label (e.g. NOT X-GM-LABELS "Paperless"). The search operation calls GetGmailLabels on the connector for each candidate message.
Replace per-message Proton API calls with local DB queries. The search now resolves the label to a mailbox ID via the connector, queries the local DB for all messages in that mailbox, and builds an in-memory set for O(1) per-message lookups. This turns N API calls into 2 local queries.
Python's imaplib sends labels without wrapping in parentheses: UID STORE 123 +X-GM-LABELS Paperless The parser previously required parenthesized form only: UID STORE 123 +X-GM-LABELS (Paperless) Now both forms are accepted.
Covers the previously-untested X-GM-LABELS extension surface: - imap/command: STORE/FETCH/SEARCH parser tests, incl. the bare-label (Python imaplib) form and NOT X-GM-LABELS — the exact wire forms Paperless-NGX emits. - internal/response: itemGmailLabels formatting (empty/quoting/spaces). - connector dummy: store labels as non-exclusive label mailboxes so STORE/FETCH/SEARCH round-trip end-to-end without touching folder membership; previous methods were no-op stubs. - tests: STORE -> FETCH -> STORE remove round trip, multi-message, labels with spaces, and SEARCH / NOT X-GM-LABELS (the Paperless dedupe query). - Fix TestCapability/TestCapabilityAuthenticateDisabled/login/ authenticate which now must advertise X-GM-EXT-1 (sorted last); these were broken when the feature commit started advertising it.
1974e75 to
fb4bd2d
Compare
Point the gluon dependency at the gluon module that carries the X-GM-EXT-1 server support (depends on ProtonMail/gluon#450) and pin golang.org/x/exp to the revision internal/usertypes expects so the module graph resolves and builds.
|
This PR adds the X-GM-EXT-1 Gmail label extension ( Motivation: Paperless-NGX tags processed e-mails over IMAP using Gmail-style labels ( Rebased on current |
|
@bolausson can I use it explicitly |
X-GM-EXT-1 is a server-side IMAP capability, so it depends on what your IMAP client connects to, not the client itself! Server: Client: |
Just to be clear - This was entirly coded with a LLM!
X-GM-EXT-1 Gmail Label Extension for Proton Bridge
Paperless-NGX uses Gmail's
X-GM-LABELSIMAP extension to apply and query labels on emails after processing. Proton Bridge didn't support this, so we implemented it across Gluon and Bridge.Gluon (IMAP server library)
STORE +X-GM-LABELS ("Paperless")/-X-GM-LABELScommands, routes them through a newSetGmailLabelsconnector interface to the Bridge backend. AddedX-GM-EXT-1capability advertisement.FETCH (X-GM-LABELS)as a fetch attribute, callsGetGmailLabelson the connector, returns labels in Gmail format:X-GM-LABELS ("Paperless" "Notifications").X-GM-LABELSas a search key so clients can filter messages by label (e.g.NOT X-GM-LABELS "Paperless"). The search operation callsGetGmailLabelson the connector for each candidate message with case-insensitive matching.X-GM-EXT-1to the pre-auth capability list. Python'simaplibchecks capabilities beforeLOGINand never re-reads them, so clients like Paperless-NGX weren't detecting support.Proton Bridge
MarkMessagesWithGmailLabelsmaps label names to Proton label IDs (auto-creating if needed), then callsLabelMessages/UnlabelMessagesAPI. Messages stay in INBOX — labels are applied without moving.GetGmailLabelscallsGetMessageAPI to getLabelIDs, maps them back to names via the shared label cache, filtering forLabelTypeLabelonly. Used by both FETCH and SEARCH operations.Tests
Paperless-ngx logs:
paperless.log
mail.log
celery.log