{"id":33453042,"url":"https://github.com/rustmailer/bichon","last_synced_at":"2026-05-23T06:14:20.599Z","repository":{"id":324952201,"uuid":"1099214862","full_name":"rustmailer/bichon","owner":"rustmailer","description":"Bichon – A lightweight, high-performance Rust email archiver with WebUI","archived":false,"fork":false,"pushed_at":"2026-01-14T06:32:38.000Z","size":2224,"stargazers_count":1058,"open_issues_count":24,"forks_count":31,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-01-16T20:55:01.130Z","etag":null,"topics":["backup","compression","email","email-archiver","email-archiving","imap","mail","oauth2","openapi","rust","search","self-hosted","selfhosted","tantivy","webui"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rustmailer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":"rustmailer","thanks_dev":null,"custom":null}},"created_at":"2025-11-18T18:02:57.000Z","updated_at":"2026-01-16T18:25:08.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rustmailer/bichon","commit_stats":null,"previous_names":["rustmailer/bichon"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/rustmailer/bichon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustmailer%2Fbichon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustmailer%2Fbichon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustmailer%2Fbichon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustmailer%2Fbichon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rustmailer","download_url":"https://codeload.github.com/rustmailer/bichon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rustmailer%2Fbichon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28659878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backup","compression","email","email-archiver","email-archiving","imap","mail","oauth2","openapi","rust","search","self-hosted","selfhosted","tantivy","webui"],"created_at":"2025-11-24T21:04:14.470Z","updated_at":"2026-05-23T06:14:20.572Z","avatar_url":"https://github.com/rustmailer.png","language":"TypeScript","funding_links":["https://buymeacoffee.com/rustmailer"],"categories":["Libraries","TypeScript","Software","Applications","rust"],"sub_categories":["Email","Archiving and Digital Preservation (DP)","Emails"],"readme":"\u003cp align=\"center\"\u003e\n    \u003cimg width=\"200\" height=\"175\" alt=\"Bichon Logo\" src=\"https://github.com/user-attachments/assets/06dc3b67-7d55-4a93-a3de-8b90951c575b\" /\u003e\n\u003c/p\u003e\n\n\u003cH1 align=\"center\"\u003eBICHON\u003c/H1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/rustmailer/bichon/stargazers\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/stars/rustmailer/bichon?style=for-the-badge\u0026color=gold\u0026label=STARS\" alt=\"GitHub Stars\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/rustmailer/bichon\"\u003e\n    \u003cimg src=\"https://img.shields.io/docker/pulls/rustmailer/bichon?style=for-the-badge\u0026color=2496ED\u0026label=DOCKER%20PULLS\" alt=\"Docker Pulls\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://docs.google.com/forms/d/e/1FAIpQLScOlwsiUMfyQPBCLW2MLkygdRmAutEgvXDYPzzvEGPz0HFPXQ/viewform\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Roadmap-2026_Survey-blue?style=for-the-badge\u0026logo=googleforms\" alt=\"User Survey\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/rustmailer/bichon/releases\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/v/release/rustmailer/bichon\" alt=\"Release\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/rustmailer/bichon\"\u003e\n    \u003cimg src=\"https://img.shields.io/docker/v/rustmailer/bichon?label=docker\" alt=\"Docker\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/license-AGPLv3-blue.svg\" alt=\"License\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://deepwiki.com/rustmailer/bichon\"\u003e\n    \u003cimg src=\"https://deepwiki.com/badge.svg\" alt=\"Ask DeepWiki\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://discord.gg/Bq4M2cDmF4\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Discord-Join%20Server-7289DA?logo=discord\u0026logoColor=white\" alt=\"Discord\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://x.com/rustmailer\"\u003e\n    \u003cimg src=\"https://img.shields.io/twitter/follow/rustmailer?style=social\" alt=\"Follow on X\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003eA self-hosted email archiving server built in Rust. Download emails from IMAP accounts, builds a full-text search index, and serves a REST API with an embedded WebUI. Purpose-built for long-term preservation, unified cross-account search, and programmatic access to archived email.\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.youtube.com/watch?v=fMlayXo3Bo0\"\u003e\n    \u003cimg src=\"https://img.youtube.com/vi/fMlayXo3Bo0/maxresdefault.jpg\" alt=\"Watch the demo\"/\u003e\n  \u003c/a\u003e\n  \u003cbr/\u003e\n  \u003cem\u003e▶ Click to watch the demo\u003c/em\u003e\n\u003c/p\u003e\n\n\u003e [!NOTE]\n\u003e Bichon is an **archiver**, not an email client. It does not send, compose, forward, or reply to emails. Its optional SMTP server is for **receiving** emails only.\n\n## Contents\n\n- [Features](#features)\n- [Quick Start](#quick-start)\n  - [Docker (Recommended)](#docker-recommended)\n  - [Docker Compose](#docker-compose)\n  - [Binary Installation](#binary-installation)\n  - [Build from Source](#build-from-source)\n- [Configuration Reference](#configuration-reference)\n  - [Required Settings](#required-settings)\n  - [Server \u0026 Networking](#server--networking)\n  - [Logging](#logging)\n  - [CORS](#cors)\n  - [TLS \u0026 HTTPS](#tls--https)\n  - [SMTP Server](#smtp-server)\n  - [Storage Paths](#storage-paths)\n  - [Performance Tuning](#performance-tuning)\n- [Authentication \u0026 RBAC](#authentication--rbac)\n- [CLI Tools](#cli-tools)\n- [API Reference](#api-reference)\n- [Import \u0026 Export](#import--export)\n- [Architecture](#architecture)\n- [Storage \u0026 Backup](#storage--backup)\n- [Internationalization](#internationalization)\n- [Data Migration (v0.x → v1.0)](#data-migration-v0x--v10)\n- [FAQ](#faq)\n- [Roadmap](#roadmap)\n- [Contributing](#contributing)\n- [Tech Stack](#tech-stack)\n- [License](#license)\n\n## Features\n\n- **Multi-Account IMAP Download**: Download multi-account concurrently. Supports password (PLAIN/LOGIN) and OAuth 2.0 (SASL XOAUTH2) with automatic token refresh and PKCE. SSL/TLS, STARTTLS, or plain connections with optional self-signed certificate acceptance.\n- **Incremental Download**: UID-based delta fetching downloads only new messages after the initial download. UIDVALIDITY changes are detected and trigger automatic cache rebuilds.\n- **Fetch Scoping**: Filter download by date range, mailbox folder limit, or specific folder names. Configurable per-account SOCKS5 proxy routing.\n- **Auto-Configuration**: Discover IMAP server settings automatically from an email domain.\n- **Full-Text Search**: Search across subject, body, sender, recipients, attachment properties, and more. Optimized for European languages.\n- **Advanced Filters**: Date range, size range, attachment presence, file type, content category, and facet-based tag combinations.\n- **Thread Grouping**: Reconstruct and view complete conversation threads across folders.\n- **Attachment Search**: Browse and filter attachments by sender, file type, size, and other attachment properties.\n- **Faceted Tags**: Add, remove, or overwrite tags on messages and attachments. Filter by tag combinations with real-time count updates.\n- **Contacts View**: Extracted and deduplicated sender/recipient address book across all authorized accounts.\n- **Three-Layer Storage**: Tantivy for full-text indexing (Zstd compression), Fjall with LZ4 for compressed blob storage, and memdb for relational metadata. All embedded — zero external dependencies.\n- **Content Deduplication**: Identical email bodies and attachments stored once via BLAKE3 content hashing. Folder moves update metadata only.\n- **Dashboard Analytics**: Email volume trends, top senders, storage usage breakdown, attachment statistics, and per-account activity. Scoped by user permissions.\n- **OpenAPI 3.0**: Interactive API documentation at `/api-docs` (Swagger UI, ReDoc, Scalar). All endpoints documented with request/response schemas.\n- **Multi-User RBAC**: 5 built-in roles (Admin, Manager, Member, AccountManager, AccountViewer) plus custom roles with 22 granular permissions.\n- **Account-Level Isolation**: Grant users access to specific accounts with scoped roles. Permissions enforced at the API layer.\n- **CLI Import Tools**: Import from EML directories, MBOX files (including Gmail variants), Thunderbird profiles, and Outlook PST files.\n- **CLI Export**: Download account data as MBOX via `bichon-cli`.\n- **Bulk Restore**: Restore emails in bulk back to their original IMAP accounts.\n- **Embedded SMTP Server**: Receive emails directly at the gateway level. STARTTLS or TLS encryption. AUTH PLAIN/LOGIN with API token authentication.\n- **Admin Tooling**: Password reset for locked-out admins. Non-destructive v0.3.7 to v1.0 data migration.\n- **API Token Management**: Create, list, and revoke long-lived API tokens for programmatic access.\n- **SOCKS5 Proxy Management**: Configure and manage proxy profiles for routing IMAP traffic per account.\n\n## Quick Start\n\n### Docker (Recommended)\n\n```bash\n# Pull the image\ndocker pull rustmailer/bichon:latest\n\n# Create data directory\nmkdir -p ./bichon-data\n\n# Run container\ndocker run -d \\\n  --name bichon \\\n  -p 15630:15630 \\\n  -v $(pwd)/bichon-data:/data \\\n  --user 1000:1000 \\\n  -e BICHON_ROOT_DIR=/data \\\n  -e BICHON_ENCRYPT_PASSWORD=your-secure-password-here \\\n  rustmailer/bichon:latest\n```\n\nOpen **[http://localhost:15630](http://localhost:15630)** in your browser.\n\n\u003e [!IMPORTANT]\n\u003e Default login: username `admin`, password `admin@bichon`. **Change this immediately** via Settings → Profile.\n\n### Docker Compose\n\n```yaml\nservices:\n  bichon:\n    image: rustmailer/bichon:latest\n    container_name: bichon\n    ports:\n      - \"15630:15630\"\n    volumes:\n      - ./bichon-data:/data\n    user: \"1000:1000\"\n    environment:\n      BICHON_ROOT_DIR: /data\n      BICHON_ENCRYPT_PASSWORD: your-secure-password-here\n      BICHON_LOG_LEVEL: info\n```\n\n### Binary Installation\n\nDownload from the [Releases](https://github.com/rustmailer/bichon/releases) page:\n\n| Platform | Archive |\n|----------|---------|\n| Linux (GNU) | `bichon-x.x.x-x86_64-unknown-linux-gnu.tar.gz` |\n| Linux (MUSL) | `bichon-x.x.x-x86_64-unknown-linux-musl.tar.gz` |\n| macOS | `bichon-x.x.x-x86_64-apple-darwin.tar.gz` |\n| Windows | `bichon-x.x.x-x86_64-pc-windows-msvc.zip` |\n\n```bash\n# Linux / macOS\n./bichon --bichon-root-dir /path/to/data --bichon-encrypt-password your-password\n\n# Windows\n.\\bichon.exe --bichon-root-dir E:\\bichon-data --bichon-encrypt-password your-password\n```\n\n`--bichon-root-dir` **must be an absolute path**. All Bichon data lives under this directory.\n\n### Build from Source\n\n**Prerequisites:** Rust (latest stable), Node.js 20+, pnpm\n\n```bash\ngit clone https://github.com/rustmailer/bichon.git\ncd bichon\n\n# Build the WebUI (required before building the server)\ncd web \u0026\u0026 pnpm install \u0026\u0026 pnpm run build \u0026\u0026 cd ..\n\n# Build and run\nexport BICHON_ENCRYPT_PASSWORD=dev-password\ncargo run -- --bichon-root-dir /tmp/bichon-data\n```\n\nFor frontend development:\n\n```bash\ncd web \u0026\u0026 pnpm run dev   # Vite dev server with API proxy to Rust backend\n```\n\n\u003e [!TIP]\n\u003e The WebUI must be built at least once (`pnpm run build`) for the server to serve the frontend. In dev mode (`pnpm run dev`), Vite proxies API calls to the Rust server automatically.\n\n## Configuration Reference\n\nAll settings accept both CLI flags (`--bichon-http-port`) and environment variables (`BICHON_HTTP_PORT`). CLI flags take precedence over environment variables.\n\n### Required Settings\n\n| Variable | CLI Flag | Description |\n|----------|----------|-------------|\n| `BICHON_ROOT_DIR` | `--bichon-root-dir` | **Required.** Absolute path for all persistent data |\n| `BICHON_ENCRYPT_PASSWORD` | `--bichon-encrypt-password` | Password used to encrypt stored credentials (IMAP passwords, OAuth tokens) |\n| `BICHON_ENCRYPT_PASSWORD_FILE` | `--bichon-encrypt-password-file` | Alternative: read the encryption password from a file |\n\n\u003e [!NOTE]\n\u003e If both password options are set, the direct value takes precedence over the file.\n\n### Server \u0026 Networking\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `BICHON_HTTP_PORT` | `15630` | HTTP server port |\n| `BICHON_BIND_IP` | `0.0.0.0` | IP address to bind to (IPv4 or IPv6) |\n| `BICHON_PUBLIC_URL` | `http://localhost:15630` | Public-facing URL used in OAuth redirects and docs |\n| `BICHON_BASE_URL` | `/` | Base path for WebUI when behind a reverse proxy (e.g. `/bichon`) |\n| `BICHON_WEBUI_TOKEN_EXPIRATION_HOURS` | `168` | Access token lifetime in hours (default 7 days) |\n| `BICHON_HTTP_COMPRESSION_ENABLED` | `true` | Enable gzip/brotli/zstd response compression |\n\n### Logging\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `BICHON_LOG_LEVEL` | `info` | Log level: `trace`, `debug`, `info`, `warn`, `error` |\n| `BICHON_ANSI_LOGS` | `true` | Colorized terminal output |\n| `BICHON_JSON_LOGS` | `false` | JSON-formatted logs for log aggregators |\n| `BICHON_LOG_TO_FILE` | `false` | Persist logs to files under root dir |\n| `BICHON_MAX_SERVER_LOG_FILES` | `5` | Max log files to retain |\n\n### CORS\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `BICHON_CORS_ORIGINS` | *(allow all)* | Comma-separated list of allowed origins: `http://192.168.1.16:15630,http://myserver.local:15630` |\n| `BICHON_CORS_MAX_AGE` | `86400` | Cache duration for CORS preflight in seconds |\n\n\u003e [!WARNING]\n\u003e If `BICHON_CORS_ORIGINS` is **not set**, all origins are allowed. If you set it, only exact matches pass. Wildcards (`*`) are **not supported**. Do not add trailing slashes. When using Docker, avoid wrapping the value in quotes.\n\n### TLS \u0026 HTTPS\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `BICHON_ENABLE_REST_HTTPS` | `false` | Serve the API over HTTPS (requires valid certificate) |\n\n### SMTP Server\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `BICHON_ENABLE_SMTP` | `false` | Enable the embedded SMTP receiver |\n| `BICHON_SMTP_PORT` | `2525` | SMTP listening port |\n| `BICHON_SMTP_ENCRYPTION` | `starttls` | Encryption mode: `none`, `starttls`, or `tls` |\n| `BICHON_SMTP_AUTH_REQUIRED` | `true` | Require authentication for SMTP connections |\n| `BICHON_SMTP_TLS_KEY_PATH` | — | Absolute path to SMTP TLS private key |\n| `BICHON_SMTP_TLS_CERT_PATH` | — | Absolute path to SMTP TLS certificate chain |\n\n### Storage Paths\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `BICHON_INDEX_DIR` | `{root}/bichon-indices` | Tantivy full-text index directory |\n| `BICHON_DATA_DIR` | `{root}/bichon-storage` | Fjall blob storage directory |\n\n\u003e [!TIP]\n\u003e Place `BICHON_INDEX_DIR` on fast SSD storage for responsive search, and `BICHON_DATA_DIR` on high-capacity HDD for cost-effective blob storage.\n\n\n\u003e [!IMPORTANT]\n\u003e Bichon does NOT support writing data directly to a network file system (NFS, CIFS/SMB, etc.). All directories — `BICHON_ROOT_DIR`, `BICHON_DATA_DIR`, and `BICHON_INDEX_DIR` — must reside on a **local file system**; otherwise, data corruption may occur.\n\n### Performance Tuning\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `BICHON_SYNC_CONCURRENCY` | `num_cpus × 2` | Max concurrent account sync tasks |\n| `BICHON_METADATA_CACHE_SIZE` | `134217728` (128 MB) | Metadata DB cache in bytes |\n| `BICHON_ENVELOPE_CACHE_SIZE` | `134217728` (128 MB) | Envelope index cache in bytes |\n\n## Authentication \u0026 RBAC\n\n### Authentication\n\n1. `POST /api/login` with username + password returns a JWT access token\n2. All `/api/v1/*` endpoints require `Authorization: Bearer \u003ctoken\u003e`\n3. Tokens expire after the configured duration (`BICHON_WEBUI_TOKEN_EXPIRATION_HOURS`, default 7 days)\n4. Long-lived API tokens can be created via WebUI or API for programmatic access\n\n### Default Admin Account\n\nOn first start, Bichon creates a built-in admin user:\n\n- **Username:** `admin`\n- **Password:** `admin@bichon`\n\n\u003e [!IMPORTANT]\n\u003e **Change the password immediately** via WebUI: Settings → Profile. If locked out, use the `bichon-admin` CLI tool to reset it.\n\n### Built-in Roles\n\n| Role | Type | Scope | Description |\n|------|------|-------|-------------|\n| **Admin** | Global | Unrestricted | Full system access — users, roles, tokens, all accounts, all data operations |\n| **Manager** | Global | ACL-scoped | Create accounts, view users, manage authorized accounts and their data |\n| **Member** | Global | Minimal | Basic login access; data access granted through account-level role assignments |\n| **AccountManager** | Account | Per-account | Full control over an assigned account — config, sync, data read/write/delete, import, SMTP ingest |\n| **AccountViewer** | Account | Per-account | Read-only access to an assigned account's messages and metadata |\n\n### Permission Reference\n\n**Global permissions:**\n\n| Permission | Description |\n|------------|-------------|\n| `system:access` | Login and access the dashboard |\n| `system:root` | Manage system configurations (OAuth providers, proxy settings) |\n| `user:manage` | Create, update, and delete users |\n| `user:view` | View user list and basic profiles |\n| `token:manage` | View and revoke all API tokens |\n| `account:create` | Connect new email accounts to the system |\n| `account:manage:all` | Manage configurations for all email accounts |\n| `data:read:all` | Search and read messages across all accounts |\n| `data:manage:all` | Manage tags and metadata for all accounts |\n| `data:raw:download:all` | Download raw EML files from any account |\n| `data:delete:all` | Permanently delete messages from any account |\n| `data:export:batch:all` | Export messages in bulk from all accounts |\n\n**Account-scoped permissions (require ACL assignment):**\n\n| Permission | Description |\n|------------|-------------|\n| `account:manage` | Modify configuration and sync settings for authorized accounts |\n| `account:read_details` | View status and details of authorized accounts |\n| `data:read` | Read messages from authorized accounts |\n| `data:manage` | Manage tags and metadata for authorized accounts |\n| `data:raw:download` | Download raw EML files from authorized accounts |\n| `data:delete` | Delete messages from authorized accounts |\n| `data:export:batch` | Export messages from authorized accounts |\n| `data:import:batch` | Import EML/PST data into authorized accounts |\n| `data:smtp:ingest` | Receive and archive emails via SMTP for authorized accounts |\n\n\u003e [!TIP]\n\u003e Built-in role permissions are immutable. Create **custom roles** via WebUI (`/users/roles`) or API for any combination of the permissions above.\n\n## CLI Tools\n\n### bichon-cli — Import \u0026 Export\n\n```bash\n./bichon-cli --config config.toml\n```\n\nCreates a `config.toml` on first run with your server URL and API token.\n\n| Operation | Description |\n|-----------|-------------|\n| **EML Directory** | Recursively scan a directory tree of `.eml` files; preserves folder structure |\n| **MBOX** | Stream-import from a single `.mbox` archive (including Gmail's MBOX variant) |\n| **Thunderbird** | Import directly from a local Thunderbird profile directory |\n| **PST** | Import from Outlook Personal Storage `.pst` files |\n| **Export to MBOX** | Download account data as an `.mbox` file |\n\nAll imports are processed server-side — the server handles MIME parsing, indexing, deduplication, and storage.\n\n### bichon-admin — Administration\n\n```bash\n./bichon-admin\n```\n\nInteractive menu with two operations:\n\n| Operation | Description |\n|-----------|-------------|\n| **Reset Admin Password** | Reset the built-in admin password when locked out |\n| **Migrate v0.3.7 → v1.0** | Non-destructive migration from legacy storage layout to v1.0 architecture |\n\n## API Reference\n\nInteractive API documentation is available at:\n\n| Endpoint | UI |\n|----------|----|\n| `/api-docs/swagger` | Swagger UI |\n| `/api-docs/redoc` | ReDoc |\n| `/api-docs/scalar` | Scalar |\n| `/api-docs/spec.json` | Raw OpenAPI 3.0 JSON |\n| `/api-docs/spec.yaml` | Raw OpenAPI 3.0 YAML |\n\nAll `/api/v1/*` endpoints require `Authorization: Bearer \u003ctoken\u003e`.\n\n## Import \u0026 Export\n\n### Supported Formats\n\n| Format | Tool | Notes |\n|--------|------|-------|\n| **EML Directory** | `bichon-cli` | Recursive `.eml` scan; preserves folder hierarchy |\n| **MBOX** | `bichon-cli` | Single-file streaming import; supports Gmail's MBOX variant |\n| **Thunderbird** | `bichon-cli` | Reads directly from local Thunderbird profile directory |\n| **PST** | `bichon-cli` | Outlook Personal Storage (`.pst`) file parsing |\n| **API Import** | `POST /api/v1/import` | Base64-encoded EML payloads for programmatic use |\n| **MBOX Export** | `bichon-cli` | Download account data as `.mbox` file |\n\nAll imports flow through the Bichon REST API. The server parses MIME, extracts metadata, indexes content into Tantivy, deduplicates by BLAKE3 content hash, and stores raw blobs in Fjall.\n\n## Architecture\n\n### Workspace Crates\n\n```\nbichon/\n├── crates/\n│   ├── memdb/         Embedded key-value database layer (WAL, transactions)\n│   ├── core/          Library — IMAP sync, search, storage, auth, models\n│   ├── server/        Binary — Poem web server + embedded WebUI (rust-embed)\n│   ├── cli/           Binary — bichon-cli import/export CLI\n│   └── admin/         Binary — bichon-admin password reset \u0026 migration\n└── web/               React + TypeScript + Vite + ShadCN UI frontend\n```\n\n### Three-Layer Storage\n\n```\nRequest Layer\n    REST API (Poem)  │  WebUI (React)\n─────────────────────┼────────────────────\nStorage Layer         │\n                      │\n  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐\n  │    memdb     │  │   Tantivy    │  │    Fjall     │\n  │  (metadata)  │  │  (full-text) │  │   (blobs)    │\n  │              │  │              │  │              │\n  │ • accounts   │  │ • envelope   │  │ • raw emails │\n  │ • users      │  │ • attachment │  │ • attachments│\n  │ • roles      │  │ • tags       │  │   LZ4 compr. │\n  │ • config     │  │ • contacts   │  │              │\n  │ • proxies    │  │   Zstd compr.│  │ BLAKE3 hash  │\n  └──────────────┘  └──────────────┘  └──────────────┘\n```\n\n- **memdb**: Key-value metadata store. Houses accounts, users, roles, OAuth2 configs, proxy settings, and system configuration. All operations wrapped in `tokio::spawn_blocking`.\n- **Tantivy**: Full-text search indices with Zstd compression support. Two separate indices: envelope (email metadata + body text) and attachment (file metadata + extracted text). Batch-committed every 1,000 documents or 60 seconds.\n- **Fjall**: LZ4-compressed LSM tree key-value store. Two keyspaces — `email_keyspace` and `attachments_keyspace`. Content-hash addressed (BLAKE3) with insert-time deduplication. Values larger than 1 KB stored as separate files (KV separation).\n\n### IMAP Download Pipeline\n\n```\nSchedule tick (every 10s)\n        │\n        ▼\n  reconcile_mailboxes()\n  Compare local vs. remote\n        │\n   ┌────┴────┐\n   ▼         ▼\nUID OK    UID changed / new\n(incremental)  (full rebuild)\n   │         │\n   ▼         ▼\nfetch new   fetch all\n(max+1:*)   (1:* batched)\n   │         │\n   └────┬────┘\n        ▼\nextract_envelope_and_store_it()\n        │\n   ┌────┼────┐\n   ▼    ▼    ▼\nTantivy Fjall memdb\n```\n\n- Per-account background tasks managed by a global download-task singleton\n- Concurrency controlled by semaphore (default: `num_cpus × 2`)\n- Manual sync via `POST /api/v1/accounts/:id/start-download`; cancel with `cancel-download`\n- Busy-check prevents overlapping manual and automatic syncs on the same account\n\n## Storage \u0026 Backup\n\n### Data Directory Layout\n\n```\n{root}/\n├── bichon-indices/         Tantivy full-text index (envelope + attachment)\n├── bichon-storage/         Fjall LZ4-compressed blob store\n├── memdb/                  Metadata database (accounts, users, roles, config)\n├── logs/                   Server logs (when BICHON_LOG_TO_FILE=true)\n```\n\n### Backup\nBack up the entire `BICHON_ROOT_DIR` (and `BICHON_INDEX_DIR` / `BICHON_DATA_DIR` if overridden). **All three layers must be backed up together** for consistency.\n\n\u003e [!WARNING]\n\u003e Do not place `BICHON_ROOT_DIR` or index/data directories directly on network-mounted storage (NFS, SMB, etc.). This can cause index corruption and data loss. Always run Bichon on local storage and use rsync or similar tools to sync to remote destinations.\n\n```bash\n# Example with rsync\nrsync -avz /path/to/bichon-data/ backup-server:/backups/bichon/\n```\n\n### Encryption\nStored credentials (IMAP passwords, OAuth tokens) are encrypted with AES-256-GCM via `ring`. The encryption key is derived from `BICHON_ENCRYPT_PASSWORD`.\n\n\u003e [!NOTE]\n\u003e Re-encrypting stored secrets after a password change is not yet supported. If this is a required feature for your use case, please open an issue.\n\n## Internationalization\nThe WebUI is available in **18 languages**:\n\n| Code | Language | Code | Language |\n|------|----------|------|----------|\n| `ar` | العربية | `it` | Italiano |\n| `da` | Dansk | `jp` | 日本語 |\n| `de` | Deutsch | `ko` | 한국어 |\n| `en` | English | `nl` | Nederlands |\n| `es` | Español | `no` | Norsk |\n| `fi` | Suomi | `pl` | Polski |\n| `fr` | Français | `pt` | Português |\n| `it` | Italiano | `ru` | Русский |\n| `zh` | 中文 | `sv` | Svenska |\n| `zh-tw` | 繁體中文 | | |\n\nLanguage preference and UI theme are saved to your user profile and can be changed anytime from the WebUI settings.\n\n## Data Migration (v0.3.7 → v1.0)\n\nBichon v1.0 introduced a redesigned storage architecture:\n\n| Layer | v0.3.7 (Legacy) | v1.0 |\n|-------|---------------|------|\n| **Index** | Tantivy (shared) | Tantivy (separate envelope + attachment indices) |\n| **Raw data** | Tantivy (inline) | Fjall (LZ4-compressed key-value store) |\n| **Metadata** | Tantivy (shared) | memdb (dedicated embedded DB) |\n\nIf you ran Bichon prior to v1.0, migrate your data:\n\n```bash\n./bichon-admin\n# Select \"Migrate Legacy v0.3.7 Storage to v1.0\"\n```\n\n\u003e [!NOTE]\n\u003e The migration is **non-destructive** — original v0.3.7 files remain in place and are not modified. You can safely remove them manually after verifying the migration was successful.\n\n## FAQ\n\n### CORS errors when accessing the WebUI\n\n1. Enable debug logging: `BICHON_LOG_LEVEL=debug`\n2. Check the server logs for the incoming `Origin` header and configured origins\n3. Ensure the browser's exact origin matches an entry in `BICHON_CORS_ORIGINS` (no trailing slash, no wildcards)\n4. In Docker, do **not** quote the value: `-e BICHON_CORS_ORIGINS=http://192.168.1.16:15630`\n\n### \"Legacy data layout detected\" error on startup\n\nYour data was created by Bichon v0.3.7 and must be migrated. Run `./bichon-admin` and select the migration option.\n\n### How do I run Bichon behind a reverse proxy?\n\nSet `BICHON_BASE_URL=/bichon` (or your sub-path) and configure your proxy:\n\n```nginx\n# nginx example\nlocation /bichon/ {\n    proxy_pass http://127.0.0.1:15630/;\n    proxy_set_header Host $host;\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n}\n```\n\n### Can Bichon send emails?\n\nNo. Bichon is an **archiver**, not an email client. The optional SMTP server **receives** emails only — it cannot send, forward, or reply.\n\n### What hardware does Bichon need?\n\n- **Minimal:** 1 CPU core, 512 MB RAM\n- **Recommended (100+ accounts, 200+ GB):** 4+ cores, 2+ GB RAM\n- Indices benefit from SSD storage; blob storage can use HDD\n\n### How do I reset the admin password?\n\n```bash\n./bichon-admin\n# Select \"Reset Admin Password\"\n```\n\n### Where can I get help?\n\n- [GitHub Issues](https://github.com/rustmailer/bichon/issues)\n- [Discord](https://discord.gg/Bq4M2cDmF4)\n- [Wiki](https://github.com/rustmailer/bichon/wiki)\n\n## Roadmap\n\n- [x] Multi-account IMAP Download (Password + OAuth2)\n- [x] Full-text search with faceted tags\n- [x] Multi-user support with RBAC and custom roles\n- [x] WebUI in 18 languages with dark/light themes\n- [x] Dashboard with analytics\n- [x] CLI import: EML, MBOX, Thunderbird, PST\n- [x] CLI export: MBOX\n- [x] Embedded SMTP server\n- [x] Data migration tooling (v0.3.7 → v1.0)\n- [x] On-demand manual download controls\n- [ ] Post-download server cleanup (free remote mailbox space)\n- [ ] Account-to-account email merge / migration\n- [ ] MCP Server for LLM-powered email search and analysis\n- [ ] S3-compatible storage backend\n- [ ] Enterprise SSO (OIDC / SAML)\n\n## Contributing\n\nContributions of all kinds are welcome — code, bug reports, documentation, or feature suggestions.\n\n```bash\ngit clone https://github.com/rustmailer/bichon.git\ncd bichon\n\n# Build WebUI\ncd web \u0026\u0026 pnpm install \u0026\u0026 pnpm run build \u0026\u0026 cd ..\n\n# Build backend\ncargo build\n\n# Run tests\ncargo test\n```\n\n\u003e [!IMPORTANT]\n\u003e Before implementing a new feature or making significant changes, please **open an issue first** to discuss your idea with the maintainer and ensure it aligns with the project's scope.\n\nFeel free to open an [Issue](https://github.com/rustmailer/bichon/issues) or join the [Discord](https://discord.gg/Bq4M2cDmF4) to discuss ideas.\n\n## Tech Stack\n\n| Layer | Technology |\n|-------|-----------|\n| **Backend** | Rust, Tokio, Poem + Poem OpenAPI |\n| **Full-text search** | Tantivy (Zstd compression) |\n| **Blob storage** | Fjall (LSM tree, LZ4 compression, KV separation) |\n| **Metadata DB** | memdb (embedded key-value store with WAL) |\n| **IMAP** | async-imap, rustls (ring), SOCKS5 proxy support |\n| **SMTP** | Embedded receiver (AUTH PLAIN/LOGIN, STARTTLS/TLS) |\n| **Cryptography** | AES-256-GCM (ring), BLAKE3 (content hashing) |\n| **Frontend** | React 18, TypeScript, Vite 6, ShadCN UI, TanStack Router/Query/Table |\n| **Charts** | Recharts |\n| **i18n** | i18next (18 languages) |\n| **Allocator** | mimalloc |\n| **Container** | Ubuntu 24.04, Docker |\n\n## License\n\nBichon is licensed under the [GNU Affero General Public License v3.0](LICENSE).\nCopyright \u0026copy; 2025–2026 [rustmailer.com](https://rustmailer.com)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustmailer%2Fbichon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frustmailer%2Fbichon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frustmailer%2Fbichon/lists"}