Commit Graph
31 Commits
Author SHA1 Message Date
soconnor eee315fe3d fix read-only behavior 2026-08-02 16:07:16 -04:00
Kacper Kwapisz 23d4b1fc79 Merge remote-tracking branch 'origin/main' into fix/issue-5-watcher-uid-tracking 2026-04-29 11:16:20 +02:00
Kacper Kwapisz c88ea40459 Persist watcher UID cursor across reconnects
The IDLE watcher previously re-baselined last_seen_uid on every
reconnect (e.g. after iCloud's unsolicited FETCH FLAGS responses
during IDLE caused idle_check to raise). Mail that arrived during the
short disconnect window had a UID below the new baseline and was
silently dropped, so Poke never saw it.

Hoist last_seen_uid and last_uidvalidity to the outer reconnect loop
so the cursor survives transient disconnects. Reset only on first run
or when UIDVALIDITY changes (which means the server has reassigned
UIDs and the previous cursor is meaningless).

Apply the same fix to _poll_folder via a shared mutable cursor dict so
non-IDLE servers also retain their cursor across poll-error reconnects.

Fixes #5
2026-04-29 09:30:15 +02:00
Kacper Kwapisz 68c40055e7 Merge remote-tracking branch 'origin/main' into fix/issue-5-watcher-uid-tracking 2026-04-29 09:28:08 +02:00
Kacper Kwapisz af796d8583 Send IMAP ID after login for providers that require it (netease)
Some providers (notably netease 163.com / 126.com / yeah.net) reject
clients that don't issue an RFC 2971 ID command after login. Send a
minimal client identification when the server advertises the ID
capability. Failures are logged at debug and never break login.

Fixes #10
2026-04-29 09:25:59 +02:00
Kacper Kwapisz 5f049c691a Apply ruff format 2026-04-29 09:18:55 +02:00
Kacper Kwapisz c543ed9c47 Add list_accounts tool and require account_id on all email tools
- New list_accounts MCP tool: cheap inbox discovery with no IMAP I/O
- account_id is now required on all 11 per-account tools (no silent
  fallback to first configured account)
- resolve_account: whitespace-tolerant, case-insensitive id matching,
  ambiguity detection on email-address fallback, clear errors that
  point agents at list_accounts
- get_server_info: description clarifies it does live IMAP checks
- Version bumped to 1.1.0
- README: tool count 12 -> 13, breaking-change note, account_id
  requirement called out
2026-04-29 09:12:00 +02:00
0xK 3d4a1cb791 Fix UID-based tracking for already-Seen messages 2026-03-30 16:37:37 +02:00
Kacper Kwapisz 1d4fe9c4cf Fix emails marked as read despite mark_as_read: false
Open IMAP folder in readonly mode when mark_as_read is false,
preventing FETCH RFC822 from implicitly setting the \Seen flag.
2026-03-25 16:46:10 +01:00
Kacper Kwapisz 93b6873925 Add GitHub Releases and version-based OTA updates
- Add __version__ = "0.1.0" to src/server.py
- Add release.yml workflow to create GitHub Releases on v* tags
- Refactor start.sh OTA to use GitHub Releases API instead of commit SHAs
2026-03-25 15:10:23 +01:00
0xKandGitHub 906555d73e Merge pull request #6 from kacperkwapisz/feat/mark-as-read-option
Add mark_as_read config option
2026-03-25 14:50:46 +01:00
Kacper Kwapisz 7ac6531248 Fix ruff formatting 2026-03-25 14:49:21 +01:00
Kacper Kwapisz 5a6ae3e94f Add mark_as_read config option to preserve email read status
Emails forwarded to Poke are no longer marked as read by default,
so users can continue using read/unread status to organize their
inbox. Set mark_as_read: true (global or per-account) to restore
the previous behavior.

Closes #5
2026-03-25 14:47:42 +01:00
0xKandGitHub bcc9f89cf9 Merge pull request #4 from kacperkwapisz/fix/detect-drafts-folder
Fix drafts folder detection using non-existent imapclient constant
2026-03-24 16:41:12 +01:00
0xKandGitHub 5a22a54ca0 Merge pull request #1 from kacperkwapisz/feat/poke-login-sdk
feat: integrate Poke login SDK token automation into start.sh
2026-03-24 16:28:55 +01:00
Kacper Kwapisz 7d38b7ed81 Fix detect_drafts_folder using non-existent imapclient.DRAFTS constant
imapclient.DRAFTS does not exist (only imapclient.DRAFT, which is a
message flag, not a folder attribute). Replaced with direct list_folders
iteration checking for the \Drafts special-use flag, matching the
approach used by detect_archive_folder.
2026-03-24 16:16:26 +01:00
Kacper Kwapisz 2343072c7d Add rate limiting, route filtering, and webhook payload improvements
- Add DropNonMCPRoutes middleware to return empty 404 for non-MCP paths
- Add per-IP sliding window rate limiter with separate GET/POST buckets
- Include account_id and from_address in webhook forwarding payload
- Fix IDLE watcher to always check UNSEEN instead of filtering by EXISTS
- Track seen UIDs to avoid re-forwarding on subsequent IDLE cycles
- Switch to uvicorn.run() with Starlette middleware stack
2026-03-24 15:54:44 +01:00
0xK 581dd0b89a fix: optional MCP_API_KEY in tunnel mode + address Copilot review issues
- start.sh: detect POKE_TUNNEL env var; skip MCP_API_KEY requirement and
  auth when running via poke tunnel (server.py reads the same var)
