Browser Local Storage
Relevant source files
The following files were used as context for generating this wiki page:
Browser Local Storage serves as the primary persistence layer for Mailiner, enabling a serverless architecture where sensitive data remains strictly on the user's device. The application stores account configurations, mail folder structures, message metadata, and UI layout preferences as JSON-serialized blobs within the browser's localStorage API.
This localized approach ensures privacy by avoiding intermediate server storage. However, security depends on the browser profile's integrity; anyone with access to the profile can read the stored secrets, such as IMAP passwords and proxy tokens. Users must clear site data to remove these credentials.
Sources: README.md:36-41, crates/mailiner-app/src/components/accounts.rs:163-168
Storage Architecture and Key Management
Mailiner organizes data using specific string keys to segment different types of information. The application uses versioned keys to manage schema changes and prevent data corruption during updates.
Key Definitions
| Feature | Local Storage Key | Data Type | Description |
|---|---|---|---|
| Mail Cache | mailiner.cache.v1 | JSON Blob | Stores folder trees and message prefixes. |
| Folder Width | mailiner.layout.folderWidthPx | String (f64) | Width of the sidebar in pixels. |
| List Height | mailiner.layout.listHeightPct | String (f64) | Height of the message list as a percentage. |
Sources: crates/mailiner-app/src/mail_cache.rs:25, crates/mailiner-app/src/layout.rs:3-4
Data Flow Diagram
The following diagram illustrates how the application interacts with the browser's storage during runtime.
The MailCache trait abstracts persistence, allowing the application to switch between WebLocalStorage for production and an InMemoryMailCache for testing.
Sources: crates/mailiner-app/src/mail_cache.rs:40-42, crates/mailiner-app/src/mail_cache.rs:288-292
Mail Cache Management
The mail cache stores snapshots of folder trees and message-list prefixes to enable "instant first paint" when the application starts. To prevent localStorage overflow, the system implements strict size limits and eviction policies.
Cache Constraints
- Schema Version: Currently at version 1.
- Max Cache Size: The encoded JSON blob is capped at 1,500,000 bytes.
- Folder Limit: Retains snapshots for a maximum of 8 folders per account using LRU (Least Recently Used) eviction.
- Message Limit: Stores a maximum of 50 contiguous message envelopes per folder.
Sources: crates/mailiner-app/src/mail_cache.rs:27-33
LRU Eviction Logic
When the cache exceeds its byte budget or folder limit, the MailCacheBlob performs eviction.
- Folder-level: When
save_messagesis called and the account exceedsMAX_CACHED_FOLDERS, the oldest accessed folder is removed. - Blob-level: When
save_blobfails due to size, theevict_oldest_message_listfunction removes the globally oldest message-list snapshot until the blob fits theMAX_CACHE_BLOB_BYTESlimit.
Sources: crates/mailiner-app/src/mail_cache.rs:247-264, crates/mailiner-app/src/mail_cache.rs:335-348
Layout Persistence
UI layout preferences are synchronized with localStorage to maintain consistency across sessions. The layout.rs module manages the width of the folder pane and the height of the message list.
Persistence Procedures
- Clamping: Values are clamped before storage to ensure UI usability (e.g., Folder Width between 160px and 480px).
- Application: During startup,
apply_saved_layoutreads the stored values, parses them asf64, and injects them as CSS variables (--folder-pane-width,--message-list-height) directly into the#appelement style declaration.
Sources: crates/mailiner-app/src/layout.rs:6-12, crates/mailiner-app/src/layout.rs:77-106
Security and Privacy Considerations
Because Mailiner has no server-side account, localStorage is the sole authority for identity and credentials.
- Encryption: While IMAP connections are encrypted on the browser side, the credentials (IMAP password, proxy token) are stored in plaintext within
localStorage. - Isolation: The application uses a baseline Content-Security-Policy (CSP) to harden the origin against XSS, which protects these secrets from being exfiltrated by malicious scripts.
- Clearance: The
e2etests confirm that an emptylocalStoragetriggers theNeedsOnboardingstate, directing users to the setup form rather than the mail interface.
Sources: README.md:36-41, README.md:46-50, e2e/tests/app.spec.ts:3-12
Attachment Handling
While metadata is cached in localStorage, actual attachment data is handled via Blob objects and URL.createObjectURL. The StreamingBlobDownload system accumulates decoded octets as discrete parts in a JS Array to avoid large contiguous memory allocations before triggering a browser-native download.
Sources: crates/mailiner-app/src/download.rs:69-80, crates/mailiner-app/src/download.rs:134-142