Account Management & Onboarding
Relevant source files
The following files were used as context for generating this wiki page:
Mailiner manages email accounts locally within the browser's localStorage. The onboarding and account management system handles the lifecycle of these accounts, including initial setup, modification, deletion, and active account switching. Because browsers cannot open direct TCP connections, all account configurations include settings for a WebSocket-to-TCP proxy to communicate with IMAP and SMTP servers.
Sources: README.md:12-20, crates/mailiner-app/src/main.rs:242-246
Application Bootstrap and Routing
The application uses a bootstrap state machine to determine if a user needs to complete the onboarding process or can proceed to the main mail interface. When the app starts, it attempts to open the local account store and list existing accounts.
Bootstrap States
| State | Description |
|---|---|
LoadingStore | The application is currently opening the local storage and retrieving account lists. |
NeedsOnboarding | No accounts exist in storage. The UI redirects the user to the onboarding form. |
Ready | Accounts exist and are loaded. The user can access the main mail interface. |
StoreError | localStorage is unavailable or unreadable, preventing account persistence. |
Sources: crates/mailiner-app/src/main.rs:43-52, crates/mailiner-app/src/main.rs:360-380
Bootstrap Flow
The following diagram illustrates how the application resolves its initial state based on the local account store.
Onboarding Process
The onboarding process requires users to provide identity, IMAP, and proxy credentials. Mailiner enforces a "connect-before-persist" policy: the application must successfully connect and authenticate with the IMAP server before it saves the account settings to local storage.
Data Flow for New Accounts
When a user submits the onboarding or "Add Account" form, the system follows this sequence:
- Validation: The
build_config_from_formfunction validates input fields (e.g., non-empty strings, valid port numbers). - Connection Testing: The UI sends a
CoreEvent::TestConnectionorCoreEvent::CommitNewAccountto the core loop. - State Monitoring: The component watches
connection_statesfor aConnectionState::Readystatus. - Persistence: Upon success, the core loop saves the configuration and the UI transitions to the
Readybootstrap state.
Sources: crates/mailiner-app/src/components/onboarding.rs:163-188, crates/mailiner-app/src/components/account_form.rs:77-123
Account Management
Users manage existing accounts through the /settings/accounts view. This interface allows switching the active account, editing credentials, and deleting accounts.
Account Switching
Only one account stays connected at a time. Switching accounts involves updating the active_account_id in storage and notifying the core loop to disconnect the previous session and establish a new one. To prevent UI lag, account switching is debounced by 200ms.
Sources: crates/mailiner-app/src/components/accounts.rs:23-24, crates/mailiner-app/src/components/accounts.rs:102-123
Credential Updates
Editing an account uses the same form logic as onboarding. If "sensitive" credentials (host, port, username, password, or proxy settings) change, the app requires a successful connection test before saving the changes. Non-sensitive changes (e.g., display name) are persisted immediately to storage.
pub fn credentials_changed(old: &AccountConfig, new: &AccountConfig) -> bool {
old.imap.host != new.imap.host
|| old.imap.port != new.imap.port
|| old.imap.username != new.imap.username
|| old.imap.password != new.imap.password
|| old.imap.use_tls != new.imap.use_tls
|| old.proxy != new.proxy
}
Sources: crates/mailiner-app/src/components/account_form.rs:161-168, crates/mailiner-app/src/components/accounts.rs:528-560
Account Deletion
When you delete an account, the application removes the configuration from localStorage.
- If the deleted account was the active one, the app attempts to select the next available account.
- If you delete the last remaining account, the app transitions back to the
NeedsOnboardingstate and redirects you to the onboarding form.
Sources: crates/mailiner-app/src/components/accounts.rs:200-245
Security and Privacy
Account settings, including IMAP passwords and proxy tokens, are stored only in the browser's localStorage. Mailiner does not have a server-side component for account storage.
- Access Control: Anyone with access to the browser profile can read stored secrets.
- Data Removal: Clearing site data removes all account configurations and cached mail.
- Connection Security: While traffic passes through a WebSocket proxy, IMAP traffic remains TLS-wrapped from the client to the email server, preventing the proxy from reading the content.
Sources: README.md:27-38, crates/mailiner-app/src/components/accounts.rs:153-159
Configuration Fields
The following fields are required for account setup:
| Category | Field | Description |
|---|---|---|
| Identity | Display Name | Name shown to recipients. |
| Your email address. | ||
| IMAP | Host / Port | Incoming server address and port (default 993). |
| Username / Password | Your email credentials or app password. | |
| Proxy | Base URL | WebSocket proxy address (e.g., ws://localhost:9400/proxy). |
| Token | Authentication token for the proxy. | |
| SMTP | Host / Port | Outgoing server address and port (default 587 or 465). |
Sources: crates/mailiner-app/src/components/account_form.rs:242-320, crates/mailiner-app/src/components/account_form.rs:360-390
This onboarding and management system ensures that Mailiner remains a private, client-side application while providing the necessary infrastructure to bridge browser limitations for TCP-based protocols like IMAP and SMTP.