Self-hosted email archive that centralizes organizational email in one searchable place.
MailArchive keeps a local, searchable copy of your organization's email — across Microsoft 365 and IMAP mailboxes — with storage and access under your control. Open source (MIT). No proprietary archive lock-in. No PST dependency.
Docs: User manual (EN) · Manual de usuario (ES) · TODO · Backup · Contributing · Changelog
Landing: redmanxp.github.io/MailArchive-OSS (Vite + Tailwind · GitHub Pages)
Email is a critical business record. Provider quotas, account changes, employee turnover, or accidental deletion should not mean losing years of communication.
MailArchive gives your organization a central archive you host and govern: search it, restore it, and keep copies independently of the original mailbox provider.
- Microsoft 365 / Exchange Online (Graph OAuth)
- Generic IMAP servers
- Multiple mailboxes in one centralized archive
- Full-text search over archived messages
- Browse history without depending on the live provider mailbox
- Download EML or ZIP; restore messages back to the provider
- Admin / Supervisor — manage the organization archive and oversee all mailboxes
- User — archive and access their own linked accounts
- Read-only — consult without changing data
- Audit trail of sensitive actions
- Messages stored as standard EML + attachments + metadata (SHA-256)
- Local filesystem or S3-compatible object storage (MinIO, AWS S3, R2, Wasabi, …)
- Branding assets stay on disk; mail objects can live in the bucket
- Export mailboxes as EML / ZIP — independent from the email provider (no PST lock-in)
- Restore to the provider, with optional keep-local-copy
- Keep a searchable local copy (optional keep copy on restore)
- Ease quota pressure by archiving older mail from the provider
- Preserve history when people leave or providers change
- Build an internal searchable email repository for the organization
- Centralize Microsoft 365 and IMAP mailboxes in one place
- Archive former employee mailboxes before deprovisioning
- Keep historical communications after account or tenant changes
- Export an archive in standard EML format, independent of the provider
- Reduce mailbox usage / free quota on Microsoft 365 or IMAP servers
- Restore selected messages to the provider while optionally retaining the local copy
- Employee departure: archive a leaving employee's mailbox and keep it searchable for admins
- Transfer linked mailboxes between users (admin) when people change roles
| Login | Dashboard |
|---|---|
![]() |
![]() |
| Users | Settings |
|---|---|
![]() |
![]() |
| Archived search | Accounts |
|---|---|
![]() |
![]() |
- Clean Architecture (API / use cases / domain / infrastructure)
- Multi-tenant ready (
tenant_idfrom day one; install v1 = one organization) - Providers behind a
MailProviderinterface - Public self-register off by default (
FEATURE_PUBLIC_REGISTER=false) - Rate limiting on login / register / install
- App-wide language packs (UI + email templates); ES/EN included
- Editable invite / reset email templates
- Docker on Linux hosts
- Microsoft 365 / Exchange Online (Graph OAuth)
- Generic IMAP servers
- SQLite (demo / small installs) and MySQL (production profile)
- Filesystem or S3-compatible mail storage
Never commit secrets (
.env, tokens, passwords, certificates, dumps).
- Copy
.env.example→.envand fill in local values. .envis gitignored — do not commit it.- Never commit Microsoft credentials, IMAP/SMTP/MySQL passwords, PEM keys, or SQL dumps.
- If a secret leaks: rotate it immediately.
See SECURITY.md.
MailArchive ships as two images (API + UI). Prefer Compose:
git clone https://github.com/redmanxp/MailArchive-OSS.git
cd MailArchive-OSS
cp .env.example .env
# Set SECRET_KEY, JWT_SECRET_KEY, DATA_ENCRYPTION_KEY (see comments in .env.example)
export GHCR_OWNER=redmanxp
export MAILARCHIVE_TAG=1.0.0 # or latest
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
# UI: http://localhost:8080
# API: http://localhost:18100/healthOr pull the images directly (public packages — no docker login required):
docker pull ghcr.io/redmanxp/mailarchive-api:1.0.0
docker pull ghcr.io/redmanxp/mailarchive-frontend:1.0.0Update later:
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -dOptional MySQL: set DB_ENGINE=mysql in .env, then
docker compose -f docker-compose.prod.yml --profile mysql up -d.
Images are published on version tags (v1.0.0, …) and via Actions → Publish GHCR → Run workflow. Tags: latest, 1, 1.0, 1.0.0.
cp .env.example .env # set SECRET_KEY, JWT, Fernet, etc.
docker compose up --build
# UI: http://localhost:8080
# API: http://localhost:18100/healthOptional MySQL: docker compose --profile mysql up --build and set DB_ENGINE=mysql in .env.
Optional MinIO (S3 lab): docker compose --profile minio up -d, then Settings → Data → Object storage with endpoint http://minio:9000 (from the API container).
To use GHCR images while keeping the full compose (mysql/minio profiles):
export GHCR_OWNER=redmanxp
docker compose -f docker-compose.yml -f docker-compose.ghcr.yml pull
docker compose -f docker-compose.yml -f docker-compose.ghcr.yml up -d# Backend
cd backend
source .venv/bin/activate # uv venv .venv --python 3.12
export PYTHONPATH=$PWD
uvicorn app.main:app --host 0.0.0.0 --port 18100
# Frontend
cd frontend
npm install
npm run dev # http://localhost:5175On startup the API runs Alembic migrations and creates any missing tables.
API smoke test: bash scripts/test_phase0.sh http://127.0.0.1:18100
| Layer | Technologies |
|---|---|
| Backend | Python 3.11+, FastAPI, SQLAlchemy, Alembic, MySQL/SQLite, JWT, Pydantic |
| Providers | Microsoft Graph (HTTP/httpx), IMAPClient |
| Frontend | React, Vite, TypeScript, Material UI, React Router, Axios |
| Storage | Filesystem or S3 (mail.eml + attachments + metadata.json, SHA-256) |
backend/ FastAPI + Clean Architecture
frontend/ React + Vite (app UI)
landing/ Marketing site (GitHub Pages)
storage/ Local data (gitignored)
docs/ Manuals, release checklist, screenshots
deploy/ systemd / nginx examples
MailArchive is a self-hosted organizational email archive — not a real-time mailbox sync tool. Language we use on purpose: scheduled incremental archive. We avoid “sync” (that implies mirror deletes, bidirectional changes, and conflict resolution).
- Manual / bulk archive (Microsoft 365 Graph + IMAP)
- Search (FTS) + RBAC + audit
- Open EML storage (filesystem) + optional S3-compatible backend
- Download EML / ZIP export; restore to provider (optional keep-local-copy)
- Delete from archive + exclusion tombstones (jobs will not re-download)
- Docker, i18n ES/EN, SMTP templates, GHCR, docs
- Scheduled incremental archive (per-account; optional historical backfill — not “sync”)
- Archive status per account; dashboard archive health
- Admin: transfer linked accounts; unlink keeps archive; deactivate asks transfer vs unlink
- Employee departure wizard (historical pull + keep searchable + disable access)
- Gmail via IMAP + App Password with UI preset (
imap.gmail.com:993); dedicated Gmail OAuth still optional later
See the full release checklist and TODO.
- Retention policies (time-based cleanup rules)
- Advanced permissions / sharing refinements
- Optional Postgres
- External queue worker (Redis/Celery) for multi-node
- Dedicated Gmail OAuth (optional; IMAP preset already ships)
- Legal hold / stronger immutability (WORM-oriented options)
- LDAP / Active Directory
- Compliance reporting
- Deeper multi-tenant SaaS UX
If MailArchive helps your organization, consider supporting development.
Page: ko-fi.com/mailarchive · GitHub Sponsor button via .github/FUNDING.yml
Your support helps fund development, documentation, testing, and new hardware for the project.
Español: este README está en inglés a propósito (público / GitHub). Manual de uso: docs/MANUAL_USUARIO.md. Checklist de release: docs/RELEASE_CHECKLIST.md.