- start.sh: pass POKE_TOKEN into Python via env var + use json.dumps to
  safely escape quotes/backslashes in YAML (fixes shell-interpolation
  injection risk, Copilot issue #5 / start.sh:72)
- start.sh: anchor MCP_API_KEY guard to non-commented line-start
  assignments and also detect empty value (Copilot issues #1, #8 /
  start.sh:104)
- start.sh: anchor re.sub pattern with re.MULTILINE so only the actual
  assignment line is rewritten, not mid-line occurrences (Copilot
  issue #2)
- start.sh: check re.sub replacement count, warn when poke_api_key key
  is missing from config.yml (Copilot issue #6)
- start.sh: guard npm/npx usage with command -v check; fall back to npx
  poke instead of hard-failing (Copilot issue #3)
- start.sh: use python3 consistently for server.py (Copilot issue #9 /
  start.sh:134)
- start.sh: prefer npx poke tunnel; check command -v poke and fall back
  gracefully (Copilot issue #10 / start.sh:135)
- server.py: honour POKE_TUNNEL=1 — skip bearer-token auth so the poke
  tunnel handles identity; MCP_API_KEY becomes optional in that mode
- README.md: add Node.js/npm prerequisite note (Copilot issue #4)
- README.md: clarify server starts on first run; update AI agent prompt
  (Copilot issue #11 / README.md:48)
2026-03-24 11:40:26 +01:00
Kacper Kwapisz fef9157c4a Fix GET /mcp 405 log spam and resolve_account email matching
Add a custom GET /mcp health route so health checks and client polling
return 200 instead of flooding logs with 405. Also allow resolve_account
to match by email address (from_address, imap_username, smtp_username)
in addition to account ID.
2026-03-23 19:33:51 +01:00
Kacper Kwapisz b3a5cd4c5b Switch webhook endpoint to Poke SDK's /inbound/api-message 2026-03-23 16:38:53 +01:00
Kacper Kwapisz 4ca7032e30 Add from_address override per account for custom domain sending
Useful for iCloud SMTP where login is @icloud.com but you send as a
custom domain. Falls back to smtp_username when not set.
2026-03-23 13:47:29 +01:00
Kacper Kwapisz 4a14d33e22 Default allow_send to false — sending must be explicitly enabled 2026-03-23 08:55:17 +01:00
Kacper Kwapisz 518aeda901 Add blocked_recipients per account to prevent sending to specific addresses 2026-03-23 08:52:59 +01:00
Kacper Kwapisz 0323eb1f7f Fix log spam: skip existing unseen on startup, silence httpx logs 2026-03-23 00:21:21 +01:00
Kacper Kwapisz 8a2d6ac8ed Add debug logging for Poke webhook auth to diagnose 401s 2026-03-23 00:20:23 +01:00
Kacper Kwapisz 9c84ea1a91 Add create_draft tool and allow_send toggle per account
- create_draft: saves email as draft in IMAP Drafts folder
- allow_send: global config toggle (default true), overridable per account
- When sending disabled, send_email returns error suggesting create_draft
2026-03-23 00:13:35 +01:00
Kacper Kwapisz 6e9f1ca617 Fix NoneType encode error in search_emails address formatting 2026-03-23 00:00:47 +01:00
Kacper Kwapisz 8a0abba80c Make SMTP config optional, falls back to IMAP host/credentials 2026-03-22 22:06:48 +01:00
Kacper Kwapisz 48b3f3816f Change default port to 3000 2026-03-22 21:55:49 +01:00
Kacper Kwapisz fc9a2bb8f8 Fix lint: remove unused imports, apply ruff formatting 2026-03-22 21:52:37 +01:00
Kacper Kwapisz eb76dbb489 Initial release: IMAP/SMTP email bridge MCP server
- 11 MCP tools: search, read, send, archive, move, mark emails + folder management
- IMAP IDLE watcher with polling fallback, forwards new emails to Poke webhook
- Bearer token auth (MCP_API_KEY) for securing the server
- Multi-account support via config.yml
- Docker + GitHub Actions CI/CD (lint, build, push to GHCR)
2026-03-22 21:46:14 +01:00