Commit Graph
41 Commits
Author SHA1 Message Date
Hieu Nguyen (Jack) 9db2c29b9a Merge pull request #21 from rome-xi/contrib/mailflare-19
fix(setup): keep fresh D1 bootstrap schema in sync with migrations 0013/0021/0022
2026-09-02 01:13:48 +07:00
Hieu Nguyen (Jack) 71c2006ca2 Merge pull request #18 from brucemclachlan/fix/backup-missing-tables
fix(backups): back up the tables added since the format shipped
2026-09-02 01:12:47 +07:00
Hieu Nguyen (Jack) cb65fe4734 Merge pull request #17 from brucemclachlan/feat/mailbox-delete-ui
feat(mailboxes): add mailbox deletion to the settings UI
2026-09-02 01:11:52 +07:00
rome-xi ac4bd9839a fix(setup): sync fresh D1 bootstrap schema with migrations 0013/0021/0022
Signed-off-by: rome-xi <rome-xi@users.noreply.github.com>
2026-09-01 12:43:05 +00:00
Hieu Nguyen (Jack) 8b7e8d3854 Update cloudflare-api-utils.ts 2026-09-01 18:39:38 +07:00
Hieu Nguyen (Jack) 00f311c39a remove unnecessary env 2026-09-01 17:22:39 +07:00
Bruce McLachlanandClaude Opus 5 a6c326d77c fix(backups): back up the tables added since the format shipped
BACKUP_TABLES is a hardcoded list, and the migrations that added
email_templates, calendar_events (0020) and auto_reply_deliveries (0022)
never updated it. Those three tables are absent from every backup, and
because restoreDatabaseRecords only touches the listed tables, restoring
into an empty database silently loses calendar events and email templates
with nothing reporting a problem.

Add the three tables, and add assertBackupTablesCoverDatabase, which
compares sqlite_master against BACKUP_TABLES and aborts the backup naming
any unlisted table. A backup that fails loudly is recoverable; one that
silently omits a table is only discovered during a restore, when the data
is already gone. The three tables are appended, so the reverse-order delete
still removes children before parents and the forward-order insert still
writes them after users and mailboxes, which they reference.

Extending the list would by itself have broken restores of existing
backups: isDatabaseBackupDocument required every BACKUP_TABLES entry to be
present, and documents written before this change have only the original
nineteen. Split out REQUIRED_BACKUP_TABLES so tables added later are
optional on read, and fill absent ones with an empty array before
validation. Documents missing an original table are still rejected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 01:23:39 +02:00
Bruce McLachlanandClaude Opus 5 374ad89bb0 feat(mailboxes): add mailbox deletion to the settings UI
The DELETE /api/mailboxes/[id] endpoint already existed but nothing in the
UI called it, so a mailbox could be created but never removed.

Add a "Danger zone" card to the mailbox settings page with a confirmation
prompt, consistent with the existing destructive-action pattern used on the
backups page, redirecting back to the mailbox list on success.

Also fix a cleanup gap in the endpoint itself: creating a mailbox provisions
a Cloudflare Email Routing rule via ensureMailboxDomainRouting, but deleting
one only removed the database row, orphaning the routing rule so mail kept
being routed to the Worker for an address that no longer existed. Add the
mirrored removeMailboxDomainRouting and call it before the row is deleted,
returning 502 without deleting if the Cloudflare call fails so the database
and Cloudflare cannot drift apart.

The rule-matching predicate used by ensureEmailRoutingRuleToWorker is
extracted into isWorkerRouteForAddress and reused by the new
deleteEmailRoutingRuleForAddress, so both sides match rules identically.
Address selection reuses getMailboxDomainAddresses, which already excludes
domains claimed by another mailbox with the same local part, so deleting a
mailbox cannot remove another mailbox's routing rule.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 00:48:30 +02:00
Hieu Nguyen (Jack) 57c6d17d3d Added signature + auto reply 2026-08-30 20:54:36 +07:00
Hieu Nguyen (Jack) ac034e5344 improve receiving email from other domains in the same inbox 2026-08-30 09:28:40 +07:00
Hieu Nguyen (Jack) f27448b9bd various improvements 2026-08-29 17:08:17 +07:00
Hieu Nguyen (Jack) 56483510b5 minor improvement 2026-08-29 13:37:23 +07:00
Hieu Nguyen (Jack) d74923c90a improve import emails from file/imap 2026-08-29 13:37:15 +07:00
Hieu Nguyen (Jack) 47ff67c81f improve backup / export 2026-08-29 12:22:50 +07:00
Hieu Nguyen (Jack) 3b0dd196c2 add support for inbox with multiple domain 2026-08-29 12:22:37 +07:00
Hieu Nguyen (Jack) 78fefdeb9b update email row action 2026-08-29 11:41:22 +07:00
Hieu Nguyen (Jack) 7e6a7017e3 Add message actions 2026-08-29 00:21:10 +07:00
Hieu Nguyen (Jack) 4b23205d50 added snooze / actions on email list 2026-08-28 22:46:33 +07:00
Hieu Nguyen (Jack) 9eca43d388 Added shared inbox + forward email 2026-08-28 19:04:19 +07:00
Hieu Nguyen (Jack) eaed0d6b3f Improve inputs 2026-08-28 11:32:04 +07:00
Hieu Nguyen (Jack) e4903e923c Improve Uis 2026-08-27 17:07:08 +07:00
Hieu Nguyen (Jack) 47157fd5e7 fix cf deployment 2026-08-27 15:46:41 +07:00
Hieu Nguyen (Jack) 2d919420d5 push v0.2.0 2026-08-27 15:42:25 +07:00
Hieu Nguyen (Jack) cffd4b142f Improve setup page 2026-08-25 11:41:23 +07:00
Hieu Nguyen (Jack) 649688f0a8 Merge pull request #11 from brucemclachlan/fix/update-and-backup-paths
Fix the admin update check and D1 database backups
2026-08-25 11:19:37 +07:00
Hieu Nguyen (Jack) 5d3b6c480e various UI improvements 2026-08-25 11:15:20 +07:00
Bruce McLachlanandClaude Opus 5 57335e9431 fix(backups): finish the D1 export and read the nested signed URL
Scheduled backups could never produce a file. Two independent bugs, either of
which breaks the export permanently:

