Frappe Mail
  • Python 56.7%
  • Vue 29.2%
  • TypeScript 7.1%
  • JavaScript 5.6%
  • HTML 0.9%
  • Other 0.5%
Find a file
Akash Tom d26e8bdc0e
feat: chunked file upload for mail import (#597)
Upload import files in sequential chunks so large archives aren't capped
by the web server's request-body limit. Adds a useChunkedUpload composable
(matching the framework's chunked upload_file handler) and switches the
import UI off frappe-ui's FileUploader to use it.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 18:07:39 +05:30
.github chore: branching workflow 2026-06-09 10:21:13 +05:30
docker Merge pull request #340 from asaura08/patch-1 2025-12-15 11:12:33 +05:30
docs/screenshots docs: update README.md (#529) 2026-06-17 16:28:20 +05:30
frappe-ui@21e081816b chore: add CLAUDE.md 2026-05-26 17:56:55 +05:30
frontend feat: chunked file upload for mail import (#597) 2026-06-22 18:07:39 +05:30
mail Merge remote-tracking branch 'upstream/develop' into pr-571-resolve 2026-06-22 17:35:32 +05:30
scripts feat: switch to bun 2026-04-10 17:44:44 +05:30
UPGRADING fix: prefix Error Log titles with "[Mail]" (#572) 2026-06-19 17:25:42 +05:30
.editorconfig chore: add tsconfig and add ts file type to pre-commit 2025-02-11 15:05:53 +05:30
.git-blame-ignore-revs refactor: use single component to show all folder pages 2025-02-17 14:19:09 +05:30
.gitignore feat: switch to bun 2026-04-10 17:44:44 +05:30
.gitmodules feat: docker setup 2025-01-20 19:31:13 +05:30
.mergify.yml fix(mergify): allow PR authors to run the backport command (#509) 2026-06-10 13:21:08 +05:30
.pre-commit-config.yaml fix: typo in docs 2025-12-13 23:19:00 +05:30
.prettierrc.json chore: update eslint config 2025-02-10 12:46:44 +05:30
.releaserc chore: branching workflow 2026-06-09 10:21:13 +05:30
CLAUDE.md chore: add CLAUDE.md 2026-05-26 17:56:55 +05:30
CODEOWNERS chore: add CODEOWNERS 2025-12-12 10:20:09 +05:30
commitlint.config.js chore: lint vue and js files 2025-02-10 16:19:38 +05:30
eslint.config.mjs chore: update frappe-ui and ignore linting for doctypes file 2026-04-10 11:58:13 +05:30
license.txt feat: Initialize App 2023-12-23 18:50:53 +05:30
package.json fix: postinstall script 2026-04-10 18:28:40 +05:30
pyproject.toml feat: use LMDB as DataStore (#548) 2026-06-18 20:30:00 +05:30
README.md docs: update README.md (#529) 2026-06-17 16:28:20 +05:30
yarn.lock build: restore yarn.lock 2026-04-10 19:02:28 +05:30

Frappe Mail logo

Frappe Mail

End-to-End Email Management Platform

architecture

Frappe Mail

Frappe Mail is an end-to-end mail platform with two core responsibilities:

  1. A generic JMAP client for mailbox operations (read, send, manage identities, contacts, settings).
  2. A control plane for deploying and managing one or more Stalwart Mail clusters.

It is built as a Frappe app with a Vue 3 + TypeScript frontend.

Contents

Why Frappe Mail

  • JMAP-first architecture for modern mail workflows.
  • Unified UI and APIs for mailbox users and platform admins.
  • Multi-cluster Stalwart operations from one control plane.
  • Built-in support for provisioning, DNS records, sync, and lifecycle management.

Good fit for:

  • Teams self-hosting email infrastructure.
  • Integrators building on a JMAP-compatible mailbox backend.
  • Operators managing multiple Stalwart clusters with centralized workflows.

System Requirements

  • Python: 3.14
  • Frappe Framework: 16+
  • Node toolchain: Bun (frontend scripts use Bun)
  • Optional for local container setup: Docker + Docker Compose

Quick Start

Option A: Docker

wget -O docker-compose.yml https://raw.githubusercontent.com/frappe/mail/develop/docker/docker-compose.yml
wget -O init.sh https://raw.githubusercontent.com/frappe/mail/develop/docker/init.sh
docker compose up -d

Open http://mail.localhost

Default credentials:

  • Username: administrator
  • Password: admin

Option B: Manual Bench Setup

Prerequisite: Bench installed and working. See the Frappe installation guide: https://docs.frappe.io/framework/user/en/installation

From your bench root (not from apps/mail):

bench get-app mail
bench new-site mail.localhost --install-app mail
bench browse mail.localhost --user Administrator

Development

Frontend Commands

Run from repository root unless noted otherwise.

# install frontend dependencies (runs after npm install via postinstall)
npm install

# start Vite dev server
npm run dev

# build frontend + email css
npm run build

# build frontend only
npm run build-app

# build email css only
npm run build-email-css

Backend and Tests

Run from bench root:

bench --site <site> install-app mail
bench --site <site> run-tests --app mail
bench --site <site> run-tests --app mail --module mail.tests.test_foo
bench build

Linting and Formatting

pre-commit run --all-files
ruff check mail/
cd frontend && bun run lint

Stalwart Setup from UI

Use the Admin Dashboard to configure and deploy Stalwart.

  1. Configure Mail Settings
  2. Create a Mail Cluster
  3. Create a Mail Server
  4. Verify SSH connection
  5. Run install actions (Ansible, Docker, Stalwart)
  6. Regenerate and redeploy after config changes
  7. Add domains and publish DNS records

Reference screenshots:

  • Mail Settings: Mail Settings
  • Mail Cluster: Mail Cluster
  • Mail Server: Mail Server
  • SSH: Mail Server SSH Tab
  • Stalwart login: Stalwart Login Page

Credentials Configuration

Set Stalwart credentials in Mail Settings (recommended) or in site_config.json:

{
  "mail": {
    "server_url": "https://mail.example.com",
    "username": "admin",
    "password": "your-password"
  }
}

stalwart-cli is auto-downloaded after migrate. You can pin the CLI version via mail.stalwart_cli_version in site_config.json.

API Quick Reference

Authentication

  • Validate mailbox ownership/permission
    • POST /auth/validate
    • Frappe method: /api/method/mail.api.auth.validate

Outbound

  • Send structured message
    • POST /outbound/send
    • Frappe method: /api/method/mail.api.outbound.send
  • Send raw MIME message
    • POST /outbound/send-raw
    • Frappe method: /api/method/mail.api.outbound.send_raw

Inbound

  • Pull parsed messages
    • GET /inbound/pull
    • Frappe method: /api/method/mail.api.inbound.pull
  • Pull raw MIME messages
    • GET /inbound/pull-raw
    • Frappe method: /api/method/mail.api.inbound.pull_raw

For request payload details, inspect implementation in:

  • mail/api/auth.py
  • mail/api/outbound.py
  • mail/api/inbound.py

Frontend Overview

Frappe Mail frontend is split into two primary surfaces.

Mailbox

  • Folder and thread navigation
  • Compose, reply, forward
  • Search and filtering
  • Keyboard shortcuts
  • Address books and contacts
  • Account/identity/vacation settings
  • Mail exchange (import/export)
  • PWA support

Screenshots:

  • Mailbox
  • Mail list
  • Thread view
  • Compose
  • Search
  • Shortcuts

Admin Dashboard

  • Domain management
  • Member and access management
  • Invite workflows
  • Mailing list management

Screenshots:

  • Domain
  • Member
  • Invites
  • Mailing list

Sign-up Flows

Two supported onboarding flows:

  1. Open sign-up (domain whitelist based, enabled in Mail Settings)
  2. Invite-based sign-up

Invite flow screenshots:

  • Invite flow step 1
  • Invite flow step 2
  • Invite flow step 3

Contributing

Enable pre-commit hooks:

pre-commit install

Pre-commit runs:

  • ruff
  • eslint
  • prettier
  • pyupgrade

License

GNU Affero General Public License v3.0