Commit Graph
5 Commits
Author SHA1 Message Date
JMR-devandClaude Opus 4.8 13a32df873 Add IMAP folder navigation drawer + per-API E2E CI matrix
Folder view: a left navigation drawer lists each account's IMAP folders;
tapping one browses and caches that folder's mail. IMAP UIDs are unique only
within a folder, so message identity, the fetch/read/flag/delete paths, sync,
and the Room cache all became folder-aware (id = "accountId:folder:uid"; new
`folder` column; schema v7->v8). Standard folders (Inbox/Sent/Drafts/Spam/Trash/
Archive) surface with friendly names + icons via RFC 6154 SPECIAL-USE attributes
with a case-insensitive name fallback; the multi-account drawer adds an account
switcher and a unified "All Inboxes". INBOX stays the only auto-synced,
IDLE-watched, notifying folder; other folders sync on demand.

Lower minSdk 33 -> 29 for a rolling ~7-year Android support window; guard the
API-33 POST_NOTIFICATIONS runtime request accordingly.

Tests and CI:
- Bump espresso-core 3.6.1 -> 3.7.0 so Compose UI tests run on API 37
  (3.6.1's InputManagerEventInjectionStrategy reflects a removed hidden method).
- New coverage across layers: FolderRoleTest, ImapClientTest folder cases,
  MailboxViewModelTest, MailRepositoryImplTest folder routing, a FolderDrawer
  Compose UI test, and LibreMailDatabaseTest folder DAO/reconcile tests.
- Gradle Managed Devices + a CI E2E matrix over every API 29-36; a single
  "CI passed" gate job fans in all jobs and is required by branch protection.
- Non-blocking, custom-provisioned API 37 (preview) E2E job with image caching.
- Build + unit-test jobs run on arm64 (ubuntu-24.04-arm); emulators stay x86_64.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 12:23:00 -05:00
JMR-devandClaude Opus 4.8 96c9f71a26 Harden transport security and add opt-in encrypted local cache
From a whole-repo security review (no critical/high issues; TLS cert and
hostname validation were already intact):

- Don't offer the plaintext "None" transport in manual account setup; it
  would send credentials in the clear. The enum value stays only for local
  test servers.
- Relabel the advanced toggle "Allow insecure STARTTLS fallback" with a
  warning subtitle: it relaxes (does not enable) STARTTLS and permits a
  plaintext downgrade when on. Default stays off/secure.
- Set mail.<proto>.ssl.checkserveridentity=true explicitly on IMAP/SMTP as
  insurance over the (already-true) Angus default.
- Add a Content-Security-Policy meta to the reader WebView (JavaScript is
  already disabled).
- Strip Log.d/Log.v in release builds and drop the account address from the
  IDLE log; mark new-mail notifications VISIBILITY_PRIVATE.

Add opt-in at-rest encryption of the Room cache (Settings -> "Encrypt local
cache", off by default) using SQLCipher. The DB passphrase is a random key
sealed by the existing Keystore crypto and kept in a separate DataStore.
DatabaseEncryption performs a self-healing, atomic plaintext<->encrypted
migration at startup that preserves PRAGMA user_version, so toggling applies
on next launch without data loss.

Verified end-to-end on an API 37 emulator (DatabaseEncryptionTest round-trip,
7 instrumented tests) plus 12 unit tests and a release R8 build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 19:50:27 -05:00
JMR-devandClaude Opus 4.8 5386ae76d3 Add IMAP receive: background sync of inbox into Room
Increment 3 — receive.

- ImapClient.fetchRecentInbox pulls recent INBOX headers (ENVELOPE/FLAGS/UID)
  over IMAP (password or XOAUTH2) into FetchedMessage.
- MailSyncer orchestrates per-account fetch -> Room (replace-per-account),
  refreshing and re-persisting the Gmail OAuth token when needed.
- WorkManager background sync via a @HiltWorker (periodic 15-min + an expedited
  one-shot after adding an account); Application supplies the HiltWorkerFactory
  and the default WorkManager initializer is removed.
- Mailbox renders real cached mail with pull-to-refresh and proper empty states
  (welcome/add-account vs no-messages); the sample-data crutch is removed.
- Shared entity mappers; MessageDao.replaceAccountMessages transaction.
- Tests: GreenMail-backed fetchRecentInbox unit test (deliver via SMTP, read via
  IMAP, newest-first). Instrumented Keystore + Angus-provider tests stay green on
  the Android 17 emulator, where the SyncWorker also runs to SUCCESS.
- Add error_prone_annotations to the compile classpath (Hilt/Dagger codegen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 18:25:54 -05:00
JMR-devandClaude Opus 4.8 9c74510832 Add account setup: Gmail OAuth + IMAP/SMTP with encrypted credentials
Increment 2 — authentication and account management.

- Gmail OAuth 2.0 via AppAuth (Authorization Code + PKCE, restricted
  https://mail.google.com/ scope); redirect scheme derived from the client id.
- Generic IMAP/SMTP manual setup (host/port/security) with an Advanced section.
- Angus/Jakarta Mail IMAP client (password + XOAUTH2); "test connection" logs in
  and lists folders before an account is saved.
- Android Keystore-backed AES-256-GCM credential store (encrypts the OAuth
  AuthState / IMAP password); accounts + secrets persisted in Room (schema v2).
- AccountRepository + Hilt wiring; Settings accounts list (add / remove).
- Tests: GreenMail-backed IMAP client unit test; instrumented Keystore round-trip
  and Angus Mail provider-resolution tests (green on the Android 17 emulator).
- Remove the placeholder Compose smoke test (the API 37 Compose-UI-test library
  hits InputManager.getInstance); on-device rendering verified via screenshots.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 10:26:57 -05:00
JMR-devandClaude Opus 4.8 c931c73745 Scaffold LibreMail: Material You email app foundation
Initial scaffold for LibreMail, a free and open-source (GPL-3.0) Android email
client. This increment delivers a buildable, runnable, themed app shell on top
of the full architecture skeleton; account sign-in, IMAP/SMTP sync and sending
arrive in later increments.

- Gradle 9.6 + AGP 9.2 + Kotlin 2.4.0 (AGP built-in Kotlin via the buildscript
  classpath; KSP, no KAPT); version catalog; minSdk 33, target/compile SDK 37
- Jetpack Compose + Material 3 with Material You dynamic color, light/dark and
  edge-to-edge; adaptive, themed launcher icon
- Navigation across Inbox, Reader, Compose, Settings (with an Advanced Settings
  group) and Account Setup
- Hilt DI, Room cache (entities/DAOs/database), domain models, and a
  MailRepository as single source of truth with a sample-data fallback
- Unit tests (repository + sample data) and a Compose smoke test
- GPL-3.0 LICENSE, SPDX headers, README with build and Gmail OAuth setup steps

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 00:17:59 -05:00