Commit Graph
507 Commits
Author SHA1 Message Date
JMR-devandClaude Opus 4.8 40b0d9b3ad Add new-mail notifications and persisted settings
Increment 6 — notifications and settings.

- Local new-mail notifications (no push service): MailNotifier posts a notification
  when background sync finds newly-arrived unread mail, and tapping it opens the app.
  Adds a POST_NOTIFICATIONS request on launch.
- MailSyncer detects genuinely new messages (diff against cached ids, skipped on an
  account's first sync) and notifies when the setting is enabled.
- SettingsRepository (Preferences DataStore) persists settings; the Settings screen
  gains a Notifications section, and "Use wallpaper colors" now actually drives the
  Material You theme (MainActivity collects it reactively).
- assemble/test/lint green; verified on the Android 17 emulator — delivered a new
  message and the on-device notification appeared in the shade.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 20:21:49 -05:00
JMR-devandClaude Opus 4.8 22ddc08a24 Add composing and sending: SMTP send + contacts + reply
Increment 5 — send.

- SmtpSender (Angus Mail; password/XOAUTH2) builds a MimeMessage and sends over
  SMTP/SMTPS. New OutgoingMessage + SmtpParams.
- MailConnectionFactory now resolves both IMAP and SMTP params (shared credential
  and token refresh); MailRepository.sendMessage.
- Compose screen wired to send: From account (a selector when there are several),
  To with device-contacts autocomplete (ContactsContract, runtime READ_CONTACTS),
  Cc, Subject, Body, with progress and error handling.
- Reply from the reader prefills To and a "Re:" subject (compose route gains optional
  to/subject args).
- Tests: GreenMail SmtpSender unit test. assemble/test/lint green; verified end-to-end
  on the Android 17 emulator — composed a message, sent it over SMTP to a local
  GreenMail server, and it round-tripped back into the inbox on re-sync.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 19:58:18 -05:00
JMR-devandClaude Opus 4.8 d81e94717b Add message reading: body fetch + hardened WebView + flag actions
Increment 4 — read.

- ImapClient.fetchBodyMarkingSeen extracts the best body part (HTML preferred,
  else plain text) and marks the message \Seen; setFlag and deleteMessage (expunge)
  back the star/read/delete actions.
- MailConnectionFactory shares credential/token resolution between sync and reader.
- Cached bodies survive sync: schema v3 (isHtml column via a data-preserving
  Migration 2->3); sync is now insert-new + update-header + delete-absent instead of
  replace-all, so fetched bodies are not clobbered.
- Reader fetches and caches the body on open (marking it read), renders HTML in a
  hardened WebView (JavaScript off, file/content access off, remote content blocked
  with an opt-in "Show images") and plain text in selectable Text; star + delete in
  the app bar; a snippet is derived from the fetched body.
- Tests: GreenMail fetchBodyMarkingSeen unit test (body + read flag). assemble/test/
  lint green; verified end-to-end on the Android 17 emulator against a local GreenMail
  server (HTML rendered in the WebView, mark-read, snippet).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 19:05:55 -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 98842a2300 Add .gitattributes for consistent cross-platform line endings
Keeps gradlew as LF (Unix shell), *.bat as CRLF, and treats jars/images as
binary, independent of each contributor's core.autocrlf setting.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 00:18:37 -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