Message Viewing and Composition
Relevant source files
The following files were used as context for generating this wiki page:The Message Viewing and Composition system is a core feature of the Email Platform, providing users with the ability to retrieve, read, manage, and send emails. The system is comprised of a React-based frontend for user interaction and a Fastify-based API backend for data processing and persistence.
This document outlines the architecture of message handling, from fetching and displaying inbound emails to composing and sending outbound messages. It covers the frontend components, API endpoints, data flows, and key functionalities like searching, categorization, and performing actions on messages.
1. Message Retrieval and Display
Messages are retrieved from the backend via a set of RESTful API endpoints and displayed in the Dashboard page. The display is organized into a multi-pane layout, typically showing a message list and a detailed view of a selected message.
1.1. API Endpoints for Retrieval
The services/api/src/routes/messages.ts file defines all endpoints for message data access. All endpoints require JWT authentication.
| Method | Endpoint | Description |
|---|---|---|
GET | /messages | Retrieves a paginated list of messages for a specific inbox with filtering options. |
GET | /inboxes/:id/messages | An alternative route to get messages for a specific inbox. |
GET | /messages/search | Searches messages across all inboxes, with optional domain filtering. |
GET | /messages/search/fuzzy | Performs a fuzzy search on message content using pg_trgm similarity. |
GET | /messages/:id | Retrieves a single message by its UUID, including its attachments and inbox details. |
Sources: services/api/src/routes/messages.ts:13-255
1.2. Message Listing and Filtering
The frontend Dashboard.tsx component is responsible for fetching and displaying the list of messages. It supports pagination, search, and filtering.
Data Fetching Flow
The following diagram illustrates the sequence of events when a user selects an inbox to view messages.
This diagram shows the flow for fetching and displaying a list of messages.
Sources: services/web/src/pages/Dashboard.tsx:135-195, services/api/src/routes/messages.ts:13-71
Search Functionality
The API provides two types of search:
- Standard Search: A
WHEREclause withcontainsandmode: "insensitive"is used for filtering. It supports various query parameters. - Fuzzy Search: Uses a raw SQL query with PostgreSQL's
pg_trgmextension to perform a similarity search, ranking results by relevance.
Sources: services/api/src/routes/messages.ts:28-50, services/api/src/routes/messages.ts:200-225
The Dashboard.tsx component uses a debounced effect to trigger a search as the user types and can switch between standard and fuzzy search based on the query structure.
Sources: services/web/src/pages/Dashboard.tsx:150-153, services/web/src/pages/Dashboard.tsx:210-215
Query Parameters for GET /messages
| Parameter | Type | Description |
|---|---|---|
inboxId | string (uuid) | Required. The ID of the inbox to fetch messages from. |
limit | number | The number of messages to return (default 50, max 200). |
offset | number | The number of messages to skip for pagination (default 0). |
q | string | A general search query for subject, from/to address, or text body. |
hasAttachments | boolean | If true, only returns messages with attachments. |
isRead | boolean | Filters messages by their read status. |
start | string (datetime) | Filters messages received on or after this date. |
end | string (datetime) | Filters messages received on or before this date. |
Sources: services/api/src/routes/messages.ts:14-26, services/api/src/routes/messages.ts:77-94
1.3. Message Categorization
The frontend automatically categorizes emails into tabs: Primary, Updates, Promotions, and Social. This logic resides entirely within the CategoryTabs.tsx component.
The categorizeMessage function inspects the message's subject, sender address, and body for specific keywords to assign a category. Messages that do not match any specific category are classified as Primary.
| Category | Keywords |
|---|---|
| Updates | notification, alert, update, thông báo, cập nhật, reminder, confirm, verification, password, login, security, account |
| Promotions | sale, discount, offer, promo, deal, free, giảm giá, khuyến mãi, ưu đãi, miễn phí, coupon, voucher, shop, store, buy |
| Social | facebook, twitter, instagram, linkedin, youtube, tiktok, social, follow, like, comment, share, friend, connection, invite, join |
Sources: services/web/src/components/CategoryTabs.tsx:21-93
1.4. Message Detail View
When a user selects a message from the list, the MessageDetail.tsx component renders its content.
Key features of the detail view:
- Displays the message subject, sender/recipient information, and date.
- Renders the HTML body of the email.
- Lists any attachments, providing a download link. The download is handled by the
GET /attachments/:id/downloadAPI endpoint. - Provides action buttons for
Reply,Forward, and other management tasks.
Sources: services/web/srcs/components/MessageDetail.tsx, services/api/src/routes/messages.ts:358-385
2. Message Actions
Users can perform various actions on messages, both individually and in bulk. These actions are handled by the Dashboard.tsx component, which makes calls to the API. Most actions trigger an optimistic UI update for a responsive user experience.
Actions Flow
This diagram shows the typical flow for an action like marking a message as unread, featuring an optimistic UI update.
Sources: services/web/src/pages/Dashboard.tsx:343-362, services/api/src/routes/messages.ts:285-305
Supported Actions
| Action | API Endpoint | Frontend Handler | Description |
|---|---|---|---|
| Mark Read/Unread | PATCH /messages/:id/read | handleSelectMessage, handleMarkUnread | Toggles the isRead boolean flag on a message. |
| Pin/Unpin | PATCH /messages/:id/pin | handleTogglePin | Toggles the isPinned boolean flag. Pinned messages are sorted to the top. |
| Snooze | PATCH /messages/:id/snooze | handleSnooze | Sets the snoozedUntil timestamp to temporarily hide a message. |
| Delete | DELETE /messages/:id | handleDeleteMessage, handleBulkDelete | Performs a soft delete by setting the deletedAt timestamp. |
| Export | GET /messages/:id/export | (Not directly in Dashboard) | Generates and downloads a .eml file for the message. |
Sources: services/web/src/pages/Dashboard.tsx:329-483, services/api/src/routes/messages.ts:257-356
Message Export (.eml)
The GET /messages/:id/export endpoint constructs a standard RFC 5322 email file. It uses the mailbuild library to assemble the headers, text/HTML body, and attachments into a single .eml file that can be opened by any email client. Attachments are fetched from storage, base64-encoded, and appended to the multipart message.
Sources: services/api/src/routes/messages.ts:388-459
3. Message Composition
The platform supports sending outbound emails through a modal interface, if enabled (OUTBOUND_ENABLED=true).
Components
ComposeModal.tsx: A full-screen modal that provides the UI for writing an email. It includes fields for sender (From), recipient (To),Subject, a rich text editor for the body, and an attachment uploader.Editor.tsx: A wrapper around theQuillrich text editor, providing a standardized toolbar for text formatting.
Sources: services/web/src/components/ComposeModal.tsx, services/web/src/components/Editor.tsx
Composition and Sending Flow
The process of sending an email involves filling out the compose modal and submitting the data as a multipart/form-data request to the backend.
This diagram shows the user and system flow for composing and sending a new email.
Sources: services/web/src/components/ComposeModal.tsx:28-56, services/web/src/pages/Dashboard.tsx:509-518
The ComposeModal.tsx component sends the email data, including attachments, to the /messages/outbound endpoint. The implementation for this specific outbound endpoint is not present in the provided services/api/src/routes/messages.ts file but is defined as a target in the frontend. The blueprint.md suggests using an external service like Amazon SES or SendGrid for outbound mail.
Sources: services/web/src/components/ComposeModal.tsx:47, blueprint.md:129-132