Commit graph

37 commits

Author SHA1 Message Date
Shautvast
05b6aac692 Add proton-bridge crate: workspace setup and SRP authentication (Step 2)
- Convert tuimail repo to Cargo workspace with tuimail and proton-bridge members
- Add proton-bridge binary crate with config, SRP 6a, and auth modules
- Implement ProtonMail SRP 6a exactly matching go-srp:
  - Little-endian bigints throughout
  - expandHash = SHA512(data||0..3) producing 256 bytes
  - k, u, M1, M2 all via expandHash with 256-byte normalised inputs
  - Password hashing v3/v4: bcrypt($2y$, salt+proton) + expandHash(output||N)
- Authenticate against Proton API (auth/info → auth/v4), verify server proof
- Persist session (UID, access/refresh tokens) to session.json
- Add bridge.toml and session.json to .gitignore (contain credentials/tokens)
- Add PROTON.md with full build plan for the mini-bridge

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 21:31:10 +01:00
Shautvast
fba2623f15 Add SMTP send with TLS mode support and timeouts
- Add smtp.rs with send_email using lettre; supports none/starttls/smtps
- Replace use_tls: bool with TlsMode enum in SmtpConfig for explicit port 465 (SMTPS) support
- Add SMTP_IO_TIMEOUT (15s) for socket I/O and SMTP_WALL_TIMEOUT (30s) covering DNS + connect
- Spawn SMTP send on a dedicated thread so the IMAP worker thread is never blocked
- Update config.toml.example with tls_mode documentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-19 20:07:17 +01:00
Shautvast
7883b35dad Add IMAP search with / keybinding and live results pane
- Press / to enter search mode; status bar shows query input
- IMAP SEARCH OR SUBJECT/FROM sent in background worker thread
- Results replace inbox list with match count in title
- Navigation and body preview work the same as in regular inbox
- Esc clears search and returns to normal inbox view

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 17:01:00 +01:00
Shautvast
c3a7c62214 Align sender and subject columns in inbox list
Compute the max sender width across the loaded emails (capped at 40
chars) and pad each sender field to that width. Long senders are
truncated with an ellipsis. Subject column now starts at a consistent
position regardless of sender name length.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 16:35:49 +01:00
Shautvast
b6ef2b4508 Fix selection reset on refresh and off-by-one body after delete
Refresh regression:
- refresh() only loads the latest 50 emails, so if the user scrolled
  further via FetchMore their selected email was not in the new list and
  selection fell back to index 0. Now preserve emails older than the
  refresh batch (previously fetched via FetchMore) by merging them back.
- Also cancel pending debounce on refresh so stale pending fetches can't
  overwrite the correct body after selection changes.
- Up-arrow now uses debounce consistently with Down-arrow.

Delete off-by-one:
- IMAP expunge renumbers all messages with seq > deleted seq. The app
  was still holding pre-delete sequence numbers, so the next FetchBody
  after a delete would retrieve the wrong message. After removing an
  email, decrement the seq of every remaining email with seq > deleted.

Cleanup: remove now-unused Inbox.oldest_seq and Inbox.has_older() since
oldest_seq/has_older are now computed from the merged emails list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 16:12:43 +01:00
Shautvast
12eb683007 Fix intermittent unresponsiveness from slow/hanging IMAP connections
Three improvements:
- Add 15s connect/read/write timeouts to TcpStream so a hung IMAP
  server can no longer block the worker thread indefinitely
- Cache tui_markdown rendering: convert Text<'a> to Text<'static> on
  first render and reuse across frames, re-parsing only when the body
  actually changes
- Debounce FetchBody requests on keyboard navigation: wait 150ms of
  inactivity before sending, so rapid scrolling doesn't flood the
  worker with stale requests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:43:45 +01:00