- The polling request omitted output_format, which Cloudflare requires on
  every export call rather than only the first. Every poll returned HTTP 400
  ("Invalid property: output_format => Required") until the retry limit was
  reached, failing with "D1 export did not finish before the polling limit".

- The finished export was read from result.result.signed_url, but the API
  nests it one level deeper at result.result.result.signed_url. The export
  completes on the first poll, so the code missed it, slept 15 seconds, and by
  the next poll Cloudflare reported "Not currently exporting anything" - the
  export was gone and could not be recovered.

Send output_format on every call and read the nested payload, falling back to
the flat shape so this keeps working if the response is ever flattened.
Describe the real response in D1ExportResult.

Verified end to end against a live database: export through to R2, 13434
bytes, 19 tables, 21 inserts.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 17:30:10 +02:00
Bruce McLachlanandClaude Opus 5 131336fe47 fix(update): resolve the source repository and dispatch the right workflow
The admin update check could never succeed:

- UPDATE_SOURCE_REPOSITORY pointed at hieunc229/mailflare-team, which is not
  publicly reachable, so getTargetVersion() always failed with "Could not read
  the target repository version".
- getDispatchConfig() hardcoded the same repository and ignored
  GITHUB_UPDATE_REPO, so the configured installation repository was unused.
- dispatchUpdateWorkflow() looked the workflow up by the display name
  "Update Mailflare", but the shipped workflow is named "Dashboard Update".
  find() returned undefined and the call threw a TypeError on item.id.

Point the version check at this repository, read GITHUB_UPDATE_REPO (failing
with a clear message when unset), and dispatch by workflow file name, which
GitHub accepts in place of the numeric id. That removes the dependency on the
workflow's display name entirely.

Also honour GITHUB_UPDATE_REF through the existing getDispatchRef() helper
instead of hardcoding "main" twice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 17:30:10 +02:00
Hieu Nguyen (Jack) a9c99866e6 Merge pull request #9 from Karnak19/fix/reply-button
Wire up the Reply button
2026-08-21 18:45:57 +07:00
Basile VernouilletandClaude Opus 5 396fa81fcf Wire up the Reply button
The Reply button rendered without a click handler, so it did nothing. Clicking
it now creates a draft addressed to the sender, with a `Re:` subject and the
original message quoted, then opens the composer on that draft.

This reuses the existing pieces rather than adding new ones: POST /api/drafts
resolves the authorized sender from the mailbox, and openDraftComposer() already
knows how to open the composer onto an existing draft. Quoting goes through
getLatestEmailContent() so replying to a thread does not re-quote the whole
chain.

Fixes #8

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 18:05:27 +02:00
Dinesh-3018 6d835219d2 feat: profile picture upload for users
Users can upload a profile picture (JPEG/PNG/WebP/GIF, max 2 MB) from
Settings. Stored in the existing R2 bucket (avatars/<userId>), served
via an authenticated endpoint, shown in the header mailbox chip with
graceful fallback.

- users.avatar_key column (migration 0010 - single ALTER; regenerating
  also resynced the drizzle meta snapshots, which were behind the
  applied SQL migrations)
- GET/POST/DELETE /api/profile/avatar (auth required, type & size
  validated)
- hasAvatar flag on /api/auth/me
- ProfileAvatarForm card on the Settings page
- MailboxSelector renders the avatar

No new dependencies. Tested on a live deployment (upload, render,
remove, unauthenticated access -> 401).
2026-07-17 17:52:48 +05:30
Hieu Nguyen (Jack) dc973c6c39 push v0.1.12 2026-06-18 23:24:27 +07:00
Hieu Nguyen (Jack) be039d31e4 Improve message display 2026-05-27 09:57:48 +07:00
Hieu Nguyen (Jack) 1ddb40f994 Various update 2026-05-26 16:41:49 +07:00
Hieu Nguyen (Jack) 8a3c1d27fd Improve UI 2026-05-26 12:27:29 +07:00
Hieu Nguyen (Jack) 7b34119b15 cleanup 2026-05-26 10:56:49 +07:00
Hieu Nguyen (Jack) add11e1316 update seed data 2026-05-26 10:56:43 +07:00
Hieu Nguyen (Jack) d049b28df5 Cleanup layout 2026-05-26 09:38:52 +07:00
Hieu Nguyen (Jack) 301cf0e970 Update variable names 2026-05-26 08:58:47 +07:00
Hieu Nguyen (Jack) cf9d2a8919 minor updates 2026-05-26 08:26:17 +07:00
Hieu Nguyen (Jack) d6771603ef push to git 2026-05-26 08:19:09 +07:00