# Fluxmail Self-Hosted documentation # Architecture URL: https://fluxmail.ai/docs/architecture ## Where your data lives [#where-your-data-lives] Fluxmail keeps its SQLite database on the machine where it runs. Google and Microsoft OAuth tokens, OAuth application secrets, license state, and IMAP/SMTP passwords are encrypted at rest with AES-256-GCM. Restart-bound deployment settings live in `/config.toml`; the encryption key remains outside that file. Your client talks to your email provider through the self-hosted Fluxmail process. Fluxmail does not copy email content to a service operated by Fluxmail. Content returned through MCP may be sent to the client's model provider, depending on how that client runs. The [code is source available](https://github.com/fluxmailai/fluxmail) under the [Elastic License 2.0](https://github.com/fluxmailai/fluxmail/blob/main/LICENSE.md). ## How requests flow [#how-requests-flow] Agents connect through MCP, apps and backend workflows use REST, and people or scripts can use the CLI. All three interfaces send email requests through the same service. Fluxmail selects the mailbox, checks access and plan limits, then passes the operation to Gmail, Microsoft Graph, or an IMAP/SMTP server. Mailbox routing, replies, forwards, and provider capabilities stay consistent across CLI, MCP, and REST. The CLI also connects mailboxes, manages members and API keys, changes configuration, and starts the MCP and REST services. Local CLI commands call route handlers in the Fluxmail process. Remote CLI profiles call the same routes over HTTPS. Each route resolves the member session or API key, applies the centralized access policy, and then calls the account, member, license, or mail service. ```text Local CLI --------------------\ Remote CLI and REST -----------> routes -> principal -> policy -> services -> SQLite HTTP MCP with an API key ------/ ``` CLI commands use the same REST operations, database, and provider connections as the running server. The CLI only handles terminal concerns such as flags, JSON input, local attachment files, and formatted output. Provider differences still affect the available behavior. Folders are places you can navigate, such as Inbox or Archive. Labels are tags that a message can have alongside its folder. Gmail user labels work as both navigable views and tags, so they appear in folder and label listings. Outlook folders appear as folders, while Outlook categories appear as labels. IMAP has folders but does not support label actions. It also uses the mail server's basic search and has no server-side thread model. Fluxmail reconstructs IMAP threads from standard email headers. ## How permissions are enforced [#how-permissions-are-enforced] Every authenticated request acts for one active member. Fluxmail first checks whether the member owns the mailbox, has an explicit grant, or can use it through `sharedWithAll`. It then applies an API key's optional account allowlist. An administrator can manage members and mailbox access, but the role does not grant access to private mailboxes. Stdio reads the selected local member session. HTTP MCP accepts scoped API keys. REST accepts sessions and API keys. Session authority follows the member's current role. API key authority is the intersection of its stored capabilities, its optional account allowlist, and its owner's current role and mailbox access. Administrative REST routes add a second check. A session owner must currently be an administrator. An API key also needs the capability for that route. Fluxmail has no memberless keys or unauthenticated mail mode. Authentication and management operations append rows to `admin_audit_events`. Database triggers prevent these rows from being changed or deleted. The table stores stable identifiers and outcome codes, not passwords, tokens, request bodies, or provider credentials. Fluxmail does not send actor or resource identifiers through anonymous telemetry. Attachments are returned as embedded MCP resources or raw REST responses. Attachment IDs are opaque strings and can contain punctuation such as `part:1.2`. Every provider enforces the configured decoded-size limit before returning the file. The default limit is 10 MB, and the hard maximum is 25 MB. Sends and forwards through REST, MCP, and CLI use delivery operations in SQLite. Each idempotency key is scoped to the authenticated credential and has no automatic expiry. Reusing a key with the same request returns the saved operation without sending again. If an operation is uncertain, check the Sent folder or recipient before creating another request. REST keys created before the delivery-operation upgrade keep their original 24 hour lifetime. --- # Authentication and instances URL: https://fluxmail.ai/docs/authentication-and-instances Fluxmail uses member sessions for people and API keys for MCP clients, scripts, and other automation. A member session follows the member's current role and mailbox access. An API key is narrower: Fluxmail also checks its capabilities and optional mailbox allowlist on every request. An *instance profile* tells your CLI which installation to use. A *member session* signs you in to that installation. A connected email *account* is a mailbox; its Google, Microsoft, or IMAP credentials are separate from your Fluxmail login. | Task | Use | | --------------------------------- | ------------------------------------------------- | | Create the first administrator | `fluxmail setup` once on a new instance | | Sign in again | `fluxmail --instance login` | | Connect a local MCP client | Saved local member session plus stdio permissions | | Connect an HTTP MCP client or app | A named, scoped API key | ## Set up a local instance [#set-up-a-local-instance] Run this once on a fresh instance: ```bash fluxmail setup --name "Your name" --email you@example.com ``` Fluxmail asks for a password without displaying it. The command creates the first administrator, adds a CLI profile named `local`, and saves a 90-day device session. Passwords must contain 8 to 256 Unicode characters. Fluxmail rejects common passwords and passwords based on the member's name or email address. It does not require a mix of uppercase letters, numbers, and symbols. ## Log in to an existing local instance [#log-in-to-an-existing-local-instance] List your profiles with `fluxmail instances list`, then log in with the name of the local profile you want to use: ```bash fluxmail --instance login ``` If your local profile was removed or the CLI files were lost, login can recreate the default profile named `local`: ```bash fluxmail --instance local login ``` On a machine with no CLI profiles at all, bare `fluxmail login` recreates the `local` profile and logs in there. If other profiles exist, name the local one explicitly as above. ## Log in to a remote instance [#log-in-to-a-remote-instance] Name the profile when you add a server: ```bash fluxmail --instance work login --server https://mail.example.com ``` Fluxmail asks for the member email and password. After the profile exists, the server URL is no longer needed: ```bash fluxmail --instance work login ``` Remote profiles require HTTPS. Plain HTTP is accepted only for loopback addresses such as `http://127.0.0.1:8977`. The CLI refuses redirects for authenticated remote requests so it cannot forward a session to another origin. If a reverse proxy terminates TLS and connects to Fluxmail from a non-loopback address, set `FLUXMAIL_TRUST_PROXY=1`. Fluxmail will then use the forwarded protocol and client address for HTTPS checks and login throttling. Enable this only when the proxy overwrites forwarded headers and blocks direct access to Fluxmail. List, select, or remove profiles with: ```bash fluxmail instances list fluxmail instances use work fluxmail instances remove work ``` `--instance ` overrides the selected profile for one command. Removing a profile deletes its local session secret but does not change the server or its data. ## Invite and enroll a member [#invite-and-enroll-a-member] An administrator creates a pending member: ```bash fluxmail members add --name "Grace Hopper" --email grace@example.com ``` The command prints a one-time enrollment code. It expires after seven days. Send it to the member through a private channel. The member enrolls with: ```bash fluxmail --instance work login --server https://mail.example.com --enroll ``` Fluxmail asks for the code and a new password without putting either secret in shell history. If the profile already exists, omit `--server`. Administrators can replace an unused or expired code with `fluxmail members invite `. Enrollment is only needed for the first password. Members use normal login afterward. ## Manage sessions [#manage-sessions] Member sessions have a server-enforced 90-day lifetime. Logout, suspension, removal, password reset, and explicit revocation take effect immediately. ```bash fluxmail auth sessions fluxmail auth revoke-session fluxmail logout ``` Administrators can inspect or revoke another member's sessions: ```bash fluxmail members sessions fluxmail members revoke-session ``` Password reset codes last for one hour: ```bash fluxmail members password-reset ``` The member redeems the code with `fluxmail --instance login --reset`. Email delivery is not built in, so the administrator must send the code privately. ## Use API keys for automation [#use-api-keys-for-automation] Create a key while logged in: ```bash fluxmail apikey create --name research-agent --profile read-only ``` The key belongs to the current member and is shown once. It can only reach mailboxes available to that member. Use repeated `--account` options to narrow it to specific mailboxes. Administrators can issue a key for another member with `--member `. Administrative capabilities require an administrator owner and an explicit `admin.*` capability. Demoting or suspending the owner removes that authority immediately. HTTP MCP accepts API keys, not member sessions: ```http Authorization: Bearer fmk_... ``` REST accepts either an API key or the `fms_...` session used by the CLI. A future web dashboard can use the same REST operations through a browser cookie adapter. ## Local stdio [#local-stdio] `fluxmail stdio` uses the authenticated member session from the selected local profile. It does not accept a member override. We recommend Full access for normal MCP use. It allows reading, sending, scheduling, drafts, organization, and moving mail into or out of Trash. It excludes permanent deletion. Choose `read-write` or `read-only` for [restricted access](/docs/permissions). Bare stdio and API-key creation without permission options remain read-only. To select Full explicitly: ```bash fluxmail stdio --profile full ``` Without `--instance`, stdio uses the active local profile, then a local profile named `local`, then the sole local profile under any other name. If several local profiles exist and none is active or named `local`, choose one with `fluxmail --instance stdio`. An explicit `--instance` must select a local profile. Stdio does not change the active profile for other CLI commands. Stdio is local only. Use the HTTP MCP endpoint and a scoped API key for remote MCP clients. Stdio can create schedules but does not deliver them; keep `fluxmail serve` or `fluxmail scheduled run` running with the same data directory for scheduled delivery. ## Stored CLI files [#stored-cli-files] Fluxmail keeps profile metadata and session secrets in separate files under `/cli`. Both files are readable only by their owner, and the directory uses owner-only permissions. The session file contains the bearer secret. Copying the profile file alone does not copy a login. ## Recover a local administrator [#recover-a-local-administrator] If every administrator session is unavailable, someone with filesystem access to the instance can reset an existing administrator: ```bash fluxmail auth recover-admin ``` The command is local only. It sets a new password, reactivates that administrator if needed, revokes their sessions, and writes a security audit event. It cannot create a member or bypass plan limits. Finish `fluxmail setup` before using administrator recovery. Migrated instances must claim an existing administrator during setup first. --- # Back up and restore URL: https://fluxmail.ai/docs/backup-and-restore Back up the complete Fluxmail data directory before an upgrade or move. By default it is `~/.fluxmail` locally and `/data` in Docker. The database and its matching encryption key must stay together: a database backup cannot decrypt credentials without that key. Also save your deployment configuration and the installed Fluxmail version or image digest. If you use `FLUXMAIL_DB_PATH`, an external encryption key, or `*_FILE` secrets outside the data directory, back up those separately. Keep backups private; they contain credentials and member sessions. ## Back up a local installation [#back-up-a-local-installation] Stop every Fluxmail process that uses the directory, including MCP clients that launch `fluxmail stdio`. Copy the complete directory to a private backup location while it is stopped, then restart your clients or server. On macOS or Linux, for the default directory: ```bash umask 077 tar -C "$HOME" -czf fluxmail-backup.tar.gz .fluxmail ``` Use a new backup filename for each backup. Check that the archive can be listed before relying on it: ```bash tar -tzf fluxmail-backup.tar.gz ``` Check for the database, configuration, and `encryption.key`, unless you manage the key externally. Archive listings show filenames, not credential values. ## Back up Docker storage [#back-up-docker-storage] Run these commands from the Compose directory. They assume the standard `/data` volume and use the configured Fluxmail image as a stopped-service backup helper: ```bash umask 077 docker compose stop fluxmail docker compose run --rm --no-deps -T --entrypoint tar fluxmail \ -C /data -czf - . > fluxmail-data-backup.tar.gz ``` Wait for the command to finish successfully, then check the archive: ```bash tar -tzf fluxmail-data-backup.tar.gz docker compose up -d fluxmail ``` Do not copy a live SQLite database file on its own. Stopping all writers and copying the complete directory keeps the database and any journal files together. The backup helper does not start the Fluxmail server. Save `.env`, the Compose file, and any external secret files separately in the same private backup system. Do not commit them to source control. Keep a copy outside the server so a disk failure cannot destroy the installation and its only backup. ## Restore a local installation [#restore-a-local-installation] Review pending scheduled sends before bringing an old backup online: messages whose scheduled time passed while the service was stopped can be sent at startup. Keep restoration tests isolated from provider access until you intend the restored instance to resume work. 1. Stop every process using the data directory. 2. Keep the current directory as a separate recovery copy. Restore the backup into an empty directory, rather than overlaying an existing database and its journal files. 3. Restore any external database path, encryption key, or secret files and their owner-only permissions. 4. Start the Fluxmail version recorded with the backup. If you intend to upgrade, verify the restored installation first, then follow the upgrade guide. 5. Run the checks below. For an archive made with the local example, extract it into an empty recovery directory with `tar -xzf /path/to/fluxmail-backup.tar.gz -C /path/to/recovery`. It creates `.fluxmail` there. Move that restored directory into the configured data location after preserving the old one. ## Restore Docker storage [#restore-docker-storage] Stop the service and keep its current volume. Restore into a new, empty volume so the original remains available if verification fails. Review scheduled sends before starting the restored server; an overdue send can run at startup. Edit the existing `volumes` mount for the `fluxmail` service in `docker-compose.yml` to use a new volume name, and declare it at the top level: ```yaml services: fluxmail: volumes: - fluxmail-restored:/data volumes: fluxmail-restored: ``` This is an excerpt: keep the service's image, ports, environment, and other settings. Choose a volume name you have not used before. Set the image to the version recorded with the backup and restore the matching external secrets before starting it. From the Compose directory, restore the archive: ```bash docker compose run --rm --no-deps -T --entrypoint tar fluxmail \ -C /data -xzf - < fluxmail-data-backup.tar.gz docker compose up -d fluxmail ``` Run the extraction only after stopping the original service. Check its exit status before starting Fluxmail. Keep the original volume until you have verified the restored service. ## Verify the restored installation [#verify-the-restored-installation] ```bash fluxmail status fluxmail accounts list fluxmail oauth status fluxmail --mail-account folders list ``` For Docker, prefix each command with `docker compose exec fluxmail`. Log in again if the saved member session has expired. Check a client connection with its existing API key or stdio configuration as well. If Fluxmail cannot decrypt credentials, restore the matching encryption key. Generating a new key does not recover the encrypted records. If a provider token was revoked after the backup, [reconnect that mailbox](/docs/troubleshooting#a-mailbox-needs-to-be-reconnected). --- # Build with REST URL: https://fluxmail.ai/docs/build-with-rest Use the REST API to work with Gmail, Outlook, and IMAP mailboxes from an app or script. Start with a connected mailbox from the [local quickstart](/docs/quickstart) or [Docker guide](/docs/deploy-with-docker). This walkthrough uses read-only access. It verifies the connection, lists inbox messages, and fetches a message you choose. ## 1. Start the API and create a key [#1-start-the-api-and-create-a-key] Before starting an existing stopped instance, [review pending schedules](/docs/sending-and-retries#before-restarting-an-existing-instance). Starting the server can resume overdue sends independently of this tutorial's read-only API key. Find the mailbox ID with `fluxmail accounts list`, then create a key for your app: ```bash fluxmail apikey create --name my-app --profile read-only --account ``` For Docker, run that command with `docker compose exec fluxmail`. Docker already runs the HTTP server. For a local installation, start it in a separate terminal: ```bash fluxmail serve ``` Fluxmail displays the key once. Store it in your app's secret store. For the requests below, load it into `FLUXMAIL_API_KEY` in a private terminal without putting the value in shell history. Set the base URL and account ID: ```bash export FLUXMAIL_API_URL='http://localhost:8977/api/v1' export FLUXMAIL_ACCOUNT_ID='' ``` For a remote server, use its public HTTPS URL followed by `/api/v1`. ## 2. Find your mailbox [#2-find-your-mailbox] ```bash curl --fail-with-body "$FLUXMAIL_API_URL/accounts" \ -H "Authorization: Bearer $FLUXMAIL_API_KEY" ``` The response has a `data` array. A shortened example: ```json { "data": [ { "id": "acct_123", "provider": "gmail", "email": "you@example.com", "status": "active" } ] } ``` Set `FLUXMAIL_ACCOUNT_ID` to the returned `id`. An empty array means this key has no visible mailboxes; check the member's mailbox access and the key's allowlist. See [Permissions](/docs/permissions). ## 3. Verify provider access [#3-verify-provider-access] ```bash curl --fail-with-body \ "$FLUXMAIL_API_URL/accounts/$FLUXMAIL_ACCOUNT_ID/folders" \ -H "Authorization: Bearer $FLUXMAIL_API_KEY" ``` A successful folder listing confirms that the key works and Fluxmail can reach your provider. It does not read message bodies or change mail. You can stop here when you only want to verify setup. Folders describe navigable mailbox locations. The separate `/accounts//labels` endpoint returns Gmail user labels or Outlook categories. Gmail user labels appear in both listings; IMAP does not support the labels endpoint. ## 4. List inbox messages [#4-list-inbox-messages] When you're ready to retrieve email, request five inbox messages: ```bash curl --fail-with-body \ "$FLUXMAIL_API_URL/accounts/$FLUXMAIL_ACCOUNT_ID/messages?folder=inbox&pageSize=5" \ -H "Authorization: Bearer $FLUXMAIL_API_KEY" ``` The response contains metadata for each message. This shortened example shows the fields to use in the next request: ```json { "data": [ { "id": "msg_123", "accountId": "acct_123", "subject": "Project update", "from": { "email": "ann@example.com" } } ], "meta": { "nextPageToken": "opaque-continuation-token", "exhausted": false } } ``` If `meta.nextPageToken` is present, send it as `pageToken` with the same account and request settings. Treat an empty page as a confirmed end only when `meta.exhausted` is `true`. Tokens are opaque; URL-encode them when constructing requests. Gmail and Outlook include native snippets by default. Use `includeSnippet=true` for IMAP previews, or `false` to suppress previews for any provider. Filters such as `read=false`, `from=person@example.com`, and `text=invoice` narrow the results. The `query` parameter supports [portable search syntax](/docs/email-search); `includeSearchContext=true` requests an excerpt around a literal body match. See [List messages](/docs/rest-api/list-messages) for all parameters and the complete response schema. ## 5. Read a message [#5-read-a-message] Use an ID returned by the list request: ```bash curl --fail-with-body \ "$FLUXMAIL_API_URL/accounts/$FLUXMAIL_ACCOUNT_ID/messages/" \ -H "Authorization: Bearer $FLUXMAIL_API_KEY" ``` This retrieves the message body and attachment metadata. Use [Get a thread](/docs/rest-api/get-thread) for a conversation. Keep attachment IDs exactly as returned, including IMAP IDs such as `part:1.2`, and pass them to the [download operation](/docs/rest-api/download-attachment). ## Handle errors [#handle-errors] Check the HTTP status before reading `data`. Errors include a safe code and request ID. Input errors describe the invalid field, and search errors include `error.data.diagnostics`. Provider error text is not returned. A `401` usually requires checking the bearer token. A `403` requires checking the requested operation and mailbox against the key's permissions. Use [Troubleshooting](/docs/troubleshooting) for the next checks. ## Continue building [#continue-building] Use [batch search](/docs/rest-api/search-messages) to search several mailboxes in one request. Results are grouped by account; inspect each group's errors even when another account succeeds. For writes, create or update a key with the capabilities your workflow needs. `read-write` permits drafts and organization; sending requires `mail.send`. Read [Sending and retries](/docs/sending-and-retries) before implementing delivery, and [Modify messages](/docs/rest-api/modify-messages) before bulk changes. Bulk results report `succeededIds`, `failed`, and `uncertainIds`; inspect uncertain messages before retrying and send at most 100 distinct IDs per request. The [REST reference](/docs/rest-api) lists all endpoints. Your running instance serves its OpenAPI 3.1 document at `/api/v1/openapi.json`. --- # Configuration URL: https://fluxmail.ai/docs/configuration Deployment settings control startup, storage paths, and the server address. Instance settings hold OAuth applications and the license. Start with the setting you need to change: | Task | Where to change it | Restart? | | -------------------------------------------- | -------------------------------------------------- | -------------------------------------- | | Change the port, public URL, or storage path | `config.toml` or process environment | Yes | | Configure a Google or Microsoft OAuth app | `fluxmail oauth configure` | No, unless using environment overrides | | Activate a license | `fluxmail license activate` | No, unless using environment overrides | | Inspect effective settings and their sources | `fluxmail config show` and `fluxmail oauth status` | No | ## Deployment configuration [#deployment-configuration] Deployment settings are resolved in this order: 1. Built-in defaults 2. `/config.toml` 3. Process environment variables Changes to deployment settings require a restart. Run `fluxmail config init` to create a starter file with owner-only permissions. Run `fluxmail config show` to see effective values, their sources, and the paths Fluxmail is using. `FLUXMAIL_DATA_DIR` stays outside `config.toml` because it tells Fluxmail where to find the file. It defaults to `~/.fluxmail`, or `/data` in the Docker image. A typical file looks like this: ```toml [storage] database_path = "/var/lib/fluxmail/fluxmail.db" [server] port = 8977 public_url = "https://mail.example.com" trust_proxy = false max_attachment_mb = 10 [oauth.local] host = "127.0.0.1" port = 8976 ``` Fluxmail rejects unknown TOML keys, invalid types, and values outside their allowed ranges. It does not change `process.env` while resolving settings. ## Instance settings [#instance-settings] Custom Google and Microsoft OAuth applications and the license key are stored as encrypted records in SQLite. Changes made with `fluxmail oauth configure`, `fluxmail oauth reset`, or `fluxmail license activate` take effect immediately. You do not need to restart the server. Use `fluxmail oauth status` to see client IDs, tenant IDs, configuration state, and source categories. Status output never includes client secrets, ciphertext, secret-file paths, or environment values. Environment variables can override a complete provider group. When a provider comes from the environment, authenticated commands and APIs cannot replace or reset it until you remove the overrides and restart Fluxmail. * Google requires both `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`. * Microsoft requires `MICROSOFT_CLIENT_ID` when any Microsoft override is present. `MICROSOFT_TENANT_ID` defaults to `common`. Public clients can omit `MICROSOFT_CLIENT_SECRET`. ## Secret storage [#secret-storage] Fluxmail encrypts instance settings and provider credentials with AES-256-GCM before writing them to SQLite. Encrypted values use a versioned storage envelope so future releases can migrate the format safely. The encryption key is resolved from one source: 1. `FLUXMAIL_ENCRYPTION_KEY` 2. `FLUXMAIL_ENCRYPTION_KEY_FILE` 3. `/encryption.key` Fluxmail generates `/encryption.key` with owner-only permissions when no external key is configured. Back up this file with the database. A database backup is not usable without the matching key. Follow [Back up and restore](/docs/backup-and-restore) to preserve the complete installation. For managed deployments, use `*_FILE` variables instead of putting secrets directly in the process environment. Fluxmail supports files for `FLUXMAIL_ENCRYPTION_KEY`, `GOOGLE_CLIENT_SECRET`, `MICROSOFT_CLIENT_SECRET`, and `FLUXMAIL_LICENSE_KEY`. Paths must be absolute. Fluxmail reads UTF-8, removes one final newline, rejects empty files, and leaves externally managed file permissions unchanged. ## Import an env file [#import-an-env-file] Fluxmail does not read `config.env`, `.env.local`, or `.env` files. Import settings from an existing file before starting Fluxmail: ```bash fluxmail config migrate --from /absolute/path/to/old.env --dry-run fluxmail config migrate --from /absolute/path/to/old.env ``` If the source file sets `FLUXMAIL_DATA_DIR`, that directory is the migration target. Otherwise, the command uses `FLUXMAIL_DATA_DIR` from the process environment or the default data directory. The command validates imported deployment values and checks the database format before writing anything. If the target database already contains encrypted values, you must provide its existing encryption key. Fluxmail will not generate a replacement key for that database. The command writes deployment settings to `config.toml`, stores OAuth applications and the license in encrypted SQLite records, and preserves the source file. If the encrypted settings step fails, Fluxmail removes only the new `config.toml` and `encryption.key` files created by that import. Run `fluxmail config show` and `fluxmail oauth status` after the import. Remove the old `config.env` after you verify the result. Docker Compose and process-manager env files still work because those tools populate the process environment before Fluxmail starts. ## Outbound proxy [#outbound-proxy] If Gmail or Google sign-in requests need an HTTP proxy, set `HTTPS_PROXY` in the Fluxmail process environment before starting the server. Fluxmail also accepts `https_proxy`, `HTTP_PROXY`, and `http_proxy`. When several are set, it uses the first of `HTTPS_PROXY`, `https_proxy`, `HTTP_PROXY`, and `http_proxy`. Use an `http://` or `https://` proxy URL. Fluxmail keeps proxy connections open on supported Node.js versions. A Gmail search can reuse a tunnel while reading messages. With an `https://` proxy, Fluxmail includes the proxy hostname in the TLS handshake so the proxy can present the right certificate. To send some requests directly, list hosts in `NO_PROXY` (or `no_proxy`), separated by commas. Each entry can be: * `*`, which skips the proxy for every host * A hostname, such as `gmail.googleapis.com` * A domain suffix, such as `.googleapis.com` or `*.googleapis.com` * An origin, such as `https://gmail.googleapis.com` These variables apply to Gmail API and Google sign-in requests. They do not change Outlook or IMAP connections. Restart Fluxmail after changing them. ## Local logs [#local-logs] Fluxmail writes bounded local logs for failures and low-volume service events. Successful MCP, REST, and CLI operations are not logged. See [Local logs](/docs/logging) for the file location, the 20 MiB disk limit, viewing commands, and privacy notes. ## Setting reference [#setting-reference] | Setting | Primary storage | Environment override | Default | Applies | Purpose | | ------------------------------- | -------------------------- | ----------------------------------------------------------- | ----------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------ | | `deployment.data_dir` | External | `FLUXMAIL_DATA_DIR` | `~/.fluxmail (/data in Docker)` | Restart | Directory for the SQLite database, deployment configuration, and generated encryption key. | | `storage.database_path` | `storage.database_path` | `FLUXMAIL_DB_PATH` | `/fluxmail.db` | Restart | Override the SQLite database path. | | `deployment.encryption_key` | External | `FLUXMAIL_ENCRYPTION_KEY`
`FLUXMAIL_ENCRYPTION_KEY_FILE` | `generated automatically` | Restart | A 64-character hexadecimal key used to encrypt credentials and instance secrets. | | `server.port` | `server.port` | `FLUXMAIL_PORT` | `8977` | Restart | HTTP server port. | | `server.public_url` | `server.public_url` | `FLUXMAIL_PUBLIC_URL` | `http://localhost:` | Restart | Public base URL used for HTTP APIs and hosted OAuth callbacks. | | `server.trust_proxy` | `server.trust_proxy` | `FLUXMAIL_TRUST_PROXY` | `false` | Restart | Trust forwarded protocol and client address headers from a reverse proxy. | | `oauth.local.port` | `oauth.local.port` | `FLUXMAIL_OAUTH_PORT` | `8976` | Restart | Port for the local OAuth callback listener. | | `oauth.local.host` | `oauth.local.host` | `FLUXMAIL_OAUTH_HOST` | `127.0.0.1` | Restart | Bind address for the local OAuth callback listener. | | `server.max_attachment_mb` | `server.max_attachment_mb` | `FLUXMAIL_MAX_ATTACHMENT_MB` | `10` | Restart | Largest decoded attachment returned through MCP or REST, from 1 through 25 MB. | | `logging.level` | `logging.level` | `FLUXMAIL_LOG_LEVEL` | `info` | Restart | Minimum severity retained by the bounded local logger. | | `logging.destination` | `logging.destination` | `FLUXMAIL_LOG_DESTINATION` | `both` | Restart | Write local logs to both the rotating file and console, or choose file or console. | | `oauth.google.client_id` | Encrypted SQLite | `GOOGLE_CLIENT_ID` | `Fluxmail Desktop OAuth app` | Immediate; env: restart | Override the built-in Google OAuth client ID. | | `oauth.google.client_secret` | Encrypted SQLite | `GOOGLE_CLIENT_SECRET`
`GOOGLE_CLIENT_SECRET_FILE` | `Fluxmail Desktop OAuth app` | Immediate; env: restart | Override the built-in Google OAuth client secret. Required with GOOGLE\_CLIENT\_ID. | | `oauth.microsoft.client_id` | Encrypted SQLite | `MICROSOFT_CLIENT_ID` | `required for Outlook` | Immediate; env: restart | Microsoft Entra application client ID. | | `oauth.microsoft.client_secret` | Encrypted SQLite | `MICROSOFT_CLIENT_SECRET`
`MICROSOFT_CLIENT_SECRET_FILE` | `required for hosted Outlook connections` | Immediate; env: restart | Microsoft Entra application client secret. | | `oauth.microsoft.tenant_id` | Encrypted SQLite | `MICROSOFT_TENANT_ID` | `common` | Immediate; env: restart | Microsoft Entra tenant ID or verified domain. | | `license.key` | Encrypted SQLite | `FLUXMAIL_LICENSE_KEY`
`FLUXMAIL_LICENSE_KEY_FILE` | `none` | Immediate; env: restart | Paid-plan license key, normally stored with fluxmail license activate. | | `telemetry.enabled` | Data directory marker | `FLUXMAIL_TELEMETRY` | `1` | Before startup | Set to 0 to turn off anonymous CLI, MCP, and REST usage telemetry. | | `telemetry.do_not_track` | Data directory marker | `DO_NOT_TRACK` | `unset` | Before startup | Set to 1 to turn off anonymous usage telemetry. | HTTP MCP requests require an API key. REST requests accept an active member session or API key. See [Permissions](/docs/permissions) and [Authentication and instances](/docs/authentication-and-instances). ## Telemetry [#telemetry] Fluxmail sends anonymous operation events and grouped error reports by default. They exclude email content, credentials, command arguments, and original error text. See [Telemetry](/docs/telemetry) for the event fields and exclusions. To turn it off for this installation: ```bash fluxmail telemetry disable ``` You can also set `FLUXMAIL_TELEMETRY=0` or `DO_NOT_TRACK=1`. Any disabling source takes priority. Run `fluxmail telemetry status` to check the effective state. --- # Connect IMAP/SMTP URL: https://fluxmail.ai/docs/connect-an-imap-mailbox Fluxmail can connect to email providers that offer IMAP for reading mail and SMTP for sending it. ## 1. Find your provider settings [#1-find-your-provider-settings] Before you start, find the IMAP and SMTP settings from your email provider. Some providers require an app password instead of your usual email password. Fluxmail defaults to IMAP over TLS on port 993 and SMTP with STARTTLS on port 587. It uses the mailbox address as the username for both connections. You can override each of these settings when you connect the mailbox. ## 2. Connect the mailbox [#2-connect-the-mailbox] Choose the setup that matches how you run Fluxmail. For a fresh local instance, create the first administrator and log in: ```bash fluxmail setup --name "Your name" --email you@example.com ``` ### Local terminal [#local-terminal] Run: ```bash fluxmail accounts add imap \ --email you@example.com \ --imap-host imap.example.com \ --smtp-host smtp.example.com ``` Fluxmail prompts for the password without showing it on screen. If your provider uses different settings, pass the matching options: ```bash fluxmail accounts add imap \ --email you@example.com \ --display-name 'Your Name' \ --imap-host imap.example.com \ --imap-port 143 \ --imap-security starttls \ --imap-user your-username \ --smtp-host smtp.example.com \ --smtp-port 465 \ --smtp-security tls \ --smtp-user your-username ``` Both security options accept `tls` or `starttls`. Fluxmail checks both connections before saving the mailbox. Mailbox passwords are encrypted at rest with AES-256-GCM in Fluxmail's local SQLite database. ### Docker [#docker] For an interactive setup, run the same command inside the container. Enter the password at the private prompt: ```bash docker compose exec fluxmail \ fluxmail accounts add imap \ --email you@example.com \ --imap-host imap.example.com \ --smtp-host smtp.example.com ``` ### Scripts and non-interactive environments [#scripts-and-non-interactive-environments] Load the app password into `IMAP_PASSWORD` through your secret store or a private prompt, then pass the variable name to Fluxmail. Avoid typing the secret into a shell command that will be saved in history: ```bash fluxmail accounts add imap \ --email you@example.com \ --imap-host imap.example.com \ --smtp-host smtp.example.com \ --imap-password-env IMAP_PASSWORD ``` Fluxmail uses the IMAP password for SMTP too. If they differ, load a second variable and pass its name with `--smtp-password-env`. For Docker, pass the existing variable into the container: ```bash docker compose exec -e IMAP_PASSWORD fluxmail \ fluxmail accounts add imap \ --email you@example.com \ --imap-host imap.example.com \ --smtp-host smtp.example.com \ --imap-password-env IMAP_PASSWORD ``` ## 3. Verify the connection [#3-verify-the-connection] List the connected mailboxes, then use the IMAP account ID to fetch its folders: ```bash fluxmail accounts list fluxmail --mail-account folders list ``` For Docker, prefix both commands with `docker compose exec fluxmail`. The folder call checks provider access without reading message bodies or changing mail. Continue with [MCP setup](/docs/connect-an-mcp-client) or [REST](/docs/build-with-rest) to verify access through your client as well. ## If a special folder is missing or incorrect [#if-a-special-folder-is-missing-or-incorrect] Fluxmail looks for Sent, Drafts, Trash, Archive, and Spam folders using the server's special-use flags first, then common folder names such as `Sent Items` and `Junk Mail`. It prints a warning when a folder is missing or ambiguous, but still connects the mailbox. Fluxmail does not create a missing folder or guess when several folders match. An action that needs an unresolved folder returns an error. This prevents an archive or trash command from moving mail to the wrong place. Set the right folder path with the account ID from `fluxmail accounts list`: ```bash fluxmail accounts configure --sent-folder 'Sent Items' fluxmail accounts configure --trash-folder 'Deleted Messages' ``` You can configure `--sent-folder`, `--drafts-folder`, `--trash-folder`, `--archive-folder`, and `--spam-folder`. Pass `auto` to remove an override and let Fluxmail detect that folder again: ```bash fluxmail accounts configure --trash-folder auto ``` ## Optional: avoid duplicate Sent messages [#optional-avoid-duplicate-sent-messages] Fluxmail normally saves an SMTP submission in the resolved Sent folder. Some mail services already save SMTP submissions themselves. If yours does, add `--no-save-sent` when you connect the mailbox so each message appears only once: ```bash fluxmail accounts add imap \ --email you@example.com \ --imap-host imap.example.com \ --smtp-host smtp.example.com \ --no-save-sent ``` ## Connect through REST [#connect-through-rest] An administrative client can test settings without saving them at `POST /api/v1/admin/imap/tests`, then connect the mailbox at `POST /api/v1/admin/connections`. The API key needs `admin.accounts`. ```bash curl "$FLUXMAIL_PUBLIC_URL/api/v1/admin/connections" \ -X POST \ -H "Authorization: Bearer $FLUXMAIL_ADMIN_API_KEY" \ -H "Content-Type: application/json" \ --data '{ "provider": "imap", "ownerMemberId": "you@example.com", "email": "you@example.com", "imap": { "host": "imap.example.com", "port": 993, "security": "tls", "user": "you@example.com", "password": "app-password" }, "smtp": { "host": "smtp.example.com", "port": 587, "security": "starttls", "user": "you@example.com", "password": "app-password" }, "saveSent": true }' ``` Fluxmail tests IMAP and SMTP within 30 seconds before it saves the mailbox. The response does not echo either password. Reauthorization keeps the existing `saveSent` value and folder overrides when those fields are omitted. Mailbox owners can update folder mappings with `PATCH /api/v1/accounts/:accountId/imap/folders`. Administrators can use `PATCH /api/v1/admin/accounts/:accountId/imap/folders` for any mailbox. A string sets a folder path. `null` removes an override and restores automatic detection. Fluxmail validates every requested path before saving any of them. ## How Fluxmail works with IMAP [#how-fluxmail-works-with-imap] If the SMTP account has aliases, an administrator can register those existing addresses in Fluxmail. The selected address is used in both the From header and SMTP envelope. Your SMTP server must allow it. See [Send from another address](/docs/send-as-addresses). Fluxmail uses IMAP to read and organize the mailbox, and SMTP to send messages. The available behavior depends partly on the mail server: * Each message lives in a folder. Fluxmail can move messages between folders, but IMAP mailboxes do not support label actions. * Fluxmail builds threads from the standard `References`, `In-Reply-To`, and `Message-ID` headers. * Searches run through the IMAP server, so results depend on what that server can index. * List and search results omit previews by default. Pass `includeSnippet=true` to fetch a short preview from the preferred text part without downloading attachments or complete messages. The `snippets: false` capability means IMAP has no preview available without a body read. It does not disable requested previews. * Pass `includeSearchContext=true` with a literal text query to fetch an excerpt around the match. Fluxmail scans at most 256 KiB from the preferred text part. If you also request a snippet, both values come from one partial, non-marking body read. Through MCP or REST, Fluxmail can read and search mail, work with attachments and drafts, send or schedule messages, reply, forward, and organize messages into folders. Continue with [Connect an MCP client](/docs/connect-an-mcp-client), [Build with REST](/docs/build-with-rest), or [Use the CLI](/docs/use-the-cli). --- # Connect an MCP client URL: https://fluxmail.ai/docs/connect-an-mcp-client Connect your client after installing Fluxmail and connecting a mailbox through the [local quickstart](/docs/quickstart) or [Docker guide](/docs/deploy-with-docker). For an agent to do the configuration, use [agent-first setup](/docs/quickstart#agent-first-setup). Stdio can create and inspect schedules within the client's permissions, but it does not deliver them. For a stdio installation, keep `fluxmail serve` or `fluxmail scheduled run` running with the same data directory. Remote HTTP installations already deliver schedules through `serve`, including after a client disconnects. Before starting a delivery worker, [review pending schedules](/docs/sending-and-retries#before-restarting-an-existing-instance). ## Choose one transport [#choose-one-transport] | Where Fluxmail runs | Transport | Authentication | | ---------------------------------- | --------------- | ------------------------------- | | On the same computer as the client | stdio | Your saved local member session | | In Docker or on another machine | Streamable HTTP | A Fluxmail API key | Use one transport per connection. We recommend Full access for normal MCP use, and the examples below select it explicitly. Full allows reading, sending, scheduling, drafts, organization, and moving mail into or out of Trash. It excludes permanent deletion. Choose `read-write` or `read-only` for [restricted access](/docs/permissions). Bare stdio and API-key creation without permission options remain read-only. HTTP clients must support an Authorization header or a compatible local bridge. Check your client's entry before creating a key. Regular ChatGPT developer-mode connections cannot use Fluxmail's bearer API keys; the Codex connection is a separate client setup. ## Option 1: Connect over stdio [#option-1-connect-over-stdio] Your client launches `fluxmail stdio --profile full` using the member session saved during setup. You do not need to start `fluxmail serve`. The client must run as the same operating-system user and use the same data directory as setup. Add `--account ` to the arguments to limit the client to one mailbox. Repeat it for several mailboxes. For multiple local instances or a custom installation path, see [Local instance settings](#local-instance-settings). ## Option 2: Connect over Streamable HTTP [#option-2-connect-over-streamable-http] Create a named API key on the instance your client will use. This example grants Full access to one mailbox: ```bash fluxmail apikey create --name my-agent --profile full --account ``` For Docker, prefix that command with `docker compose exec fluxmail`. The key is shown once. Store it in the client's secret store or private configuration; never commit a real key or paste it into a chat. A local installation also needs a running HTTP server: ```bash fluxmail serve ``` Docker Compose already starts the server. The local endpoint is `http://localhost:8977/mcp`. For a remote server, use its public HTTPS URL followed by `/mcp`. ## Choose your client [#choose-your-client] Use the local or HTTP instructions within your client's section. In HTTP examples, replace the URL with your server's endpoint and enter the key privately wherever `fmk_...` appears. Preserve other servers in your configuration. ### Claude Code [#claude-code] #### Local connection [#local-connection] ```bash claude mcp add fluxmail -- fluxmail stdio --profile full ``` #### HTTP connection [#http-connection] ```bash claude mcp add --transport http fluxmail http://localhost:8977/mcp \ --header "Authorization: Bearer fmk_..." ``` ### Claude Desktop [#claude-desktop] #### Local connection [#local-connection-1] Add this server to `claude_desktop_config.json` under Settings > Developer > Edit Config: ```json { "mcpServers": { "fluxmail": { "command": "fluxmail", "args": ["stdio", "--profile", "full"] } } } ``` #### HTTP connection [#http-connection-1] Claude Desktop's built-in remote connectors accept OAuth or no authentication, so they cannot send a Fluxmail API key. Use the local [`mcp-remote`](https://github.com/geelen/mcp-remote) bridge. Add this server to `claude_desktop_config.json` under Settings > Developer > Edit Config: ```json { "mcpServers": { "fluxmail": { "command": "npx", "args": [ "-y", "mcp-remote@latest", "http://localhost:8977/mcp", "--allow-http", "--transport", "http-only", "--header", "Authorization:${FLUXMAIL_AUTH_HEADER}" ], "env": { "FLUXMAIL_AUTH_HEADER": "Bearer fmk_..." } } } } ``` Replace `fmk_...` with the API key, then restart Claude Desktop. The bridge requires Node.js and npm on the same computer as Claude Desktop. ### ChatGPT / Codex app [#chatgpt--codex-app] #### Local connection [#local-connection-2] Open Settings > Plugins > MCPs > Add server, then enter: * Name: `Fluxmail` * Type: `STDIO` * Command to launch: `fluxmail` * Arguments: `stdio --profile full` Save the server and restart the app. #### HTTP connection [#http-connection-2] Open Settings > Plugins > MCPs > Add server, then enter: * Name: `Fluxmail` * Type: `Streamable HTTP` * URL: `http://localhost:8977/mcp` * Header name: `Authorization` * Header value: `Bearer fmk_...` Save the server and restart the app. ### Codex CLI [#codex-cli] #### Local connection [#local-connection-3] ```bash codex mcp add fluxmail -- fluxmail stdio --profile full ``` You can also add the server to `~/.codex/config.toml`: ```toml [mcp_servers.fluxmail] command = "fluxmail" args = ["stdio", "--profile", "full"] ``` #### HTTP connection [#http-connection-3] Add the server to `~/.codex/config.toml`: ```toml [mcp_servers.fluxmail] url = "http://localhost:8977/mcp" http_headers = { Authorization = "Bearer fmk_..." } ``` ### Cursor [#cursor] #### Local connection [#local-connection-4] Add the server to `~/.cursor/mcp.json`, or to `.cursor/mcp.json` in a project: ```json { "mcpServers": { "fluxmail": { "command": "fluxmail", "args": ["stdio", "--profile", "full"] } } } ``` #### HTTP connection [#http-connection-4] Add the server to `~/.cursor/mcp.json`, or to `.cursor/mcp.json` in a project: ```json { "mcpServers": { "fluxmail": { "url": "http://localhost:8977/mcp", "headers": { "Authorization": "Bearer fmk_..." } } } } ``` ### Cline [#cline] #### Local connection [#local-connection-5] These commands grant Full access: reading, sending, scheduling, drafts, organization, and moving mail into or out of Trash. Full excludes permanent deletion. Use `read-write` or `read-only` for [restricted access](https://fluxmail.ai/docs/permissions). Open Cline's MCP Servers view, edit its MCP settings, and add this entry under `mcpServers` alongside any existing servers: ```json { "mcpServers": { "fluxmail": { "command": "/absolute/path/to/fluxmail", "args": ["stdio", "--profile", "full"] } } } ``` Replace the command with your Fluxmail executable's absolute path. For Cline CLI, run in an interactive terminal: ```bash cline mcp install fluxmail -- fluxmail stdio --profile full ``` Review and save the configuration in the add-server wizard. #### HTTP connection [#http-connection-5] Create a named key with the [chosen permission profile and mailbox scope](https://fluxmail.ai/docs/connect-an-mcp-client#option-2-connect-over-streamable-http). We recommend `--profile full` for normal MCP use. Open Cline's MCP settings and add this entry under `mcpServers` alongside any existing servers: ```json { "mcpServers": { "fluxmail": { "type": "streamableHttp", "url": "http://localhost:8977/mcp", "headers": { "Authorization": "Bearer fmk_..." } } } } ``` Set `type` to `streamableHttp`; omitting it makes Cline use the legacy SSE transport. Replace the URL with your server's endpoint and enter your Fluxmail API key privately in place of `fmk_...`. For Cline CLI, run `cline mcp` in an interactive terminal, add a server, choose Streamable HTTP, and enter the same URL and Authorization header. ### Hermes [#hermes] #### Local connection [#local-connection-6] Add the server to `~/.hermes/config.yaml`, then run `/reload-mcp`. You can also use the dashboard opened by `hermes dashboard`. ```yaml mcp_servers: fluxmail: command: 'fluxmail' args: ['stdio', '--profile', 'full'] ``` #### HTTP connection [#http-connection-6] Add the server to `~/.hermes/config.yaml`, then run `/reload-mcp`: ```yaml mcp_servers: fluxmail: url: 'http://localhost:8977/mcp' headers: Authorization: 'Bearer fmk_...' ``` ### ChatGPT.com [#chatgptcom] To use Fluxmail from ChatGPT.com without running a server, use [Fluxmail Cloud](https://cloud.fluxmail.ai). Cloud provides a hosted MCP endpoint with OAuth sign-in. Follow the [ChatGPT.com setup guide](https://fluxmail.ai/docs/cloud/mcp#chatgpt-remote-app). Your ChatGPT account needs access to developer mode, and organization policies may require administrator setup. ### Other clients [#other-clients] For stdio, register `fluxmail` as the command and `stdio`, `--profile`, and `full` as its arguments. Add mailbox restrictions with repeated `--account` options. For HTTP, use your server's `/mcp` URL and send `Authorization: Bearer fmk_...`. Clients that cannot supply an authorization header are not compatible with the HTTP endpoint without a suitable bridge. ## Test the connection [#test-the-connection] Reload or restart your client, then check that its discovered tools match your chosen permissions. With read access, ask: ```text Use Fluxmail to list the mailboxes I can access. For my selected mailbox, call list_folders with its accountId. Report whether both calls succeed. Do not read message bodies, send mail, create drafts, or modify messages. ``` The account list checks the connection and mailbox visibility. A successful folder call also checks provider access. If the list is empty, confirm that you connected a mailbox to this instance and that the member and client can access it. For a custom policy without `mail.read`, check tool discovery only. Do not add permissions or send a message just to test the connection. If your client needs a restart, report verification as pending. A [REST check](/docs/build-with-rest#3-verify-provider-access) can verify an existing read-scoped HTTP key, but it does not prove that MCP works. When you want the agent to retrieve email, ask it to list the five latest inbox messages. See [MCP tools](/docs/tools) for available operations and [Troubleshooting](/docs/troubleshooting) for connection failures. ## MCPB bundle permissions [#mcpb-bundle-permissions] The MCPB bundle selects `full` automatically when no permission profile is saved. It grants the Full access described above and cannot permanently delete messages. Scheduled delivery still requires `fluxmail serve` or `fluxmail scheduled run` with the same data directory. A saved profile overrides the bundle default. If you upgrade an installation without a saved profile, it can receive Full access automatically. To retain read-only access, explicitly save `read-only` in the bundle's Permission profile setting before upgrading. Save `read-write` to allow drafts, organization, and Trash without sending or scheduling. ## Limit access [#limit-access] For stdio, put the permission profile and mailbox allowlist in the server arguments. For HTTP, those settings belong to the API key and can be changed without editing client configuration. See [Permissions](/docs/permissions) for custom policies and key updates. ## Local instance settings [#local-instance-settings] Every stdio client launches `fluxmail stdio`. Without `--instance`, Fluxmail selects the active local profile first, then a local profile named `local`, then the sole local profile under any other name. It uses the member session saved for that profile. You do not need to run `fluxmail serve`. Before connecting, run `fluxmail setup` for a new installation. For an existing installation, list profiles with `fluxmail instances list` and log in to the local profile the client will use with `fluxmail --instance login`. Use `local` for the default profile created by setup or when recreating a missing local profile. The MCP client must run as the same operating-system user and use the same Fluxmail data directory as the setup or login command. To pin the client to a particular local profile, add `--instance ` before `stdio` in the client command. You must choose a profile this way if several local profiles exist and none is active or named `local`. An explicit remote profile is rejected; use Streamable HTTP for remote instances. The stdio selection does not change the active profile for other CLI commands. If a desktop client cannot find `fluxmail`, use the absolute executable path returned by `which fluxmail` (`where fluxmail` on Windows). For a project-local installation, use `/absolute/path/to/installation/node_modules/.bin/fluxmail` and keep that installation directory available. For a custom data directory, set `FLUXMAIL_DATA_DIR` in the MCP server's environment to the same absolute path used during setup. In JSON configurations, add `"env": { "FLUXMAIL_DATA_DIR": "/absolute/path/to/data" }` to the server entry. ## Work with messages [#work-with-messages] See [Sending and retries](/docs/sending-and-retries) before enabling sends or forwards. It explains delivery status, retry keys, and previews. Mail tools return typed `structuredContent` and readable text. `get_email` and `get_thread` accept `bodyFormat` to select text, HTML, both, or no body. Large bodies include truncation metadata; use `get_email_body` to read the remaining text. Thread messages are paged. `download_attachment` returns a protected resource link by default. Set `inline` only when the attachment bytes must be embedded in the tool response. Input errors explain which field needs attention. Search syntax errors include `data.diagnostics`. Provider error text is replaced with a safe message. Bulk changes with failed or uncertain messages are marked as MCP tool errors; inspect the per-message results before retrying. --- # Connect Gmail / Google Workspace URL: https://fluxmail.ai/docs/connect-gmail-to-mcp Fluxmail includes a Google Desktop OAuth client, so you can connect Gmail locally without creating Google Cloud credentials. The local flow uses PKCE, and your OAuth tokens stay with the Fluxmail server you run. This setup works with personal Gmail and Google Workspace mailboxes. Fluxmail's built-in app requests Google's `gmail.modify` permission. You can read, draft, send, and organize mail, including moving messages to Trash. Gmail does not allow immediate permanent deletion with this permission. ## Connect Gmail [#connect-gmail] Choose the setup that matches your installation: | Setup | OAuth app | Next step | | -------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------- | | CLI or Docker on the same computer as your browser | Bundled Google app | Connect locally below. | | Public server with a hosted callback | Your Google Web app | [Create the app](#create-oauth-credentials-for-a-hosted-connection), then connect through Docker below. | | CLI over SSH without a hosted callback | Bundled app or your Desktop app | Follow [Browser on a different computer](#browser-on-a-different-computer). | For a fresh local instance, create the first administrator and log in: ```bash fluxmail setup --name "Your name" --email you@example.com ``` ### Local stdio [#local-stdio] Start the browser consent flow: ```bash fluxmail accounts add gmail ``` ### Docker or a remote server [#docker-or-a-remote-server] If Docker runs on the same computer as your browser, leave `FLUXMAIL_PUBLIC_URL` unset. Docker Compose publishes the local callback at `http://127.0.0.1:8976/oauth/callback`. For a remote deployment, expose Fluxmail through a public HTTPS address. You must also [use your own Google OAuth app](#use-your-own-google-oauth-app), because Google requires each hosted callback address to be registered. Add the public address to `.env`: ```dotenv FLUXMAIL_PUBLIC_URL=https://mail.example.com ``` The value must match the public HTTPS address whose callback URI you registered in Google Cloud. Start or recreate the container, then run the same mailbox command inside it: ```bash docker compose up -d docker compose exec fluxmail \ fluxmail setup --name "Your name" --email you@example.com docker compose exec fluxmail \ fluxmail accounts add gmail ``` On local Docker, the command prints a Google consent URL and waits for the callback on `127.0.0.1:8976`. On a remote deployment with `FLUXMAIL_PUBLIC_URL` set, it prints a one-time connection link instead. Open the link in your browser, choose the Google account, and approve access. Hosted links expire after 10 minutes and do not require an admin API key. Fluxmail uses the hosted flow whenever `FLUXMAIL_PUBLIC_URL` is set. The hosted flow cannot use the built-in Google client, which only accepts local callbacks, so it needs your own Web application. Without a public URL, `fluxmail accounts add gmail` uses the local callback at `http://127.0.0.1:8976/oauth/callback`. For troubleshooting, pass `--hosted` or `--local` to choose a flow explicitly. ### Browser on a different computer [#browser-on-a-different-computer] The local callback reaches Fluxmail only when your browser runs on the same computer as the CLI. If you run `fluxmail accounts add gmail` over SSH or on a headless server, open the consent URL in any browser and approve access. The browser then tries to load `http://127.0.0.1:8976/oauth/callback` and shows a connection error. Copy the full URL from its address bar and paste it into the terminal where the command is waiting. Pasting works when you run the command in an interactive terminal, so do not pass `-T` to `docker compose exec`. Fluxmail checks that the URL belongs to the current sign-in attempt and then connects the mailbox. You can also forward the callback port before you run the command, so the redirect reaches the CLI directly: ```bash ssh -L 8976:127.0.0.1:8976 you@server ``` The command stops waiting after 10 minutes. Run it again to get a new consent URL. ## Verify the connection [#verify-the-connection] List the connected mailboxes, then use the Gmail account ID to fetch its folders: ```bash fluxmail accounts list fluxmail --mail-account folders list ``` For Docker, prefix both commands with `docker compose exec fluxmail`. The folder call checks Google access without reading message bodies or changing mail. Continue with [MCP setup](/docs/connect-an-mcp-client) or [REST](/docs/build-with-rest) to verify access through your client as well. ## Use your own Google OAuth app [#use-your-own-google-oauth-app] Use a custom Google client if you prefer to manage the OAuth consent screen yourself. A remote server with `FLUXMAIL_PUBLIC_URL` needs a Web client because Google's Desktop clients only support callbacks on the computer running the CLI. Fluxmail requests the full `https://mail.google.com/` scope when you configure a custom client. This preserves the permanent-delete action. Your Google OAuth app must be approved for that restricted scope before you make it available to other users. ### Create a Google Cloud project [#create-a-google-cloud-project] 1. Open [Google Cloud Console](https://console.cloud.google.com) and create or select a project. 2. Go to **APIs & Services → Library** and enable the **Gmail API**. 3. Open the Google Auth Platform setup and configure the OAuth consent screen. 4. Choose an **External** audience unless the app is restricted to people in your Google Workspace organization. 5. If the app is in Testing, add every Google account that will connect to Fluxmail as a test user. [Google allows up to 100 test users](https://support.google.com/cloud/answer/15549945) while an app has a Testing publishing status. Users see an unverified-app warning during authorization. ### Create OAuth credentials for a local connection [#create-oauth-credentials-for-a-local-connection] Go to **Google Auth Platform → Clients → Create client**, then choose **Desktop app**. Download the OAuth client JSON after Google creates it. Desktop apps cannot keep this credential confidential, but Google's token endpoint still requires the generated client secret. Save both values in encrypted instance settings. Fluxmail prompts for the client secret without displaying it: ```bash fluxmail oauth configure google \ --client-id .apps.googleusercontent.com ``` Fluxmail uses PKCE when it exchanges the local authorization code. ### Create OAuth credentials for a hosted connection [#create-oauth-credentials-for-a-hosted-connection] Go to **Google Auth Platform → Clients → Create client**, then choose **Web application**. Add `/auth/google/callback` as an authorized redirect URI. For example, a server available at `https://mail.example.com` uses: ```text https://mail.example.com/auth/google/callback ``` Copy the client ID and client secret, then configure the running instance: ```bash fluxmail oauth configure google \ --client-id .apps.googleusercontent.com ``` The change takes effect immediately. For Docker, prefix the command with `docker compose exec fluxmail`. In a managed deployment, you can instead set `GOOGLE_CLIENT_ID` with `GOOGLE_CLIENT_SECRET_FILE`; both values must be present, and changing them requires a restart. ### Create a hosted link through the API [#create-a-hosted-link-through-the-api] A product backend can create a hosted connection link without running the CLI. The API key needs `admin.accounts`, and its owner must still be an administrator: ```bash curl -X POST "$FLUXMAIL_PUBLIC_URL/api/v1/admin/connections" \ -H "Authorization: Bearer $FLUXMAIL_ADMIN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"provider":"gmail","ownerMemberId":"you@example.com"}' ``` The response contains `data.connectionUrl` and `data.expiresAt`. Send the URL to the user, but keep the admin API key on your backend. To reconnect an existing mailbox, send `reauthorizeAccountId` instead of `ownerMemberId`. The endpoint also accepts `provider: "outlook"`. ## Avoid seven-day token expiration with a custom app [#avoid-seven-day-token-expiration-with-a-custom-app] For an External app with a Testing publishing status, [Google expires the authorization after seven days](https://developers.google.com/identity/protocols/oauth2#expiration). Move the app to **In production** in Google Auth Platform if you want a longer-lived connection. Personal-use apps with fewer than 100 users do not have to complete Google verification, but Google may continue to show an unverified-app warning. Verification requirements differ if you make the app available more broadly. ## Reconnect Gmail later [#reconnect-gmail-later] If Google revokes or expires the token, list the accounts to find the account ID: ```bash fluxmail accounts list ``` Reconnect a local mailbox: ```bash fluxmail accounts add gmail --reauthorize ``` For Docker or HTTP, run the command inside the container: ```bash docker compose exec fluxmail \ fluxmail accounts add gmail --reauthorize ``` Open the printed link and choose the Google account that matches the mailbox you are reconnecting. Reauthorization updates the stored token for the same mailbox. It does not add another mailbox or change the mailbox owner. ## Connect through a proxy [#connect-through-a-proxy] If your server reaches Google through an HTTP proxy, set `HTTPS_PROXY` before starting Fluxmail. Gmail API and Google sign-in requests will use it. See [Outbound proxy](/docs/configuration#outbound-proxy) for `NO_PROXY` rules and variable precedence. ## How Gmail labels work [#how-gmail-labels-work] Fluxmail also reads Gmail's Send mail as settings with the same permission. Verified aliases can be used for drafts, replies, forwards, immediate sends, and scheduled messages. See [Send from another address](/docs/send-as-addresses) for sender selection rules. Fluxmail returns Gmail user labels in both folder and label listings. The folder listing lets clients navigate a label as a mailbox view. The label listing describes tags that can be added to or removed from messages, including the label colors configured in Gmail. Adding a label by name creates it when it does not exist. Removing a missing label has no effect. Use the dedicated read, star, archive, trash, and move actions for Gmail system labels. Continue with [Connect an MCP client](/docs/connect-an-mcp-client), [Build with REST](/docs/build-with-rest), or [Use the CLI](/docs/use-the-cli). --- # Connect Outlook / Exchange URL: https://fluxmail.ai/docs/connect-outlook-to-mcp Fluxmail connects to Microsoft 365 and Outlook.com through Microsoft Graph. You create the Microsoft Entra app registration, and Fluxmail stores its OAuth tokens on the server you run. This integration supports Exchange Online mailboxes in Microsoft 365 and personal Outlook.com accounts, including Hotmail addresses. For an on-premises Exchange server without Microsoft Graph access, use [IMAP and SMTP](/docs/connect-an-imap-mailbox). With [Fluxmail Cloud](https://fluxmail.ai/docs/cloud/mailboxes#outlook-and-microsoft-accounts), you can connect through Microsoft sign-in without registering your own Entra app. Before registering the app, decide whether you need a local or hosted callback. Local CLI and Docker connections use a public client without a secret. A remote server with a public HTTPS URL uses a Web callback and client secret. The steps below show both paths. ## 1. Register the application [#1-register-the-application] 1. Open the [Microsoft Entra admin center](https://entra.microsoft.com/). 2. Go to **Identity > Applications > App registrations**, then select **New registration**. 3. Enter a name for the app. 4. Choose the supported account types. Select an option that includes personal Microsoft accounts if you need Outlook.com or Hotmail. 5. Register the application, then copy its **Application (client) ID**. The default `MICROSOFT_TENANT_ID=common` accepts work, school, and personal accounts when the app registration supports them. For a single-tenant app, set `MICROSOFT_TENANT_ID` to its Directory (tenant) ID or verified tenant domain. ## 2. Add Microsoft Graph permissions [#2-add-microsoft-graph-permissions] Open **API permissions** for the app registration and add these delegated Microsoft Graph permissions: * `User.Read` * `Mail.ReadWrite` * `Mail.Send` * `MailboxSettings.Read` Fluxmail also requests standard OpenID Connect and offline access scopes during sign-in so it can identify the mailbox and refresh access tokens. An Entra administrator may need to grant consent when organizational policy blocks user consent. ## 3. Choose a callback [#3-choose-a-callback] Add the redirect URI for each way you plan to run Fluxmail. One app registration can contain both local and hosted callbacks. | Setup | Platform | Redirect URI | | --------------------------- | ------------------------------- | ---------------------------------------------------- | | Local stdio or local Docker | Mobile and desktop applications | `http://localhost:8976/oauth/microsoft/callback` | | Remote server | Web | `/auth/microsoft/callback` | For the local callback, open **Authentication**, add the Mobile and desktop applications platform with the custom redirect URI, and enable **Allow public client flows**. For a remote server, add the Web platform and its public HTTPS callback. For example, a server at `https://mail.example.com` uses: ```text https://mail.example.com/auth/microsoft/callback ``` Create a client secret under **Certificates & secrets** for hosted connections. Copy the secret value when Entra displays it. Fluxmail does not need a client secret for the local callback. ## 4. Connect the mailbox [#4-connect-the-mailbox] For a fresh local instance, create the first administrator and log in: ```bash fluxmail setup --name "Your name" --email you@example.com ``` ### Local stdio [#local-stdio] Configure a public OAuth client, then start the browser consent flow: ```bash fluxmail oauth configure outlook \ --client-id \ --public-client fluxmail accounts add outlook ``` If the app is restricted to one tenant, include it when configuring the client: ```bash fluxmail oauth configure outlook \ --client-id \ --tenant-id \ --public-client ``` Fluxmail listens on `http://localhost:8976`, prints a Microsoft authorization URL, and waits for the redirect. Choose the mailbox you want to connect and approve access. If your browser runs on a different computer, such as when you use the CLI over SSH, the redirect to `localhost` fails to load after you approve access. Copy the full URL from the browser's address bar and paste it into the waiting terminal. Pasting needs an interactive terminal. You can also forward the port first with `ssh -L 8976:127.0.0.1:8976 you@server`. The command stops waiting after 10 minutes. ### Local Docker [#local-docker] Add the client ID to `.env` and leave `FLUXMAIL_PUBLIC_URL` unset: ```dotenv MICROSOFT_CLIENT_ID= # MICROSOFT_TENANT_ID=common ``` Start Fluxmail and run the mailbox command inside the container: ```bash docker compose up -d docker compose exec fluxmail \ fluxmail setup --name "Your name" --email you@example.com docker compose exec fluxmail \ fluxmail accounts add outlook ``` Docker Compose publishes the callback listener to `localhost:8976` on the host, so the browser can return to the waiting command. ### Remote server [#remote-server] Set the public server URL in the Docker environment, then configure the OAuth application through the running instance: ```dotenv FLUXMAIL_PUBLIC_URL=https://mail.example.com ``` ```bash docker compose up -d docker compose exec fluxmail \ fluxmail oauth configure outlook \ --client-id \ --tenant-id common ``` Fluxmail prompts for the client secret and stores the complete application encrypted in SQLite. The change takes effect immediately. Managed deployments can use `MICROSOFT_CLIENT_ID`, `MICROSOFT_TENANT_ID`, and `MICROSOFT_CLIENT_SECRET_FILE` instead. Start the mailbox command: ```bash docker compose exec fluxmail \ fluxmail accounts add outlook ``` Open the printed connection link in your browser, continue to Microsoft, and approve access. The link expires after 10 minutes and works once. ## 5. Verify the connection [#5-verify-the-connection] List the connected mailboxes, then use the Outlook account ID to fetch its folders: ```bash fluxmail accounts list fluxmail --mail-account folders list ``` For Docker, prefix both commands with `docker compose exec fluxmail`. The folder call checks Microsoft access without reading message bodies or changing mail. Continue with [MCP setup](/docs/connect-an-mcp-client) or [REST](/docs/build-with-rest) to verify access through your client as well. ## Create hosted connection links through the API [#create-hosted-connection-links-through-the-api] A product backend can create a hosted link without running the CLI. The API key needs `admin.accounts`, and its owner must still be an administrator: ```bash curl -X POST "$FLUXMAIL_PUBLIC_URL/api/v1/admin/connections" \ -H "Authorization: Bearer $FLUXMAIL_ADMIN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"provider":"outlook","ownerMemberId":"you@example.com"}' ``` The response contains `data.connectionUrl` and `data.expiresAt`. Send the URL to the user, but keep the admin API key on your backend. To reconnect an existing mailbox, send `reauthorizeAccountId` instead of `ownerMemberId`. The endpoint also accepts `provider: "gmail"`. ## Reconnect Outlook later [#reconnect-outlook-later] List accounts to find the account ID: ```bash fluxmail accounts list ``` Reconnect the mailbox with the same flow used during setup: ```bash fluxmail accounts add outlook --reauthorize ``` For Docker, prefix the command with `docker compose exec fluxmail`. Choose the Microsoft account that matches the mailbox you are reconnecting. Reauthorization updates the stored tokens without changing the mailbox owner or access rules. Accounts connected before category support can keep reading and sending mail without reconnecting. Listing Outlook categories requires `MailboxSettings.Read`. If Fluxmail reports that this permission is missing, reauthorize the account after adding it to the Entra app registration. ## How Outlook categories work [#how-outlook-categories-work] Mailbox aliases can be registered in Fluxmail and selected when sending. The alias must already belong to the mailbox in Microsoft 365 or Outlook.com. Fluxmail does not create aliases or grant delegated mailbox access. See [Send from another address](/docs/send-as-addresses). Fluxmail exposes Outlook mail folders as folders and Outlook master categories as labels. Message label lists contain category names. Adding or removing a label updates the message's categories without replacing its other categories. If a category name is not in the master list, Outlook adds the name to the message without assigning a color. It does not appear in label listings. Continue with [Connect an MCP client](/docs/connect-an-mcp-client), [Build with REST](/docs/build-with-rest), or [Use the CLI](/docs/use-the-cli). --- # Deploy with Docker URL: https://fluxmail.ai/docs/deploy-with-docker Use Docker when clients connect over a network or share one Fluxmail instance. The [Fluxmail image](https://github.com/fluxmailai/fluxmail/pkgs/container/fluxmail) supports amd64 and arm64. For remote access without maintaining a server or configuring HTTPS, use [Fluxmail Cloud](https://fluxmail.ai/docs/cloud/quickstart). You'll need Docker with Compose. For remote access, also prepare a domain pointing to your server and an HTTPS reverse proxy. If your agent should guide the setup, use the [agent-first prompt](/docs/quickstart#agent-first-setup) and tell it you want Docker. ## 1. Download the server files [#1-download-the-server-files] ```bash mkdir fluxmail && cd fluxmail curl -fsSLO https://raw.githubusercontent.com/fluxmailai/fluxmail/main/docker-compose.yml curl -fsSL https://raw.githubusercontent.com/fluxmailai/fluxmail/main/.env.example -o .env ``` Review both files before starting. The Compose service stores its database, configuration, and generated encryption key in the `fluxmail-data` volume mounted at `/data`. Keep that volume when recreating the container. See [Back up and restore](/docs/backup-and-restore) before replacing storage. The downloaded file uses the `latest` image. For controlled upgrades, replace that tag with the release tag or image digest you intend to run and record it with your backups. If your existing Compose file uses `ghcr.io/churichard/fluxmail`, change the image name to `ghcr.io/fluxmailai/fluxmail` and keep your current tag or digest. Published release images are available at the new location. Keep the existing volume and configuration, then run `docker compose pull` and `docker compose up -d` when you are ready to restart. Future releases use the new image name. ## 2. Choose local or remote access [#2-choose-local-or-remote-access] ### Docker on your computer [#docker-on-your-computer] Leave `FLUXMAIL_PUBLIC_URL` unset when the browser and Docker run on the same computer. The local OAuth callback uses port 8976. For access only from this computer, edit the existing HTTP port mapping in `docker-compose.yml` to bind it to loopback: ```yaml ports: - '127.0.0.1:8977:8977' - '127.0.0.1:8976:8976' ``` ### Docker on a remote server [#docker-on-a-remote-server] Set the public HTTPS URL in `.env`: ```dotenv FLUXMAIL_PUBLIC_URL=https://mail.example.com ``` Forward HTTPS requests to Fluxmail on port 8977. The following example uses [Caddy installed on the Docker host](https://caddyserver.com/docs/quick-starts/reverse-proxy). Point your domain's DNS records at that host and allow public traffic to Caddy on ports 80 and 443. Use the loopback port mappings above so clients cannot bypass the proxy. Add this site to the host's Caddyfile and reload Caddy: ```text mail.example.com { reverse_proxy 127.0.0.1:8977 } ``` Caddy obtains and renews the HTTPS certificate for the domain. This example assumes Caddy runs on the host; inside a separate container, `127.0.0.1` would refer to that container. If the proxy reaches Fluxmail from a non-loopback address, set `FLUXMAIL_TRUST_PROXY=1` in `.env`. Docker networking can make the host proxy appear this way. Enable this only when the proxy overwrites forwarded headers and direct access to Fluxmail is blocked. See [remote authentication](/docs/authentication-and-instances#log-in-to-a-remote-instance). Hosted OAuth requires a Google Web app or a Microsoft Entra Web callback, depending on the provider. Configure those in step 4. ## 3. Start the server and create an administrator [#3-start-the-server-and-create-an-administrator] If you are reusing an existing data volume, [review pending schedules](/docs/sending-and-retries#before-restarting-an-existing-instance) before starting the service. Startup can send overdue mail, including mail outside a new client's read-only scope. ```bash docker compose up -d docker compose exec fluxmail \ fluxmail setup --name "Your name" --email you@example.com docker compose exec fluxmail fluxmail status ``` Enter the password at the terminal prompt. Run setup only for a new instance. For an existing instance, [log in](/docs/authentication-and-instances) instead. If startup fails, inspect the container before continuing: ```bash docker compose ps docker compose logs --tail=100 fluxmail ``` ## 4. Connect a mailbox [#4-connect-a-mailbox] Follow the provider guide for your deployment: | Provider | Setup | | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | [Gmail / Google Workspace](/docs/connect-gmail-to-mcp#docker-or-a-remote-server) | Local Docker can use the bundled Google app. A public callback requires your own Google Web app. | | [Microsoft 365 / Outlook.com](/docs/connect-outlook-to-mcp) | Register an Entra app. Local connections use a public client; hosted connections need a client secret. | | [IMAP/SMTP](/docs/connect-an-imap-mailbox) | Use your provider's server settings and enter the password privately. | Run configuration and mailbox commands inside the container with `docker compose exec fluxmail`. For example, after configuring Google OAuth for your deployment: ```bash docker compose exec fluxmail fluxmail accounts add gmail ``` Open the URL printed by the command and complete provider consent. Hosted connection links expire after 10 minutes. If your browser and server are on different computers without a hosted callback, follow the provider guide's SSH or callback-paste instructions. After connecting, find the mailbox ID and verify its folders: ```bash docker compose exec fluxmail fluxmail accounts list docker compose exec fluxmail \ fluxmail --mail-account folders list ``` A successful folder listing confirms provider access without changing mail. ## 5. Create a client key [#5-create-a-client-key] We recommend Full access for normal MCP use. It allows reading, sending, scheduling, drafts, organization, and moving mail into or out of Trash. It excludes permanent deletion. Choose `read-write` or `read-only` for [restricted access](/docs/permissions). Creating a key without permission options still grants read-only access. This example grants Full access to one mailbox: ```bash docker compose exec fluxmail \ fluxmail apikey create --name my-agent \ --profile full --account ``` Fluxmail shows the key once. Save it in the client's secret store or private configuration. Use a separate key for each client so it can be revoked independently. Connect an [MCP client](/docs/connect-an-mcp-client#option-2-connect-over-streamable-http) to `https://mail.example.com/mcp`, or use [REST](/docs/build-with-rest) at `https://mail.example.com/api/v1`. For local Docker, use `http://localhost:8977` as the base URL. Docker already runs the HTTP server; do not start a second `fluxmail serve` process. Verify through the client as well as inside the container. A container-only check does not test your public URL, proxy, or client key. ## Keep the server running [#keep-the-server-running] The Compose service restarts unless you explicitly stop it. Its existing `serve` process delivers scheduled mail after clients disconnect; no additional worker is needed. Queued mail remains in the data volume, overdue mail may send on startup, and retry delays survive restarts. The shipped Compose file sets `stop_grace_period: 45s`. Keep that allowance when customizing it. Other supervisors should also allow at least 45 seconds: Fluxmail stops accepting requests and new deliveries, then waits up to 30 seconds for active work before closing providers and storage. Before updating the image, follow [Upgrade Fluxmail](/docs/upgrade-fluxmail). Set up [backups](/docs/backup-and-restore) and use [Local logs](/docs/logging) or [Troubleshooting](/docs/troubleshooting) when a connection fails. --- # Email search URL: https://fluxmail.ai/docs/email-search Fluxmail has one portable search syntax for Gmail, Outlook, and IMAP mailboxes. You can use it with `fluxmail emails search`, `fluxmail emails search-batch`, the `search_emails` and `search_emails_batch` MCP tools, or the REST search operations. ```text from:ann@example.com in:archive is:unread after:2026-07-01 quarterly report ``` Search terms use implicit AND. Fluxmail does not interpret `AND`, `OR`, or parentheses as boolean expressions. ## Filters [#filters] | Syntax | Meaning | | ------------------------------------- | ---------------------------------- | | `from:value` | Sender | | `to:value` | Recipient | | `subject:value` | Subject | | `in:role` | Portable folder role | | `is:read` or `is:unread` | Read state | | `is:starred` or `is:unstarred` | Starred state | | `has:attachment` or `-has:attachment` | Non-inline attachment state | | `after:YYYY-MM-DD` | Received on or after this UTC date | | `before:YYYY-MM-DD` | Received before this UTC date | Portable folder roles are `inbox`, `sent`, `drafts`, `archive`, `spam`, `trash`, and `all`. Custom folders are account specific. Use the structured `folder` filter after looking up the folder with `list_folders` or the REST folders endpoint. Dates use the message's received or provider internal time. `after` is inclusive and `before` is exclusive. Both values must be calendar dates, and `after` must be earlier than `before`. ## Quotes and literal text [#quotes-and-literal-text] Double quotes group spaces inside a value: ```text subject:"quarterly forecast" from:"Ann Example " ``` Inside quotes, escape `"` as `\"` and `\` as `\\`. Free text is always literal. A search for `"from:ann@example.com"` looks for that text instead of activating a sender filter. URLs, times, unrelated values containing a colon, `AND`, `OR`, and parentheses also remain text. Fluxmail may return a warning when a term looks like a mistyped operator. For example, `form:ann@example.com` remains literal text and produces a suggestion for `from:`. Quote the term when you intended it as text and do not want the warning. ## Provider-native search [#provider-native-search] Use `rawProviderQuery` when you need Gmail search syntax or Outlook KQL. Native queries are not portable and must target one compatible account. They are not part of the typed search string. Structured `text` is literal and cannot be combined with `rawProviderQuery`. Other structured filters combine with a native query using AND. IMAP supports Gmail native syntax only when the server advertises `X-GM-EXT-1`. Account capabilities report whether native syntax and portable folder roles are available, unavailable, or still unknown. Fluxmail rejects filters and native queries that the selected account reports as unavailable. Capabilities marked `unknown` are passed to the provider so it can discover support when the request runs. ## Attachments [#attachments] Fluxmail treats a message as having an attachment when its hydrated metadata contains at least one part whose disposition is not `inline`. This definition is the same across providers. Gmail's `has:attachment` operator has different behavior, so Fluxmail does not use it for portable attachment searches. Gmail may need to inspect several provider pages before it fills a result page, especially when searching for messages without attachments. ## Pagination [#pagination] Pass `nextPageToken` back with the same account, query, page size, snippet setting, and search context setting. Search page tokens expire after one hour. They are signed to prevent changes, but their contents are not encrypted. Replacing the Fluxmail instance encryption key also invalidates existing tokens. Every search page includes `exhausted`. A value of `true` means Fluxmail searched the full requested scope. When you omit the folder, that scope is all mail except Spam and Trash. An IMAP server's `\All` mailbox can define its own scope. Some filters require local checks after Fluxmail receives provider candidates. A response can include: ```json { "meta": { "nextPageToken": "...", "exhausted": false, "incomplete": true, "incompleteReason": "scan_limit", "inspectedCandidates": 1000 } } ``` An empty page confirms that there are no matches only when `exhausted` is `true`. Continue with `nextPageToken` when `incompleteReason` is `scan_limit` or `time_limit`. A provider can also return `provider_limit` when it cannot search beyond its own result cap. Search work has a 10-second soft budget and a 15-second deadline. Fluxmail returns a continuation at a safe boundary when it can. If the provider stalls before Fluxmail has a continuation point, the request fails with `provider_unavailable` and `reason: "search_timeout"`. ## Message previews [#message-previews] Set `includeSnippet` to `true` to request previews or `false` to suppress them. If you omit it, Gmail and Outlook return their native previews while IMAP avoids extra body downloads. For IMAP, Fluxmail downloads up to 16 KiB from the preferred text part and returns at most 300 characters. It prefers plain text and converts HTML when needed. A preview failure leaves the message metadata available and adds a warning to the page. The `capabilities.snippets` field tells you whether a provider includes previews without fetching message bodies. A value of `false` does not prevent you from requesting a preview with `includeSnippet`. ## Search context [#search-context] Set `includeSearchContext` to `true` to include a body excerpt around the search text. This option requires literal text from the typed query or the structured `text` field. Fluxmail rejects filter-only and provider-native searches that request context. Search context is separate from `includeSnippet`. A message can contain both. Fluxmail prefers the complete search phrase, then uses the earliest matching term when the phrase does not appear in the body. Matching is case insensitive and treats punctuation as literal text. Each message returns one of these values: | Status | Meaning | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | `matched` | `excerpt` contains the matching line, cropped to 300 Unicode characters when needed. | | `no_literal_match` | Fluxmail inspected the complete selected body but did not find the literal text. The provider may have matched headers, stemming, or other indexed content. | | `scan_limit` | Fluxmail reached the 256 KiB decoded body scan limit before finding a literal match. | | `unavailable` | Fluxmail could not read a suitable body or the optional body request failed. | Fluxmail reads at most 256 KiB of decoded body content for each result. It prefers plain text and converts HTML to readable text when no plain-text body exists. Attachments and attached messages are excluded. Gmail and Outlook may transfer the complete body because their APIs do not support the same bounded partial read as IMAP. Search context is off by default because it can add one body request per accepted result. On IMAP, Fluxmail uses a partial, non-marking body read. When an IMAP request asks for both a snippet and search context, Fluxmail derives both from the same download. An optional enrichment failure leaves the message metadata available, returns `unavailable`, and adds a warning to the page. ## Search several accounts [#search-several-accounts] Use `search_emails_batch`, `POST /api/v1/messages/search`, or `fluxmail emails search-batch` to run the same portable search against several accounts. A batch accepts 1 through 20 distinct accounts and searches up to three at a time. Each account has its own page and continuation token. The response keeps account groups in request order. One account can fail without discarding successful groups. The aggregate `exhausted` value is `true` only when every group is exhausted. To continue, send only the unfinished accounts with their tokens. Batch search accepts portable folder roles and rejects provider-native queries. --- # Local logs URL: https://fluxmail.ai/docs/logging Fluxmail keeps a local record of command, MCP, REST, mailbox connection, scheduled send, and license failures. It also records a small number of service events, such as server startup. Successful requests and tool calls are not logged. Logs stay on the machine where Fluxmail runs. Fluxmail does not upload them or include their text in anonymous telemetry. ## Read recent logs [#read-recent-logs] Show the latest 100 entries: ```bash fluxmail logs ``` Choose a different limit or show only errors: ```bash fluxmail logs --tail 250 fluxmail logs --level error ``` Use `--json` to print the stored JSON record for each entry: ```bash fluxmail logs --level warn --json ``` For Docker, run the same command inside the container: ```bash docker compose exec fluxmail fluxmail logs --tail 100 ``` ## Files and disk limits [#files-and-disk-limits] The active file is `/logs/fluxmail.jsonl`. Fluxmail rotates it at 5 MiB and keeps three older files. The entire directory is limited to 20 MiB. Fluxmail batches writes, limits repeated errors, and caps sustained log output at 1 MiB per hour after a 64 KiB burst. When it drops repeated or excessive records, it writes a `logging.records_suppressed` entry after capacity becomes available. If the file cannot be written, email operations continue and Fluxmail reports the problem on the console at most once per hour. The supplied Docker Compose file also limits container console logs to three 5 MiB files. ## Configure logging [#configure-logging] `FLUXMAIL_LOG_LEVEL` accepts `info`, `warn`, `error`, or `off`. The default is `info`. `FLUXMAIL_LOG_DESTINATION` accepts `both`, `file`, or `console`. The default is `both`. One shot CLI commands still show errors in the terminal without printing a duplicate log line. For example, keep errors in the rotating file without writing structured events to the console: ```toml [logging] level = "error" destination = "file" ``` Environment variables take precedence over `config.toml`. Restart Fluxmail after changing either setting. ## Private information [#private-information] Fluxmail does not log request bodies, response bodies, email content, headers, command arguments, credentials, configuration values, or raw provider responses. It also redacts common token and secret formats from error strings. Error messages and stack traces can still contain email addresses, local file paths, or details returned by a provider. Review log entries before sharing them with anyone. --- # Fluxmail Self-Hosted URL: https://fluxmail.ai/docs/self-hosted > **Prefer a hosted setup?** Fluxmail Cloud gives your agents and apps access to email without running your own server. [Get started with Cloud](https://fluxmail.ai/docs/cloud/quickstart). Fluxmail connects Gmail, Microsoft 365, Outlook.com, and IMAP/SMTP mailboxes to your agents and apps. Run it on your computer or server, then use MCP, REST, or the CLI to work with email. ## Start here [#start-here] | What you want to do | Where to start | | -------------------------------------------- | ------------------------------------------------------------------------------------------------------ | | Have a coding agent set up Fluxmail | [Agent-first setup](/docs/quickstart#agent-first-setup) | | Connect a mailbox and use it locally | [Local quickstart](/docs/quickstart#manual-setup) | | Run a server for remote or shared access | [Deploy with Docker](/docs/deploy-with-docker) | | Connect a client to an existing installation | [MCP clients](/docs/connect-an-mcp-client), [REST](/docs/build-with-rest), or [CLI](/docs/use-the-cli) | ## What you can do [#what-you-can-do] Search and read messages or complete threads, download attachments, and work across several mailboxes. You can draft, reply, forward, send, and schedule email. Organization actions include marking mail as read, starring, archiving, moving between folders, and using Gmail labels or Outlook categories. MCP, REST, and CLI use the same mailbox operations and provider integrations. Each client can have its own permissions and mailbox scope. Business and Enterprise plans also support members with their own mailbox access. See [Permissions](/docs/permissions) and [Teams and plans](/docs/teams-and-plans). ## Choose where to run Fluxmail [#choose-where-to-run-fluxmail] | Setup | Use it for | Client connection | | ----------------- | ---------------------------------------------------- | -------------------------------------------- | | Local process | An agent on the same computer | MCP over stdio; the client launches Fluxmail | | Local HTTP server | Apps, scripts, or MCP clients that connect by URL | REST or MCP over Streamable HTTP | | Docker server | Remote access or several clients sharing an instance | REST or MCP over Streamable HTTP | A local MCP client uses your saved member session. HTTP MCP clients use scoped API keys. The CLI can manage local and remote instances. [Authentication and instances](/docs/authentication-and-instances) explains login and instance selection. ## Connect your email provider [#connect-your-email-provider] | Provider | What you need | | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | [Gmail / Google Workspace](/docs/connect-gmail-to-mcp) | Local connections can use Fluxmail's bundled Google OAuth app. Hosted callbacks require your own Google Web app. | | [Microsoft 365 / Outlook.com](/docs/connect-outlook-to-mcp) | Your own Microsoft Entra app registration. | | [IMAP/SMTP](/docs/connect-an-imap-mailbox) | Your provider's server settings and password or app password. | A *mailbox* is a connected email address. Commands and API fields call it an *account*, as in `fluxmail accounts list` and `accountId`. A *member* is a person who signs in to Fluxmail. An *instance* is the Fluxmail installation those members and mailboxes belong to. ## Where your data goes [#where-your-data-goes] Fluxmail keeps its SQLite database and encrypted provider credentials on the machine where you run it. It does not copy email content to a service operated by Fluxmail. Your MCP client may send retrieved email to its model provider, depending on the client and its settings. See [Architecture](/docs/architecture) for request flow and storage, [Configuration](/docs/configuration#telemetry) for usage telemetry, and [Back up and restore](/docs/backup-and-restore) before moving or upgrading an installation. --- # Permissions URL: https://fluxmail.ai/docs/permissions Fluxmail can limit the email actions available to each MCP or REST connection. Give a research client read-only access, or let an inbox organizer manage messages without granting send or permanent-delete access. Permissions control which MCP tools Fluxmail exposes and which REST routes or message actions a key can call. Mailbox scope is separate from permissions. The member and optional mailbox allowlist decide which mailboxes a connection can reach. The permission profile decides what it can do with those mailboxes. Fluxmail applies both checks to every connection. ## Choose a permission profile [#choose-a-permission-profile] | Profile | What it allows | Capabilities | | ------------ | --------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | | `read-only` | Read and search mail, inspect folders, labels, and scheduled sends, and download attachments. | `mail.read` | | `read-write` | Read mail, manage drafts, organize messages, and move messages to or from Trash. | `mail.read`, `mail.drafts`, `mail.organize`, `mail.trash` | | `full` | Use every Fluxmail email capability except permanent deletion, including sending mail. | `mail.read`, `mail.drafts`, `mail.organize`, `mail.trash`, `mail.send` | Fluxmail uses `read-only` when you do not choose a profile. Choose a broader profile or a [custom policy](#build-a-custom-policy) for clients that draft, organize, or send mail. No profile allows permanent deletion. To let a client permanently delete messages, add `mail.delete` to its profile: ```bash fluxmail stdio --profile full --allow mail.delete ``` ## Limit a local stdio connection [#limit-a-local-stdio-connection] Pass a profile when your MCP client launches Fluxmail: ```bash fluxmail stdio --profile read-only ``` For a client config file, put the profile in the argument list: ```json { "mcpServers": { "fluxmail": { "command": "fluxmail", "args": [ "stdio", "--profile", "read-only" ] } } } ``` ## Limit an HTTP connection [#limit-an-http-connection] HTTP permissions belong to the API key. Each key also belongs to a member. Create a separate key for each MCP or REST client so you can change or revoke one connection without affecting the others. ```bash fluxmail apikey create \ --name research-agent \ --profile read-only fluxmail apikey create \ --name inbox-agent \ --profile read-write ``` The key is shown once. `fluxmail apikey list` shows each key ID and permission profile without revealing the secret. Change an existing key by its ID: ```bash fluxmail apikey permissions --profile read-only ``` Keys created without permission options use `read-only`. Existing keys keep the profile they were created with. HTTP MCP requests always require an API key. REST accepts either a member session or an API key, except for its public login, enrollment, reset redemption, discovery, and health routes. ## Administrative capabilities [#administrative-capabilities] Administrative access is separate from mail access: | Capability | What it allows | | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `admin.accounts` | Connect and reauthorize mailboxes, test IMAP and SMTP settings, update IMAP folder mappings, and configure Outlook or IMAP sender addresses. | | `admin.members` | Invite, suspend, activate, promote, demote, and remove members. It also permits session revocation. | | `admin.api_keys` | Create, update, list, and revoke API keys. | | `admin.license` | Read, activate, and deactivate the instance license. | | `admin.audit` | Read security audit events. | Add administrative capabilities to a named mail profile with repeated `--admin` options: ```bash fluxmail apikey create \ --name account-operator \ --profile read-only \ --admin admin.accounts ``` When changing an existing key, `--admin` keeps its current named mail profile and replaces its administrative capabilities. A custom policy has no separate administrative list, so pass every allowed capability with `--allow` instead. For a custom policy, put both mail and administrative capabilities in repeated `--allow` options. Fluxmail rejects administrative capabilities for non-admin members. It also checks the owner's current role and mailbox grants on every request. Treat `admin.api_keys` as sensitive authority. Administrator sessions remain the recovery path if an administrative key is revoked or narrowed. ## Build a custom policy [#build-a-custom-policy] Use repeated `--allow` options when the named profiles are too broad. Combine them with `--profile` to add capabilities to a profile; the result is saved as a custom policy. List the available capabilities first: ```bash fluxmail apikey capabilities ``` | Capability | Actions | | --------------- | ------------------------------------------------------------------------------------------------------------------------------- | | `mail.read` | List, search, and read mail; inspect status, folders, labels, and sender addresses; list scheduled sends; download attachments. | | `mail.drafts` | Create, update, and delete drafts; cancel scheduled sends. | | `mail.organize` | Mark read or unread, star, archive, move, and manage labels or Outlook categories. | | `mail.trash` | Move messages to or from Trash. | | `mail.delete` | Permanently delete messages. | | `mail.send` | Send or schedule messages. | The generic `move` action cannot target Trash or Archive by folder ID, role, or display name. It also cannot move messages out of Trash. Use `trash` to move messages into Trash, `untrash` to restore them, and `archive` to move non-Trash messages into Archive. These restrictions keep Trash access behind the `mail.trash` capability. Create a custom HTTP key like this: ```bash fluxmail apikey create \ --name drafting-agent \ --allow mail.read \ --allow mail.drafts ``` The same options work with stdio: ```bash fluxmail stdio \ --allow mail.read \ --allow mail.organize ``` Some workflows need more than one capability. Reply drafts need `mail.drafts` and `mail.read`; replies need `mail.send` and `mail.read`; forwarding also needs `mail.send` and `mail.read`. Draft lookup needs `mail.drafts`. Send preview and delivery status need `mail.send`; previewing an existing draft also needs `mail.drafts`, and previewing a reply needs `mail.read`. Body continuation and attachment resources need `mail.read`. The same mailbox access rules apply to these operations. --- # Quickstart URL: https://fluxmail.ai/docs/quickstart Set up Fluxmail on the computer where your agent runs. You'll need Node.js 20.20.x, or Node.js 22.22 or newer, and a mailbox you can authorize. For a remote or shared server, start with [Deploy with Docker](/docs/deploy-with-docker). ## Agent-first setup [#agent-first-setup] Paste this prompt into your coding agent from the project where you want to use Fluxmail. The agent will inspect your setup, help you choose access, configure your client, and verify the connection. You'll enter passwords and complete provider consent yourself. ```text Set up Fluxmail Self-Hosted for this project. Read https://fluxmail.ai/docs/self-hosted/setup.txt and follow the setup guide. Ask me where I want to run it, which mailboxes to connect, and what the agent should be allowed to do. Configure my client and verify the connection without reading message bodies or changing mail. Guide me through password entry and provider consent. ``` The [agent setup instructions](https://fluxmail.ai/docs/self-hosted/setup.txt) cover local and Docker installations. Agents can read the [self-hosted documentation as plain text](https://fluxmail.ai/docs/self-hosted/llms.txt). ## Manual setup [#manual-setup] ### 1. Install Fluxmail [#1-install-fluxmail] ```bash npm install -g fluxmail ``` To run without a global installation, replace `fluxmail` in local commands with `npx -y fluxmail@latest`. ### 2. Create your administrator [#2-create-your-administrator] For a new installation, run: ```bash fluxmail setup --name "Your name" --email you@example.com ``` Enter your password at the private terminal prompt. This creates a local instance profile and saves a member session for up to 90 days. For an existing installation, use [login](/docs/authentication-and-instances#log-in-to-an-existing-local-instance) instead of setup. ### 3. Connect one mailbox [#3-connect-one-mailbox] Choose your provider. Complete only its steps. #### Gmail or Google Workspace [#gmail-or-google-workspace] ```bash fluxmail accounts add gmail ``` Open the consent URL, choose your Google account, and approve access. Local connections use Fluxmail's bundled Google OAuth app. See the [Gmail guide](/docs/connect-gmail-to-mcp) if you need your own app or your browser runs on a different computer. #### Microsoft 365 or Outlook.com [#microsoft-365-or-outlookcom] First [register your Microsoft Entra app](/docs/connect-outlook-to-mcp). For a local connection, configure the public client and authorize your mailbox: ```bash fluxmail oauth configure outlook \ --client-id \ --public-client fluxmail accounts add outlook ``` #### IMAP and SMTP [#imap-and-smtp] Use your provider's server names. Fluxmail prompts for the password without displaying it: ```bash fluxmail accounts add imap \ --email you@example.com \ --imap-host imap.example.com \ --smtp-host smtp.example.com ``` See the [IMAP guide](/docs/connect-an-imap-mailbox) for app passwords and provider settings. ### 4. Check the mailbox [#4-check-the-mailbox] ```bash fluxmail status fluxmail accounts list ``` Your mailbox should appear in the account list. Use its account ID to check that Fluxmail can reach the provider: ```bash fluxmail --mail-account folders list ``` A folder listing verifies provider access without reading message bodies or changing mail. If a command fails, use [Troubleshooting](/docs/troubleshooting). ### 5. Connect your agent [#5-connect-your-agent] We recommend Full access for normal MCP use. It allows reading, sending, scheduling, drafts, organization, and moving mail into or out of Trash. It excludes permanent deletion. Choose `read-write` or `read-only` for [restricted access](/docs/permissions). Bare stdio and API-key creation without permission options remain read-only. Stdio can create schedules but does not deliver them. To deliver scheduled mail, keep `fluxmail serve` or `fluxmail scheduled run` running with the same data directory. If you reused an existing installation, [review pending schedules](/docs/sending-and-retries#before-restarting-an-existing-instance) before starting either worker; overdue sends may resume even with a read-only client. For Claude Code: ```bash claude mcp add fluxmail -- fluxmail stdio --profile full ``` For other clients, follow [Connect an MCP client](/docs/connect-an-mcp-client). Add `--account ` to the stdio arguments to limit the client to one mailbox. Your client starts Fluxmail itself; you do not need to run `fluxmail serve` for stdio. Reload your client, then ask: ```text Use Fluxmail to list my connected mailboxes, then list the folders for my selected mailbox. Report whether both calls succeeded. Do not read message bodies, send mail, create drafts, or change messages. ``` A successful folder call from the agent verifies the MCP connection and provider access. A successful CLI check alone does not verify MCP. ### 6. Try your first email task [#6-try-your-first-email-task] When you're ready to let the agent retrieve email, ask: ```text Show the five most recent messages in my inbox, with sender and subject. Do not change any messages. ``` You can also list inbox messages directly: ```bash fluxmail --mail-account emails list --folder inbox --page-size 5 ``` For an app or script, continue with [Build with REST](/docs/build-with-rest). For more terminal workflows, see [Use the CLI](/docs/use-the-cli). ## If your client cannot find Fluxmail [#if-your-client-cannot-find-fluxmail] Some desktop apps start with a limited `PATH`. Run `which fluxmail` (`where fluxmail` on Windows) and use the returned absolute path in the client's configuration. The client must run as the same operating-system user and use the same data directory as setup. See [local instance settings](/docs/connect-an-mcp-client#local-instance-settings) for custom paths and multiple instances. --- # Send from another address URL: https://fluxmail.ai/docs/send-as-addresses Fluxmail can send from another address that belongs to the connected mailbox. The provider must already know and allow the address. Fluxmail does not create or verify aliases. ## Provider setup [#provider-setup] Gmail aliases come from Gmail's Send mail as settings. Fluxmail lists the primary address and verified aliases, including each identity's display name and Reply-To address. Add or verify an alias in Gmail before using it through Fluxmail. Outlook and IMAP aliases are configured in Fluxmail after an administrator creates them with the mail provider. Add an existing alias with: ```bash fluxmail accounts send-as add sales@example.com --name "Sales" ``` Remove a configured alias with: ```bash fluxmail accounts send-as remove sales@example.com ``` These commands change Fluxmail's allowed sender list. They do not change the mailbox or provider account. Microsoft 365, Outlook.com, and SMTP servers can still reject an address that the provider has not assigned to the mailbox. List the addresses available for an account: ```bash fluxmail accounts send-as list ``` You can also use the `list_send_as` MCP tool or `GET /api/v1/accounts/{accountId}/send-as`. Listing requires `mail.read`. Replacing the configured Outlook or IMAP list through REST requires `admin.accounts`: ```http PUT /api/v1/accounts/acct_123/send-as Content-Type: application/json { "identities": [ { "email": "sales@example.com", "name": "Sales" } ] } ``` The `PUT` request replaces the full configured alias list for that account. Gmail aliases remain managed by Gmail. ## Choose a sender [#choose-a-sender] Pass `from` through MCP or REST. In the CLI, use `--from` with send, draft, or forward commands: ```bash fluxmail emails send \ --from sales@example.com \ --to customer@example.com \ --subject "Order update" \ --body "Your order has shipped." ``` The sender address must match an available identity. Matching ignores letter case, but it does not remove dots or plus tags. Fluxmail rejects unknown and unverified addresses before delivery. New messages and forwards use the connected account address when `from` is omitted. Replies look for an owned address in the original To field, then Cc. The first match becomes the sender. If no address matches, Fluxmail uses the connected account address. A reply to a message sent from one of your own aliases reuses that alias. Reply-all removes every known identity for the account from the recipient list. An address that appears only in Bcc does not affect automatic sender selection. ## Drafts and scheduled messages [#drafts-and-scheduled-messages] A draft keeps its sender when you update it without `from`. To change the sender, update the draft first. Sending a draft by ID does not accept `from` or other message fields. Scheduled messages store the sender in the provider draft. Fluxmail checks an alternate sender again before delivery. If an administrator removes the alias before the send time, the schedule fails instead of switching to the primary address. --- # Sending and retries URL: https://fluxmail.ai/docs/sending-and-retries Sending requires `mail.send`. Choose the mailbox, recipients, and message before submitting a send. You can inspect a saved draft or preview a request first. Previewing does not deliver email. ## Preview the message [#preview-the-message] Use MCP `preview_send`, CLI `emails preview`, or REST `/accounts//send/preview` to resolve the sender, reply recipients, subject, and attachment metadata. To inspect an existing draft, use `get_draft`, `drafts get`, or `GET /accounts//drafts/`. See [Send from another address](/docs/send-as-addresses) if you want to use an existing mailbox alias. Fluxmail does not create the alias at your provider. ## Give each delivery a stable key [#give-each-delivery-a-stable-key] Create an idempotency key for each intended send or forward, and save it with the request before calling Fluxmail: | Interface | Where to pass the key | | --------- | -------------------------------------------------------- | | MCP | `idempotencyKey` on `send_email` or `forward_email` | | REST | `Idempotency-Key` request header | | CLI | `--idempotency-key` on `emails send` or `emails forward` | Reuse the same key when retrying the same request. New delivery-operation keys have no automatic expiry and are scoped to the authenticated credential. Reusing a key with different request data returns a conflict. See the [0.11.0 migration guide](/docs/upgrades/0.11.0) for legacy REST records with a 24-hour lifetime. Do not switch credentials or create a new key to retry a request whose outcome you have not established. ## Check the delivery operation [#check-the-delivery-operation] A send returns an `operationId` and a status. Save the returned ID; do not assume it is the same as your idempotency key. | Status | What to do | | ----------- | ---------------------------------------------------------------------------------------------------------- | | `queued` | Wait for the scheduled delivery. | | `sending` | Check the operation again. | | `succeeded` | Delivery completed; the result includes the sent message ID. | | `failed` | Inspect the failure before deciding what to do next. | | `uncertain` | Check the Sent folder or recipient before making any new send request. The provider may have delivered it. | Use MCP `get_delivery_operation`, CLI `emails delivery-status`, or REST `GET /accounts//delivery-operations/` to check the result. Fluxmail does not automatically retry an uncertain delivery under the same key. MCP marks failed and uncertain sends as tool errors, but the structured result still includes the operation ID and status. Read that result before retrying. If a request times out before you receive its result, retry the same request with the same credential and key to recover the saved operation. ## Schedule a message [#schedule-a-message] Use the sending interface's `sendAt` field or CLI scheduling option. Fluxmail saves the scheduled message as a draft in the mailbox. `fluxmail serve` or `fluxmail scheduled run` must be running against the same store for delivery. Stdio connections never start a delivery worker. Queued mail stays stored while the worker is stopped; overdue mail may send when it starts again. Retry delays survive worker restarts. Review pending schedules before restoring a backup or restarting an instance after a long outage. Use the [MCP tools](/docs/tools), [CLI guide](/docs/use-the-cli), or [REST reference](/docs/rest-api) to list and cancel scheduled sends. ## Keep scheduled delivery running [#keep-scheduled-delivery-running] For a stdio-only installation, run a persistent worker on the computer that stores the schedules: ```bash FLUXMAIL_DATA_DIR=/path/to/your/fluxmail-data fluxmail scheduled run ``` Use the same `FLUXMAIL_DATA_DIR` as the stdio clients. The runner uses local deployment configuration independently of the active CLI profile and needs no CLI login session. An explicit `--instance` must name an existing local profile. Omit `--mail-account`: the runner processes all mailboxes in the instance. The worker runs in the foreground. Keep it running with your process supervisor and allow at least 45 seconds for shutdown. SIGINT, SIGTERM, and SIGHUP stop new delivery and wait up to 30 seconds for active work. A second signal forces termination. For remote HTTP installations, schedules live on the server and `serve` continues delivery after clients disconnect. Docker's existing `serve` process handles delivery; no extra worker is needed. The standalone runner reads storage on its own host, which can be a VPS. It cannot consume another server's queue over HTTP. Workers may share one SQLite store on the same host. Do not share the store over a network filesystem. Claims reduce conflicting work, but cannot guarantee exactly-once delivery by an external mail provider. If a delivery outcome is uncertain, check Sent before sending again. ## Before restarting an existing instance [#before-restarting-an-existing-instance] Starting `fluxmail serve`, `fluxmail scheduled run`, or the Docker service starts the instance-wide scheduler. Overdue scheduled messages can send immediately. A client's read-only profile and mailbox restrictions apply to its tool calls; the worker processes the whole instance. Starting `fluxmail stdio` leaves schedules queued. Before restarting an instance, inspect pending schedules with a one-shot local CLI command for each mailbox you can access: ```bash fluxmail --instance --mail-account scheduled list ``` For a stopped Docker installation, use a one-shot container with the existing data volume: ```bash docker compose run --rm --no-deps -T fluxmail \ --instance local --mail-account scheduled list ``` These commands do not start the scheduler. If your saved session has expired, log in with a one-shot local command before listing schedules. Ask the instance operator to review mailboxes your member cannot access. Resume the instance only when you intend its pending deliveries to run. A connection test does not require canceling or changing those schedules. ## Preserve paragraph formatting [#preserve-paragraph-formatting] For plain-text email, keep each prose paragraph on one continuous line and separate paragraphs with blank lines. This applies to MCP `bodyText`, REST `body.text`, and a forward's `comment`. Fluxmail preserves line breaks, so fixed-width wrapping appears as short lines in the recipient's mail app. Lists and signatures can use intentional line breaks. See [Send email](/docs/tools/send-email) for MCP inputs or [the REST send endpoint](/docs/rest-api/send-message) for request fields. --- # Teams & plans URL: https://fluxmail.ai/docs/teams-and-plans ## Members and mailbox access [#members-and-mailbox-access] Every Fluxmail instance has at least one **member**. A personal instance uses one member to identify its owner. Business and Enterprise instances can add more people and decide which mailboxes each person can reach. ```bash # A fresh instance starts with one logged-in administrator fluxmail setup --name "Ada Lovelace" --email ada@example.com # Administrators invite more people fluxmail members add --name "Grace Hopper" --email grace@example.com fluxmail members list # Members connect mailboxes they own fluxmail accounts add gmail # Reassign an existing mailbox fluxmail accounts assign --owner grace@example.com # Choose who else can reach it fluxmail accounts access --owner-only fluxmail accounts access --shared fluxmail accounts access --share-with ada@example.com ``` `fluxmail members add` prints an enrollment code once. Send it to the new member through a private channel. They add the instance and set their password with `fluxmail login --instance --server --enroll`. `--owner-only` makes a mailbox private to its owner. `--shared` makes it available to every active member, including members added later. Repeat `--share-with` to give selected members access. The administrator role permits member, license, key, and mailbox metadata management. It does not grant access to another member's private mail. Stdio uses the member logged in to the selected local instance. You can limit a connection to selected mailboxes that member can already reach: ```bash # Local connection for the logged-in member, limited to one mailbox fluxmail stdio --account # HTTP connection for the logged-in member, limited to one mailbox and read-only actions fluxmail apikey create \ --name "ada laptop" \ --account \ --profile read-only ``` Update an HTTP key's mailbox allowlist without replacing the key: ```bash fluxmail apikey accounts --account fluxmail apikey accounts --all-accounts ``` Member and mailbox scope control which mailboxes a connection can reach. Its [permission profile](/docs/permissions) separately controls which email actions the client can take. Use one key per client so you can change its scope, change its permissions, or revoke it without interrupting other connections. ## Plans and licensing [#plans-and-licensing] Self-hosting is free on the **Personal** plan: 3 connected mailboxes and 1 member. Pro raises the mailbox limit for one person. Each member included in your Business plan raises the mailbox limit by 20. The limit applies to the instance, so one person can connect every allotted mailbox. You choose which members can access each mailbox. Contact us about Enterprise if you need more than 50 members. See [pricing](/pricing) for current limits. You can buy Pro or Business from the pricing page. Stripe returns you to Fluxmail after payment and shows your license key. Copy it then, and keep it private. Use **Manage subscription** on the pricing page or license screen to update your card, view invoices, change plans or your member limit, or cancel. Stripe asks for the email used at checkout and sends a one-time passcode before opening billing details. Stripe billing emails also include the same portal link. Unlock a paid plan with your license key: ```bash fluxmail license activate fluxmail license status ``` Fluxmail prompts for the key without displaying it. For automation, use `fluxmail license activate --key-file /absolute/path/to/license`, or pass `-` to read from stdin. An administrative REST client can read the same status from `GET /api/v1/admin/license`, activate a key with `POST /api/v1/admin/license/activate`, and deactivate it with `DELETE /api/v1/admin/license`. An API key needs `admin.license`; an administrator's member session can call the routes directly. The status response never includes the configured license key. REST cannot replace or remove a key supplied through `FLUXMAIL_LICENSE_KEY`. One license activates one instance, and enforcement keeps working offline. If you schedule a cancellation, the paid plan works until the end of the billing period. After the subscription ends or a payment fails, the instance drops back to Personal limits. Deactivating, downgrading, or lapsing never deletes mailboxes or data. Lowering the member limit takes effect at the end of the billing period. If the instance then has more mailboxes or members than the new limits allow, Fluxmail keeps working for 7 days and warns administrators in the CLI, `fluxmail license status`, and MCP tool results. You can't add mailboxes or members during that time. Remove the extras or increase your member limit before the date in the warning. After that, email tools stop working until usage fits the plan. The CLI keeps working so you can remove mailboxes or members. ## Software license [#software-license] Fluxmail is source available under the [Elastic License 2.0](https://github.com/fluxmailai/fluxmail/blob/main/LICENSE.md). You may use, modify, create derivative works, and redistribute it subject to that license. A fork does not need a paid Fluxmail subscription merely because it is a fork. Without a valid paid key, Fluxmail uses the Personal plan with 3 mailboxes and 1 member. Official Pro, Business, and Enterprise entitlements require a valid Fluxmail license key. ELv2 does not allow you to change or circumvent license key functionality or remove functionality protected by a key. It also does not allow you to provide Fluxmail to third parties as a hosted or managed service that exposes a substantial set of its features. The software license does not grant rights to Fluxmail names or logos beyond applicable law. Their use is subject to the [Fluxmail Terms of Service](https://fluxmail.ai/terms). --- # Telemetry URL: https://fluxmail.ai/docs/telemetry Fluxmail sends anonymous operation events to its PostHog project by default. Events record the CLI command, MCP tool, or REST operation, plus the outcome, duration, selected feature modes, a random installation ID, and basic runtime information. Each event is labeled `deployment_type=self_hosted` so package usage can be counted separately from Fluxmail Cloud and website traffic. Internal, provider, timeout, and uncertain-send failures also send a grouped error report with the operation name and a safe error code. MCP and REST reports include partial account or item failures. Reports exclude the original error message, stack trace, and provider response. Turning telemetry off also disables these reports. For MCP attachment downloads, telemetry records whether the tool returned a resource link or inline content. It records the same choice if the download fails, without sending the attachment name or content. For `fluxmail stdio`, telemetry records which startup phase failed, or `ready` when the server starts. The phases cover permission options, local instance selection, configuration and database initialization, session authentication, mailbox selection, and MCP transport startup. No option values or error messages are sent. Recognized startup failures also record a fixed reason, such as an unconfigured instance, ambiguous local profiles, an unreadable or invalid profile or credentials file, or a missing or invalid session. File-read failures include an allowlisted filesystem error code. Stdio events record whether the data directory came from the environment or the default and whether instance selection was explicit or automatic. They do not include the directory, instance name, session token, file contents, or error text. Delivery status, send preview, draft retrieval, body continuation, and bulk actions use the same event format. Fluxmail does not send delivery IDs, message IDs, recipients, or message content in these events. When the MCP server starts, telemetry records the plan and how many mailboxes and members the installation has. The plan is sent as Personal, Pro, Team, Business, or Enterprise, and any other plan name is sent as `other`. It does not send the license key or any address. After Fluxmail connects or removes a mailbox, telemetry records its provider and the installation's mailbox totals. OAuth connection events also record whether the callback used your public URL or the local port, and whether Google used Fluxmail's built-in application or one you registered. Local connections record whether the redirect reached Fluxmail directly, you pasted the callback URL, or the command timed out. The pasted URL is never sent. Connection events report whether they replaced credentials for an existing mailbox. Fluxmail never sends command arguments, email or mailbox data, identifiers, search text, file paths, credentials, configuration values, request payloads, provider responses, stack traces, or error text. PostHog person profiles and GeoIP lookup are disabled. For batch search, telemetry records the surface operation and marks the outcome as an error when any account group fails. It does not include account IDs, queries, page tokens, or group errors. Turn telemetry off for the installation: ```bash fluxmail telemetry disable ``` You can also set `FLUXMAIL_TELEMETRY=0` or `DO_NOT_TRACK=1`. Any disabling source takes priority over an enabling source. Use `fluxmail telemetry status` to check the effective state. --- # Troubleshooting URL: https://fluxmail.ai/docs/troubleshooting Start by checking the service and connected mailboxes: ```bash fluxmail status fluxmail accounts list ``` Show recent warnings and errors with: ```bash fluxmail logs --level warn ``` For Docker, prefix each command with `docker compose exec fluxmail`. ## The fluxmail command is not found [#the-fluxmail-command-is-not-found] Check whether your shell can find the command: ```bash which fluxmail ``` If that prints nothing, install Fluxmail globally or run it through `npx`: ```bash npm install -g fluxmail npx -y fluxmail@latest status ``` Some apps use a limited `PATH`. Run `which fluxmail` in your terminal and use the returned absolute path in the app's configuration. ## The browser cannot finish connecting a mailbox [#the-browser-cannot-finish-connecting-a-mailbox] Local OAuth connections listen for the browser redirect on port 8976 of the computer running the CLI. If your browser runs on another computer, the page fails to load after you approve access. Copy the full URL from the address bar and paste it into the terminal where the command is waiting, or forward the port with `ssh -L 8976:127.0.0.1:8976 you@server`. Pasting needs an interactive terminal. If another program is using port 8976 and you run the command in one, Fluxmail asks you to paste the URL instead. When Docker Compose is using the port, run the command inside the container with `docker compose exec fluxmail fluxmail accounts add gmail` or `outlook` so the mailbox is saved there. The command stops waiting after 10 minutes. If it times out, run it again to get a new authorization URL. A remote server needs `FLUXMAIL_PUBLIC_URL` set to its public HTTPS address. Gmail also needs a Google Web client, and Outlook needs a Microsoft Entra client secret. Follow [Deploy with Docker](/docs/deploy-with-docker) and the setup guide for [Gmail](/docs/connect-gmail-to-mcp) or [Outlook](/docs/connect-outlook-to-mcp). ## A mailbox needs to be reconnected [#a-mailbox-needs-to-be-reconnected] Run `fluxmail status` to confirm which mailbox needs attention. Then follow the reconnection steps for [Gmail](/docs/connect-gmail-to-mcp), [Outlook](/docs/connect-outlook-to-mcp), or [IMAP/SMTP](/docs/connect-an-imap-mailbox). Reconnecting updates the saved credentials without changing the mailbox owner or access rules. ## MCP or REST returns 401 [#mcp-or-rest-returns-401] HTTP clients must send the API key as a bearer token: ```text Authorization: Bearer fmk_... ``` Fluxmail shows an API key only when you create it. If the key was lost or revoked, create a new one and update the client. ## MCP or REST returns 403 [#mcp-or-rest-returns-403] The API key does not have permission for the requested operation or mailbox. Check its permission profile and mailbox allowlist: ```bash fluxmail apikey list ``` See [Permissions](/docs/permissions) to change the profile or mailbox scope. ## A Docker server does not respond [#a-docker-server-does-not-respond] Check the container status and recent logs: ```bash docker compose ps docker compose logs --tail=100 fluxmail docker compose exec fluxmail fluxmail logs --level warn ``` Confirm that port 8977 is reachable and that your reverse proxy forwards requests to it. See [Deploy with Docker](/docs/deploy-with-docker) for the expected public URL and authentication settings. ## A configuration import fails [#a-configuration-import-fails] `fluxmail config migrate` preserves the source file whether the command succeeds or fails. Read the error before changing any files. A key mismatch means the configured key differs from `/encryption.key` or cannot decrypt the existing database. Restore the key that was used with the database, then retry the command. Do not replace the key just to clear the error. Provider credentials and encrypted instance settings cannot be decrypted with a different key. If `config.toml` already exists, move it aside only when the env file should replace its deployment settings. After a successful import, run `fluxmail config show` and `fluxmail oauth status` before removing the old file. ## An OAuth application cannot be changed [#an-oauth-application-cannot-be-changed] Run `fluxmail oauth status` and check the source. An application with an `environment` or `environment-file` source is controlled by deployment overrides. Remove the complete provider override group, restart Fluxmail, then run `fluxmail oauth configure` or `fluxmail oauth reset` again. --- # Upgrade Fluxmail URL: https://fluxmail.ai/docs/upgrade-fluxmail Before upgrading, check the release notes and the version-specific [upgrade guides](/docs/upgrades/0.11.0). Apply every relevant migration guide between your current version and the target version. Clients may need updates before the server, especially when response formats change. ## 1. Record the current installation [#1-record-the-current-installation] Record your installed package version or Docker image digest, deployment configuration, and data paths. Choose the target release explicitly so you can reproduce the upgrade. Check for pending scheduled sends and plan the interruption. Sends missed during downtime can run when the server starts again. ## 2. Back up before changing versions [#2-back-up-before-changing-versions] Stop all processes sharing the data directory and [back up the complete installation](/docs/backup-and-restore). Include the matching encryption key and external secrets. Keep the backup outside the data volume you are upgrading. A database migration can make the store unreadable by an older release. Downgrading the executable or image alone may not restore the previous service. ## 3. Install the target release [#3-install-the-target-release] For a global installation, replace `` with the release you selected: ```bash npm install -g fluxmail@ ``` For Docker, set the selected release tag or digest in the Compose `image` field, then pull and recreate the service: ```bash docker compose pull fluxmail docker compose up -d fluxmail ``` Keep the existing data volume mounted. For local stdio, restart each MCP client so it launches the updated executable. For a local HTTP installation, restart the server. Stdio connections started without `--profile` or `--allow` are now read-only. If a client drafts, organizes, or sends mail, add the [permission profile](/docs/permissions) it needs to its arguments before restarting it. New API keys default to `read-only`. Existing keys keep their profiles, but keys using `full` lose permanent deletion as described below. Custom policies keep their explicit capability grants. The `full` profile no longer includes permanent deletion. This applies to existing keys and stdio clients that use `full`. If a client needs to permanently delete messages, add `--allow mail.delete` to its `--profile full` options. For an API key, run `fluxmail apikey permissions --profile full --allow mail.delete`. Scheduled delivery now belongs to `serve` or `scheduled run`. Stdio-only installations must start a persistent worker using the same data directory as their MCP clients. See [Keep scheduled delivery running](/docs/sending-and-retries#keep-scheduled-delivery-running). Remote HTTP and standard Docker installations already run the worker through `serve`. This change migrates the SQLite store to format 6 to persist retry deadlines. Stop every process sharing the store before the first upgraded process opens it. Existing schedules and delivery records are retained. Existing retry delays cannot be reconstructed, so due schedules may be eligible immediately; subsequent retry delays survive restarts. Queued mail remains stored, and overdue mail may send when a worker starts. Rollback requires the matching pre-upgrade backup. ## 4. Verify the upgrade [#4-verify-the-upgrade] ```bash fluxmail status fluxmail accounts list fluxmail --mail-account folders list ``` For Docker, prefix each command with `docker compose exec fluxmail`. Then check your MCP or REST client using its own credentials. Verify that the selected mailboxes and permissions still match the client's intended access. Do not send a test email just to check connectivity. Keep the backup until these checks pass. If startup fails, inspect [Local logs](/docs/logging) and the upgrade guide for your target release. ## If you need to roll back [#if-you-need-to-roll-back] Stop the new version, preserve its current data for diagnosis, and [restore the complete pre-upgrade backup](/docs/backup-and-restore) with the matching older release. Do not point an older binary at a migrated store. A restore loses local changes since the backup. It does not undo mail already sent or changed at the provider. Review delivery and scheduling state before resuming work to avoid repeating an action. --- # Use the CLI URL: https://fluxmail.ai/docs/use-the-cli The Fluxmail CLI can read, draft, send, schedule, and organize email. It also configures and runs the service. Mail commands call the same authenticated REST operations for local and remote instances, so permissions and mailbox access rules stay the same across CLI, MCP, and REST. Complete the [Quickstart](/docs/quickstart) before using the workflows below. ## Check the instance [#check-the-instance] ```bash fluxmail status fluxmail accounts list fluxmail members list ``` `fluxmail status` reports provider availability, connected mailboxes, and mailboxes that need to be reauthorized. ## Choose a mailbox [#choose-a-mailbox] Mail commands use the only accessible mailbox when there is exactly one. If you can access several mailboxes, pass the global account option with an account ID or email address: ```bash fluxmail --mail-account you@example.com emails list --folder inbox fluxmail -a labels list ``` Fluxmail returns an error when it cannot choose one mailbox safely. ## Read and search email [#read-and-search-email] List inbox messages, search across mail, or fetch a complete message or thread: ```bash fluxmail emails list --folder inbox --read false --page-size 20 fluxmail emails search "from:ann@example.com is:unread quarterly report" --include-search-context true fluxmail emails search-batch "subject:invoice is:unread" --account --account fluxmail emails get fluxmail threads get fluxmail emails list --all --max-results 1000 ``` The search string uses Fluxmail's [portable search syntax](/docs/email-search). Add `--include-snippet true` to request IMAP previews, or pass `false` to suppress previews. Add `--include-search-context true` to include an excerpt around literal search text. List responses include `meta.nextPageToken` when another page is available. Pass it back with `--page-token` and the same query, page size, snippet setting, and search context setting. Check `meta.exhausted` before treating an empty page as a confirmed negative result. Use `--all` on `emails list` or `emails search` to follow every page. It stops after 1,000 messages by default. Set `--max-results` to another limit up to 10,000. Set the global `--timeout ` option when a slow mailbox needs more than the default 30 seconds per request. `emails search-batch` accepts 1 through 20 repeated `--account` options. It prints every account group and exits nonzero if any group fails. Use `--input ` to send an exact batch request with per-account continuation tokens. Folders are navigable mailbox locations. Labels are Gmail user labels or Outlook categories: ```bash fluxmail folders list fluxmail labels list ``` Gmail user labels appear in both listings because Gmail uses them as mailbox views and message tags. IMAP mailboxes support folders but not labels. ## Draft, send, and forward [#draft-send-and-forward] Read [Sending and retries](/docs/sending-and-retries) before submitting a delivery. Keep the same idempotency key when retrying the same request. Build a message with flags: ```bash fluxmail drafts create \ --to ann@example.com \ --subject "Quarterly report" \ --body-file report.txt \ --attach report.pdf fluxmail drafts get fluxmail emails send \ --to ann@example.com \ --subject "Quarterly report" \ --body "The report is attached." \ --attach report.pdf \ --idempotency-key quarterly-report-2026-09 ``` Use `--html` or `--html-file` for an HTML body. Repeat `--to`, `--cc`, `--bcc`, and `--attach` as needed. If standard input is redirected and no body option is present, Fluxmail uses standard input as the plain-text body. For plain-text email, keep each prose paragraph on one continuous line in `--body`, a body file, or standard input. Use a blank line between paragraphs. Fluxmail preserves line breaks, including those in lists and signatures. Reply, send an existing draft, schedule delivery, or forward a message: ```bash fluxmail emails preview --reply-to --reply-all --body "Thanks, everyone." fluxmail emails send --reply-to --reply-all --body "Thanks, everyone." --idempotency-key reply-2026-09 fluxmail emails send --draft --idempotency-key draft-2026-09 fluxmail emails send --to ann@example.com --body "Later" --send-at 2026-10-01T12:00:00Z --idempotency-key later-2026-09 fluxmail emails forward --to lee@example.com --no-attachments --idempotency-key forward-2026-09 fluxmail emails delivery-status ``` Every send and forward needs an idempotency key that you choose. Save the key with the request and reuse it if the command times out or you need to check the result. The response contains an `operationId`. Use `emails delivery-status` to inspect it. If the status is `uncertain`, inspect the recipient mailbox or sent folder before sending again. Reusing the key never starts a second delivery. ## Organize messages [#organize-messages] Apply one action to one or more message IDs: ```bash fluxmail emails modify mark-read fluxmail emails modify archive fluxmail emails modify move --folder Projects fluxmail emails modify add-labels --label Customer ``` The available actions are `mark-read`, `mark-unread`, `star`, `unstar`, `archive`, `trash`, `untrash`, `delete`, `move`, `add-labels`, and `remove-labels`. Label actions work with Gmail labels and Outlook categories. A modify request accepts up to 100 distinct message IDs. Its result lists `succeededIds`, `failed` entries with safe error codes, and `uncertainIds`. Check uncertain messages before retrying. Other IDs continue processing when one fails. List or cancel scheduled sends: ```bash fluxmail scheduled list fluxmail scheduled cancel ``` ## Download attachments [#download-attachments] Choose the destination path explicitly: ```bash fluxmail attachments download --output ./report.pdf ``` Fluxmail will not replace an existing file unless you pass `--force`. Attachment IDs are opaque, so pass them exactly as returned. The command prints JSON metadata after it writes the attachment. ## Send exact REST JSON [#send-exact-rest-json] Draft, send, forward, and modify commands accept an exact REST request body from a file or standard input: ```bash fluxmail emails send --input request.json --idempotency-key request-2026-09 fluxmail emails modify --input - < request.json ``` `--input` cannot be combined with flags that build the same request body. Send and forward commands still accept `--idempotency-key` with JSON input. ## Script output and exit codes [#script-output-and-exit-codes] The default output is a JSON envelope with `data`, plus `meta` and `warnings` when present. Mail, account list, and root status commands return their API data in `data`. Other management commands wrap their displayed lines in `data`; interactive setup and connection flows still print prompts directly. Use the root `--format table` option for a compact display or `--format ndjson` for one record per line. Errors in JSON and NDJSON mode go to stderr as JSON. The exit code is `0` for success, `2` for invalid input, `3` for partial or uncertain results, `4` for access errors, `5` for provider or network errors, and `1` for internal or uncategorized errors. Scripts should inspect the response as well as the exit code. ## Run the HTTP server [#run-the-http-server] ```bash fluxmail serve ``` The server listens on port 8977 by default. It provides MCP at `/mcp` and REST at `/api/v1`. For a local MCP client that uses stdio, the client launches this command instead: ```bash fluxmail stdio ``` See [Connect an MCP client](/docs/connect-an-mcp-client) for client configuration and transport options. ## Manage mailboxes and members [#manage-mailboxes-and-members] Connect another mailbox or list the existing mailboxes: ```bash fluxmail accounts add gmail fluxmail accounts list ``` Administrators can invite members and share mailboxes with them: ```bash fluxmail members add --name "Another person" --email person@example.com fluxmail accounts access --share-with person@example.com ``` See [Teams and plans](/docs/teams-and-plans) for mailbox sharing and plan limits. ## Manage API keys [#manage-api-keys] Create a key for an HTTP MCP or REST client: ```bash fluxmail apikey create --name local-client ``` Fluxmail shows the key once. You can list, change, or revoke keys without exposing their stored secrets: ```bash fluxmail apikey list fluxmail apikey permissions --profile read-only fluxmail apikey revoke ``` See [Permissions](/docs/permissions) for profiles, custom capabilities, and mailbox restrictions. ## Use the CLI with Docker [#use-the-cli-with-docker] Prefix commands with `docker compose exec fluxmail`: ```bash docker compose exec fluxmail fluxmail status docker compose exec fluxmail fluxmail accounts list ``` See [Deploy with Docker](/docs/deploy-with-docker) for remote server setup. ## Command reference [#command-reference] Run `fluxmail --help` or add `--help` to a command for terminal help: ```bash fluxmail accounts add --help fluxmail emails send --help ``` The [CLI reference](/docs/cli) lists every command and option. ## Update Fluxmail [#update-fluxmail] Follow [Upgrade Fluxmail](/docs/upgrade-fluxmail) to check compatibility and back up the instance before installing a new release. Fluxmail checks npm for a newer stable release at most once every 24 hours when you run an interactive CLI command. The check runs in the background. If it finds a newer release, a later command prints an update notice to stderr. Registry and cache errors do not affect the command. Update a global installation: ```bash npm install -g fluxmail@latest ``` `npx -y fluxmail@latest` already downloads the current stable release. If you use an exact version with `npx`, change the version in the command when you are ready to update. For Docker, pull the current image and recreate the service: ```bash docker compose pull fluxmail docker compose up -d ``` Fluxmail does not show update notices for MCP stdio, redirected output, CI, npm scripts, or `npx` runs. Skip the check for one command with the global option: ```bash fluxmail --no-update-notifier status ``` Set `NO_UPDATE_NOTIFIER=1` in your shell or container environment to turn off update checks. This variable controls only CLI update checks and is not part of Fluxmail configuration. --- # fluxmail accounts access URL: https://fluxmail.ai/docs/cli/accounts-access `fluxmail accounts access` Set who can access a mailbox ## Usage [#usage] ```bash fluxmail accounts access [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ----------- | -------- | ------- | ------- | | `accountId` | Yes | None | None | ## Options [#options] | Option | Required | Details | Default | | ----------------------- | -------- | ---------------------------------------------------------- | ------- | | `--owner-only` | No | Only the owner can access the mailbox | None | | `--shared` | No | Share the mailbox with every member | None | | `--share-with ` | No | Replace selected access with this member; repeat as needed | None | --- # fluxmail accounts add URL: https://fluxmail.ai/docs/cli/accounts-add `fluxmail accounts add` Connect a Gmail, Outlook, or IMAP account ## Usage [#usage] ```bash fluxmail accounts add [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ---------- | -------- | --------------------------------------- | ------- | | `provider` | Yes | Email provider: gmail, outlook, or imap | None | ## Options [#options] | Option | Required | Details | Default | | ---------------------------- | -------- | ------------------------------------------------------------ | ---------- | | `--reauthorize ` | No | Reconnect an existing account | None | | `--local` | No | Use the local browser callback for OAuth | None | | `--hosted` | No | Use FLUXMAIL\_PUBLIC\_URL for the OAuth callback | None | | `--email
` | No | Mailbox address (required for IMAP) | None | | `--display-name ` | No | Sender name for IMAP messages | None | | `--imap-host ` | No | IMAP server hostname | None | | `--imap-port ` | No | IMAP server port | `993` | | `--imap-security ` | No | IMAP security: tls or starttls | `tls` | | `--imap-user ` | No | IMAP username; defaults to the mailbox address | None | | `--imap-password-env ` | No | Read the IMAP password from this environment variable | None | | `--smtp-host ` | No | SMTP server hostname | None | | `--smtp-port ` | No | SMTP server port | `587` | | `--smtp-security ` | No | SMTP security: tls or starttls | `starttls` | | `--smtp-user ` | No | SMTP username; defaults to the IMAP username | None | | `--smtp-password-env ` | No | Read a separate SMTP password from this environment variable | None | | `--sent-folder ` | No | Sent mailbox path | None | | `--drafts-folder ` | No | Drafts mailbox path | None | | `--trash-folder ` | No | Trash mailbox path | None | | `--archive-folder ` | No | Archive mailbox path | None | | `--spam-folder ` | No | Spam mailbox path | None | | `--no-save-sent` | No | Do not append SMTP submissions to the Sent folder | None | --- # fluxmail accounts assign URL: https://fluxmail.ai/docs/cli/accounts-assign `fluxmail accounts assign` Change mailbox ownership ## Usage [#usage] ```bash fluxmail accounts assign [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ----------- | -------- | ------- | ------- | | `accountId` | Yes | None | None | ## Options [#options] | Option | Required | Details | Default | | ------------------ | -------- | ------------------------------------- | ------- | | `--owner ` | Yes | Member id or email to own the mailbox | None | --- # fluxmail accounts configure URL: https://fluxmail.ai/docs/cli/accounts-configure `fluxmail accounts configure` Set special folder paths for an IMAP account ## Usage [#usage] ```bash fluxmail accounts configure [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ----------- | -------- | ------- | ------- | | `accountId` | Yes | None | None | ## Options [#options] | Option | Required | Details | Default | | ------------------------- | -------- | ------------------------------------------- | ------- | | `--sent-folder ` | No | Sent path, or auto to clear the override | None | | `--drafts-folder ` | No | Drafts path, or auto to clear the override | None | | `--trash-folder ` | No | Trash path, or auto to clear the override | None | | `--archive-folder ` | No | Archive path, or auto to clear the override | None | | `--spam-folder ` | No | Spam path, or auto to clear the override | None | --- # fluxmail accounts list URL: https://fluxmail.ai/docs/cli/accounts-list `fluxmail accounts list` List connected accounts ## Usage [#usage] ```bash fluxmail accounts list ``` ## Options [#options] This command has no command-specific options. --- # fluxmail accounts remove URL: https://fluxmail.ai/docs/cli/accounts-remove `fluxmail accounts remove` Disconnect an account and delete its stored tokens ## Usage [#usage] ```bash fluxmail accounts remove ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ----------- | -------- | ------- | ------- | | `accountId` | Yes | None | None | ## Options [#options] This command has no command-specific options. --- # fluxmail accounts send-as add URL: https://fluxmail.ai/docs/cli/accounts-send-as-add `fluxmail accounts send-as add` Add a configured Outlook or IMAP sender address ## Usage [#usage] ```bash fluxmail accounts send-as add [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ------------ | -------- | ----------------------- | ------- | | `account-id` | Yes | Email account ID | None | | `email` | Yes | Existing provider alias | None | ## Options [#options] | Option | Required | Details | Default | | --------------- | -------- | ------------------- | ------- | | `--name ` | No | Sender display name | None | --- # fluxmail accounts send-as list URL: https://fluxmail.ai/docs/cli/accounts-send-as-list `fluxmail accounts send-as list` List available sender addresses ## Usage [#usage] ```bash fluxmail accounts send-as list ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ------------ | -------- | ---------------- | ------- | | `account-id` | Yes | Email account ID | None | ## Options [#options] This command has no command-specific options. --- # fluxmail accounts send-as remove URL: https://fluxmail.ai/docs/cli/accounts-send-as-remove `fluxmail accounts send-as remove` Remove a configured Outlook or IMAP sender address ## Usage [#usage] ```bash fluxmail accounts send-as remove ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ------------ | -------- | ------------------------- | ------- | | `account-id` | Yes | Email account ID | None | | `email` | Yes | Configured sender address | None | ## Options [#options] This command has no command-specific options. --- # fluxmail accounts send-as URL: https://fluxmail.ai/docs/cli/accounts-send-as `fluxmail accounts send-as` Manage sender addresses ## Usage [#usage] ```bash fluxmail accounts send-as [command] ``` ## Options [#options] This command has no command-specific options. ## Subcommands [#subcommands] | Command | Description | | ----------------------------------------------------------------------- | -------------------------------------------------- | | [`fluxmail accounts send-as list`](/docs/cli/accounts-send-as-list) | List available sender addresses | | [`fluxmail accounts send-as add`](/docs/cli/accounts-send-as-add) | Add a configured Outlook or IMAP sender address | | [`fluxmail accounts send-as remove`](/docs/cli/accounts-send-as-remove) | Remove a configured Outlook or IMAP sender address | --- # fluxmail accounts URL: https://fluxmail.ai/docs/cli/accounts `fluxmail accounts` Manage connected email accounts ## Usage [#usage] ```bash fluxmail accounts [command] ``` ## Options [#options] This command has no command-specific options. ## Subcommands [#subcommands] | Command | Description | | ------------------------------------------------------------- | -------------------------------------------------- | | [`fluxmail accounts send-as`](/docs/cli/accounts-send-as) | Manage sender addresses | | [`fluxmail accounts add`](/docs/cli/accounts-add) | Connect a Gmail, Outlook, or IMAP account | | [`fluxmail accounts configure`](/docs/cli/accounts-configure) | Set special folder paths for an IMAP account | | [`fluxmail accounts list`](/docs/cli/accounts-list) | List connected accounts | | [`fluxmail accounts remove`](/docs/cli/accounts-remove) | Disconnect an account and delete its stored tokens | | [`fluxmail accounts assign`](/docs/cli/accounts-assign) | Change mailbox ownership | | [`fluxmail accounts access`](/docs/cli/accounts-access) | Set who can access a mailbox | --- # fluxmail apikey accounts URL: https://fluxmail.ai/docs/cli/apikey-accounts `fluxmail apikey accounts` Replace or clear an API key mailbox allowlist ## Usage [#usage] ```bash fluxmail apikey accounts [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ------- | -------- | ------- | ------- | | `keyId` | Yes | None | None | ## Options [#options] | Option | Required | Details | Default | | --------------------- | -------- | --------------------------------------------------------- | ------- | | `--account ` | No | Replace the allowlist with this mailbox; repeat as needed | None | | `--all-accounts` | No | Clear the allowlist | None | --- # fluxmail apikey capabilities URL: https://fluxmail.ai/docs/cli/apikey-capabilities `fluxmail apikey capabilities` List capabilities for API key permission policies ## Usage [#usage] ```bash fluxmail apikey capabilities ``` ## Options [#options] This command has no command-specific options. --- # fluxmail apikey create URL: https://fluxmail.ai/docs/cli/apikey-create `fluxmail apikey create` Create an API key (shown once) ## Usage [#usage] ```bash fluxmail apikey create [options] ``` ## Options [#options] | Option | Required | Details | Default | | ---------------------- | -------- | --------------------------------------------------------------------------------- | ------- | | `--name ` | Yes | Human-readable key name | None | | `--member ` | No | Admin only: issue the key to another member | None | | `--account ` | No | Limit the key to one mailbox; repeat as needed | None | | `--profile ` | No | Tool profile: read-only, read-write, full | None | | `--allow ` | No | Allow one capability in a custom policy, or add it to --profile; repeat as needed | None | | `--admin ` | No | Add one admin capability to a named profile; repeat as needed | None | --- # fluxmail apikey list URL: https://fluxmail.ai/docs/cli/apikey-list `fluxmail apikey list` List API keys ## Usage [#usage] ```bash fluxmail apikey list ``` ## Options [#options] This command has no command-specific options. --- # fluxmail apikey permissions URL: https://fluxmail.ai/docs/cli/apikey-permissions `fluxmail apikey permissions` Change the permissions for an API key ## Usage [#usage] ```bash fluxmail apikey permissions [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ------- | -------- | ------- | ------- | | `keyId` | Yes | None | None | ## Options [#options] | Option | Required | Details | Default | | ---------------------- | -------- | --------------------------------------------------------------------------------- | ------- | | `--profile ` | No | Tool profile: read-only, read-write, full | None | | `--allow ` | No | Allow one capability in a custom policy, or add it to --profile; repeat as needed | None | | `--admin ` | No | Add one admin capability to a named profile; repeat as needed | None | --- # fluxmail apikey revoke URL: https://fluxmail.ai/docs/cli/apikey-revoke `fluxmail apikey revoke` Revoke an API key ## Usage [#usage] ```bash fluxmail apikey revoke ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ------- | -------- | ------- | ------- | | `keyId` | Yes | None | None | ## Options [#options] This command has no command-specific options. --- # fluxmail apikey URL: https://fluxmail.ai/docs/cli/apikey `fluxmail apikey` Manage API keys for the HTTP MCP and REST APIs ## Usage [#usage] ```bash fluxmail apikey [command] ``` ## Options [#options] This command has no command-specific options. ## Subcommands [#subcommands] | Command | Description | | --------------------------------------------------------------- | ------------------------------------------------- | | [`fluxmail apikey capabilities`](/docs/cli/apikey-capabilities) | List capabilities for API key permission policies | | [`fluxmail apikey create`](/docs/cli/apikey-create) | Create an API key (shown once) | | [`fluxmail apikey list`](/docs/cli/apikey-list) | List API keys | | [`fluxmail apikey accounts`](/docs/cli/apikey-accounts) | Replace or clear an API key mailbox allowlist | | [`fluxmail apikey permissions`](/docs/cli/apikey-permissions) | Change the permissions for an API key | | [`fluxmail apikey revoke`](/docs/cli/apikey-revoke) | Revoke an API key | --- # fluxmail attachments download URL: https://fluxmail.ai/docs/cli/attachments-download `fluxmail attachments download` Download an attachment ## Usage [#usage] ```bash fluxmail attachments download [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | --------------- | -------- | ------------------------------------------ | ------- | | `message-id` | Yes | Provider message ID | None | | `attachment-id` | Yes | Opaque attachment ID from message metadata | None | ## Options [#options] | Option | Required | Details | Default | | ----------------- | -------- | --------------------------------- | ------- | | `--output ` | Yes | Write the attachment to this path | None | | `--force` | No | Overwrite an existing file | None | --- # fluxmail attachments URL: https://fluxmail.ai/docs/cli/attachments `fluxmail attachments` Download message attachments ## Usage [#usage] ```bash fluxmail attachments [command] ``` ## Options [#options] This command has no command-specific options. ## Subcommands [#subcommands] | Command | Description | | ----------------------------------------------------------------- | ---------------------- | | [`fluxmail attachments download`](/docs/cli/attachments-download) | Download an attachment | --- # fluxmail auth recover-admin URL: https://fluxmail.ai/docs/cli/auth-recover-admin `fluxmail auth recover-admin` Reset an administrator password using local filesystem access ## Usage [#usage] ```bash fluxmail auth recover-admin ``` ## Arguments [#arguments] | Name | Required | Details | Default | | -------- | -------- | ------------------------- | ------- | | `member` | Yes | Administrator id or email | None | ## Options [#options] This command has no command-specific options. --- # fluxmail auth revoke-session URL: https://fluxmail.ai/docs/cli/auth-revoke-session `fluxmail auth revoke-session` Revoke one of the current member's sessions ## Usage [#usage] ```bash fluxmail auth revoke-session ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ----------- | -------- | ------- | ------- | | `sessionId` | Yes | None | None | ## Options [#options] This command has no command-specific options. --- # fluxmail auth sessions URL: https://fluxmail.ai/docs/cli/auth-sessions `fluxmail auth sessions` List sessions for the current member ## Usage [#usage] ```bash fluxmail auth sessions ``` ## Options [#options] This command has no command-specific options. --- # fluxmail auth URL: https://fluxmail.ai/docs/cli/auth `fluxmail auth` Manage interactive authentication ## Usage [#usage] ```bash fluxmail auth [command] ``` ## Options [#options] This command has no command-specific options. ## Subcommands [#subcommands] | Command | Description | | --------------------------------------------------------------- | ------------------------------------------------------------- | | [`fluxmail auth recover-admin`](/docs/cli/auth-recover-admin) | Reset an administrator password using local filesystem access | | [`fluxmail auth sessions`](/docs/cli/auth-sessions) | List sessions for the current member | | [`fluxmail auth revoke-session`](/docs/cli/auth-revoke-session) | Revoke one of the current member's sessions | --- # fluxmail config init URL: https://fluxmail.ai/docs/cli/config-init `fluxmail config init` Create config.toml in the Fluxmail data directory ## Usage [#usage] ```bash fluxmail config init ``` ## Options [#options] This command has no command-specific options. --- # fluxmail config migrate URL: https://fluxmail.ai/docs/cli/config-migrate `fluxmail config migrate` Import settings from an env file without deleting it ## Usage [#usage] ```bash fluxmail config migrate [options] ``` ## Options [#options] | Option | Required | Details | Default | | ------------------- | -------- | ------------------------------------------------------- | ------- | | `--from ` | Yes | Read recognized settings from this env file | None | | `--dry-run` | No | Show recognized setting names without changing Fluxmail | None | --- # fluxmail config show URL: https://fluxmail.ai/docs/cli/config-show `fluxmail config show` Show effective configuration, sources, paths, and restart requirements ## Usage [#usage] ```bash fluxmail config show ``` ## Options [#options] This command has no command-specific options. --- # fluxmail config URL: https://fluxmail.ai/docs/cli/config `fluxmail config` Inspect and initialize deployment configuration ## Usage [#usage] ```bash fluxmail config [command] ``` ## Options [#options] This command has no command-specific options. ## Subcommands [#subcommands] | Command | Description | | ----------------------------------------------------- | ---------------------------------------------------------------------- | | [`fluxmail config init`](/docs/cli/config-init) | Create config.toml in the Fluxmail data directory | | [`fluxmail config show`](/docs/cli/config-show) | Show effective configuration, sources, paths, and restart requirements | | [`fluxmail config migrate`](/docs/cli/config-migrate) | Import settings from an env file without deleting it | --- # fluxmail drafts create URL: https://fluxmail.ai/docs/cli/drafts-create `fluxmail drafts create` Create a draft ## Usage [#usage] ```bash fluxmail drafts create [options] ``` ## Options [#options] | Option | Required | Details | Default | | ------------------------- | -------- | --------------------------------------------------------------------------- | ------- | | `--from
` | No | Send from an available address | None | | `--to
` | No | Add a To recipient; repeat as needed | None | | `--cc
` | No | Add a Cc recipient; repeat as needed | None | | `--bcc
` | No | Add a Bcc recipient; repeat as needed | None | | `--subject ` | No | Set the subject | None | | `--body ` | No | Set the plain-text body; use blank lines between unwrapped prose paragraphs | None | | `--body-file ` | No | Read the plain-text body from a file; keep prose paragraphs unwrapped | None | | `--html ` | No | Set the HTML body | None | | `--html-file ` | No | Read the HTML body from a file | None | | `--attach ` | No | Attach a local file; repeat as needed | None | | `--reply-to ` | No | Reply to a message | None | | `--reply-all` | No | Include the original recipients in the reply | None | | `--input ` | No | Read an exact REST JSON body from a file, or pass - for stdin | None | --- # fluxmail drafts delete URL: https://fluxmail.ai/docs/cli/drafts-delete `fluxmail drafts delete` Delete a draft ## Usage [#usage] ```bash fluxmail drafts delete ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ---------- | -------- | ----------------- | ------- | | `draft-id` | Yes | Provider draft ID | None | ## Options [#options] This command has no command-specific options. --- # fluxmail drafts get URL: https://fluxmail.ai/docs/cli/drafts-get `fluxmail drafts get` Read a draft ## Usage [#usage] ```bash fluxmail drafts get ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ---------- | -------- | ----------------- | ------- | | `draft-id` | Yes | Provider draft ID | None | ## Options [#options] This command has no command-specific options. --- # fluxmail drafts update URL: https://fluxmail.ai/docs/cli/drafts-update `fluxmail drafts update` Replace the content of a draft ## Usage [#usage] ```bash fluxmail drafts update [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ---------- | -------- | ----------------- | ------- | | `draft-id` | Yes | Provider draft ID | None | ## Options [#options] | Option | Required | Details | Default | | ------------------------- | -------- | --------------------------------------------------------------------------- | ------- | | `--from
` | No | Send from an available address | None | | `--to
` | No | Add a To recipient; repeat as needed | None | | `--cc
` | No | Add a Cc recipient; repeat as needed | None | | `--bcc
` | No | Add a Bcc recipient; repeat as needed | None | | `--subject ` | No | Set the subject | None | | `--body ` | No | Set the plain-text body; use blank lines between unwrapped prose paragraphs | None | | `--body-file ` | No | Read the plain-text body from a file; keep prose paragraphs unwrapped | None | | `--html ` | No | Set the HTML body | None | | `--html-file ` | No | Read the HTML body from a file | None | | `--attach ` | No | Attach a local file; repeat as needed | None | | `--reply-to ` | No | Reply to a message | None | | `--reply-all` | No | Include the original recipients in the reply | None | | `--input ` | No | Read an exact REST JSON body from a file, or pass - for stdin | None | --- # fluxmail drafts URL: https://fluxmail.ai/docs/cli/drafts `fluxmail drafts` Create and manage drafts ## Usage [#usage] ```bash fluxmail drafts [command] ``` ## Options [#options] This command has no command-specific options. ## Subcommands [#subcommands] | Command | Description | | --------------------------------------------------- | ------------------------------ | | [`fluxmail drafts get`](/docs/cli/drafts-get) | Read a draft | | [`fluxmail drafts create`](/docs/cli/drafts-create) | Create a draft | | [`fluxmail drafts update`](/docs/cli/drafts-update) | Replace the content of a draft | | [`fluxmail drafts delete`](/docs/cli/drafts-delete) | Delete a draft | --- # fluxmail emails delivery-status URL: https://fluxmail.ai/docs/cli/emails-delivery-status `fluxmail emails delivery-status` Check a send or forward outcome ## Usage [#usage] ```bash fluxmail emails delivery-status ``` ## Arguments [#arguments] | Name | Required | Details | Default | | -------------- | -------- | --------------------- | ------- | | `operation-id` | Yes | Delivery operation ID | None | ## Options [#options] This command has no command-specific options. --- # fluxmail emails forward URL: https://fluxmail.ai/docs/cli/emails-forward `fluxmail emails forward` Forward a message ## Usage [#usage] ```bash fluxmail emails forward [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ------------ | -------- | ------------------- | ------- | | `message-id` | Yes | Provider message ID | None | ## Options [#options] | Option | Required | Details | Default | | ------------------------- | -------- | -------------------------------------------------------------------------- | ------- | | `--from
` | No | Send from an available address | None | | `--to
` | No | Add a To recipient; repeat as needed | None | | `--cc
` | No | Add a Cc recipient; repeat as needed | None | | `--comment ` | No | Add a comment above the forwarded message; keep prose paragraphs unwrapped | None | | `--no-attachments` | No | Do not include attachments from the original message | None | | `--idempotency-key ` | No | Reuse a delivery request safely | None | | `--input ` | No | Read an exact REST JSON body from a file, or pass - for stdin | None | --- # fluxmail emails get URL: https://fluxmail.ai/docs/cli/emails-get `fluxmail emails get` Get a complete message ## Usage [#usage] ```bash fluxmail emails get ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ------------ | -------- | ------------------- | ------- | | `message-id` | Yes | Provider message ID | None | ## Options [#options] This command has no command-specific options. --- # fluxmail emails list URL: https://fluxmail.ai/docs/cli/emails-list `fluxmail emails list` List and filter messages ## Usage [#usage] ```bash fluxmail emails list [options] ``` ## Options [#options] | Option | Required | Details | Default | | ------------------------------------ | -------- | -------------------------------------------------------- | ------- | | `--folder ` | No | Filter by folder ID, role, or name | None | | `--from
` | No | Filter by sender | None | | `--to
` | No | Filter by recipient | None | | `--subject ` | No | Filter by subject | None | | `--read ` | No | Filter by read state | None | | `--starred ` | No | Filter by starred state | None | | `--has-attachment ` | No | Filter by attachment state | None | | `--after ` | No | Return messages on or after this YYYY-MM-DD date | None | | `--before ` | No | Return messages before this YYYY-MM-DD date | None | | `--raw-provider-query ` | No | Pass a provider-native query | None | | `--page-size ` | No | Return 1 to 100 messages | None | | `--page-token ` | No | Continue from a previous response | None | | `--include-snippet ` | No | Request or suppress message previews | None | | `--include-search-context ` | No | Include a body excerpt around the search match | None | | `--all` | No | Fetch every page up to --max-results | None | | `--max-results ` | No | Maximum results with --all (default 1000, maximum 10000) | None | | `--text ` | No | Filter by literal full-text search | None | --- # fluxmail emails modify URL: https://fluxmail.ai/docs/cli/emails-modify `fluxmail emails modify` Apply one action to one or more messages ## Usage [#usage] ```bash fluxmail emails modify [action] [message-ids...] [options] ``` ## Arguments [#arguments] | Name | Required | Details | Default | | ---------------- | -------- | --------------------------------------------------------------- | ------- | | `action` | No | Message action, such as mark-read, archive, move, or add-labels | None | | `message-ids...` | No | Provider message IDs | None | ## Options [#options] | Option | Required | Details | Default | | ------------------- | -------- | ------------------------------------------------------------- | ------- | | `--folder ` | No | Destination folder for move | None | | `--label