Shautvast
e6ff04a97d Clean up HTML table pipes in message body and improve focus indicators
- Strip pipe characters from HTML-to-markdown table remnants in email body
- Add bold + arrow prefix (▶) to focused pane title for clear focus indication
- Rename Focus::Preview and all preview_* variables to Message/message_*

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:15:43 +01:00
Shautvast
3e647dbe52 Post-process markdown to clean up noisy HTML email output
Strip images, simplify links to just text, remove very long bare URLs,
and collapse excessive blank lines for a cleaner preview pane.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:41:25 +01:00
Shautvast
23f179df24 Replace html2text with fast_html2md + tui-markdown for styled email preview
HTML emails are now converted to markdown then rendered with rich formatting
(bold, italic, headings, links) in the preview pane via tui-markdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 13:39:14 +01:00
Shautvast
2214b15f44 Increase html2text wrap width to avoid breaking long URLs
Let Ratatui handle visual line wrapping instead of html2text splitting
lines at 80 columns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:52:52 +01:00
Shautvast
df9d67a7c9 Fix terminal not restoring properly on exit
Ensure disable_raw_mode and LeaveAlternateScreen run even when the
app returns an error. Also add a panic hook to restore the terminal
on unexpected panics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:03:04 +01:00
Shautvast
0eda9045cd Cancel stale body fetch requests when selection changes quickly
Uses Arc<AtomicU32> to track the most recently wanted email sequence
number. The worker skips fetch requests that no longer match, avoiding
wasted network calls when scrolling through emails rapidly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 08:59:42 +01:00
Shautvast
7269eca3e9 Fix worker thread blocking startup by deferring IMAP connection
The eager connect() call in the worker thread could hang if the server
was unreachable, preventing the worker from ever processing commands.
Let refresh() handle the initial connection instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 08:57:57 +01:00
Shautvast
212fd49534 Add delete email with optimistic UI update
Press 'd' to delete the selected email. Removes it from the list
immediately and performs the server-side delete in the background
for a snappy user experience.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:57:10 +01:00
Shautvast
e871c1aab8 Clean up leftover quoted-printable artifacts in email body
Add a second-pass QP decode to catch =XX sequences that survive
the initial mailparse decoding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:47:47 +01:00
Shautvast
d0df411c57 Render HTML emails as plain text using html2text
Fall back to html2text when no text/plain part is available,
converting HTML emails to readable terminal output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:45:44 +01:00
Shautvast
3a2ce88ebf Extract plain text from emails using mailparse
Fetch full raw email and parse MIME structure to find the
text/plain part, removing MIME headers and boundaries from
the preview pane.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:38:46 +01:00
Shautvast
bdb6dce672 Update CLAUDE.md for skim project
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:34:46 +01:00
Shautvast
328a5fa5d2 Rename project to skim
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:33:37 +01:00
Shautvast
2aacac82be Preserve selection across inbox refresh by matching sequence number
After refresh, find the previously selected email by its IMAP
sequence number and keep the highlight on it. Falls back to the
first email if the selected one was deleted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:32:09 +01:00
Shautvast
174a1b1030 Add focus switching and scrollable preview pane
Tab toggles focus between inbox list and preview. Focused pane
gets a cyan border. When preview is focused, up/down scrolls the
email body instead of navigating the list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:29:13 +01:00
Shautvast
b781b0fa08 show mail contents 2026-02-17 21:23:19 +01:00
Shautvast
df9f9f0b2f Move IMAP operations to background thread for responsive UI
Spawn a worker thread that owns the IMAP session and processes
fetch commands via channels. The UI thread polls for results
non-blockingly, keeping the app responsive during network operations.
Shows loading indicator while fetching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:13:42 +01:00
Shautvast
2f23ea7686 Reorganize mail setup docs with Gmail instructions first
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:00:43 +01:00
Shautvast
df112755ec Fetch older emails on scroll with lazy loading
Introduce Inbox struct to track the oldest fetched sequence number.
When scrolling past the last email, automatically fetch the next
batch of 50 older messages and append them to the list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 20:58:12 +01:00
Shautvast
fd1b087f76 timezone correction 2026-02-17 20:52:24 +01:00
Shautvast
904f89f1b4 timezone correction 2026-02-17 20:52:15 +01:00
Shautvast
fe396a394b sort descending 2026-02-17 20:47:10 +01:00
Shautvast
ddb2c314d0 geen timezone 2026-02-17 20:45:21 +01:00
Shautvast
1412ecfbb8 refactor 2026-02-17 20:36:24 +01:00
Shautvast
96e170f1c9 google settings 2026-02-17 20:26:12 +01:00
Shautvast
cc7eeba7f8 Add TLS support and limit inbox fetch to last 50 messages
Support both plain and TLS IMAP connections via an ImapSession enum,
enabling use with Gmail and other TLS-only servers. Limit fetch range
to the most recent 50 messages to avoid hanging on large mailboxes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 20:25:37 +01:00
Shautvast
7bb8aaec32 highlight bar 2026-02-17 20:11:54 +01:00
Shautvast
2cd6446d13 keep existing session 2026-02-17 20:03:20 +01:00
Shautvast
05aa47d723 manual refactoring 2026-02-17 19:58:04 +01:00
Shautvast
9bbfad554e Fetch and display inbox emails with periodic polling
Replace simple IMAP login with full inbox fetch that displays
Subject, From, and Date for each message. Auto-refreshes every
30 seconds and supports manual refresh with 'r' key.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:31:37 +01:00
Shautvast
78f5c4655c basic gui and login to imap 2026-02-17 17:24:35 +01:00