sources: add a generic IMAP source - #236
Open
constkolesnyak wants to merge 1 commit into
Open
Conversation
Adds an IMAP mailbox source for providers the Gmail source cannot reach (the existing one goes through the gog CLI / Gmail API, so a plain IMAP mailbox — GMX, Fastmail, a company server — has no path in today). One source per mailbox, each with an independent cursor (<UIDVALIDITY>:<max_uid>), registered from sync.imap. Some mail carries the part worth acting on only as an inline image — a scan, a photo, a rendered document — so the body text is useless to the inbox consumer. sync.imap.match singles those messages out by sender or by an image's Content-ID/filename, and sync.imap.vision runs a multimodal pass over the image at ingest time so what lands in the inbox is plain text. match.only_matched drops everything else at the source, turning the mailbox into a single-purpose notifier rather than a second inbox. Both blocks are inert by default: with no match rules configured nothing is singled out, no model is ever called, and this is a plain mailbox reader. The vision prompt and the answer key are deliberately configured as a pair: the prompt tells the model which label to emit and the parser reads the line after exactly that label, so changing one without the other would silently yield unknown_answer every time — a failure that looks like the model degrading rather than a config mistake. Two tests pin the coupling, one moving both (works) and one moving only the prompt (degrades as expected). Disabled by default; passwords are read from sync.imap.passwords keyed by username so no credential belongs in the tracked config. An account with no password is skipped with a warning instead of failing the whole sync. 25 tests pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Add a generic IMAP sync source (
nerve/sources/imap.py) that polls one or more IMAP mailboxes and surfaces new emails as source messages.config.local.yamltests/test_imap_source.py)Config example (in
config.local.yaml):Why
Gmail's IMAP access can be locked down by organization policy; a generic IMAP source lets any IMAP-accessible mailbox feed into nerve.
Rebased on current upstream/main (2026-07-30).