Postlane is a full-stack mail application inspired by modern webmail workflows. It includes a Next.js frontend, a FastAPI backend, threaded mailbox views, inbound SMTP ingestion, Redis-backed runtime services, and an admin surface for operational visibility.
- Threaded inbox, sent, archive, spam, and trash flows
- Local inbound SMTP listener for testing real email delivery into user mailboxes
- Redis integration for runtime coordination and event-related infrastructure
- Postgres persistence for users, threads, messages, labels, drafts, and settings
- NextAuth-based frontend authentication and FastAPI JWT-backed backend flows
- Admin dashboard and mailbox insights
- Docker Compose stack with Traefik, frontend, backend, Postgres, Redis, OTEL Collector, Jaeger, Prometheus, Grafana, and Redis Commander
- Frontend: Next.js, TypeScript, React, Tailwind CSS
- backend: FastAPI, SQLAlchemy asyncio, Pydantic
- Database: PostgreSQL
- Cache and coordination: Redis
- Auth: NextAuth on the frontend, JWT on the backend
- Tooling:
pnpm,uv, Docker Compose
The app runs behind a single Traefik entrypoint:
/and/api/auth/*route to the Next.js frontend/api/v1/*route to the FastAPI backend- SMTP mail is accepted on
localhost:2525 - OTEL traces and metrics flow through the OpenTelemetry Collector
- Jaeger is exposed on
http://localhost:16686 - Grafana is exposed on
http://localhost:3001 - Prometheus is exposed on
http://localhost:9090 - Redis Commander is exposed on
http://localhost:8081
Core services in Docker:
frontend: Postlane web appbackend: FastAPI API and SMTP listenerpostgres: primary relational storeredis: cache and runtime coordinationotel-collector: OTLP ingestion and telemetry export pipelinejaeger: distributed tracing UIprometheus: metrics scraping and query enginegrafana: dashboards for metrics and tracesredis-commander: Redis inspection dashboardtraefik: public reverse proxy
- Docker and Docker Compose
make
- Copy
.env.exampleto.env - Update secrets if needed
- Start the stack:
make start-build- App: http://localhost:59998
- backend API: http://localhost:59998/api/v1
- SMTP test port:
localhost:2525 - Grafana: http://localhost:3001
- Jaeger: http://localhost:16686
- Prometheus: http://localhost:9090
- Redis board: http://localhost:8081
- Email:
admin@example.com - Password:
ChangeMe123!
Run these from the repo root:
make startstarts the Docker stackmake start-buildrebuilds images and starts the stackmake stopstops the stackmake stop-cleanstops the stack and removes volumesmake logstails service logsmake psshows running servicesmake send-dummy-mailsends a canned inbound email to the demo accountmake send-test-mail MAIL_TO=noah@example.com MAIL_SUBJECT="Hello"sends a custom inbound emailmake redis-boardprints the Redis Commander URLmake observabilityprints Grafana, Jaeger, Prometheus, and Redis URLs
Postlane includes a local SMTP listener for end-to-end inbound mail testing.
Default SMTP settings:
- Host:
localhost - Port:
2525 - Auth: none
Quick test:
make send-dummy-mailCustom test:
make send-test-mail MAIL_TO=admin@example.com MAIL_SUBJECT="Postlane SMTP Test"You can also use the Python helper directly:
uv run python backend/scripts/send_test_smtp.py --to admin@example.comDetailed instructions are available in SMTP_TESTING.md.
Postlane now includes Redis Commander for inspecting Redis content and activity.
Use it to:
- Browse keys
- Inspect values
- Verify TTLs
- Check what the application is storing in Redis during runtime
Open the dashboard at http://localhost:8081.
Postlane now includes a local observability stack built around OpenTelemetry.
Included components:
- OpenTelemetry instrumentation in the FastAPI backend
- SQLAlchemy and Redis tracing
- Manual tracing around SMTP ingestion and event publishing workflows
- OTEL Collector for telemetry ingestion and routing
- Jaeger for trace exploration
- Prometheus for metrics collection
- Grafana with preconfigured Prometheus and Jaeger data sources
- Provisioned Grafana dashboard for Postlane mail-processing and telemetry metrics
What you can inspect:
- API request traces
- Database and Redis spans
- SMTP message processing spans
- Event dispatcher activity
- Custom mail-processing metrics exported from the backend
Observability URLs:
- Grafana: http://localhost:3001
- Jaeger: http://localhost:16686
- Prometheus: http://localhost:9090
Grafana opens with a provisioned Postlane Observability dashboard that tracks SMTP volume, event publishing, collector intake, and mail-processing latency.
cd backend
uv sync
uv run python scripts/export_openapi.py
uv run backendcd frontend
pnpm install
pnpm generate:api
pnpm devFor local non-Docker development, you still need running Postgres and Redis instances.
- backend: FastAPI service, SMTP ingestion, API routes, and infrastructure code
- frontend: Next.js app, auth flows, mailbox UI, and admin UI
- docker-compose.yml: full local stack definition
- Makefile: common local workflow commands
- SMTP_TESTING.md: inbound SMTP usage guide
- ops: OTEL Collector, Prometheus, and Grafana provisioning
- Schema bootstrap currently happens on application startup
- No migration files are committed yet
- If you already have an older local Docker volume, recreate it after pulling schema-related changes
- The generated frontend API types depend on backend/openapi.json
- Add database migrations
- Add outbound email provider integration
- Add background worker metrics and queue visibility
Contributions are welcome.
If you want to contribute:
- open an issue for bugs, ideas, or architecture discussions
- fork the repository and open a PR
- keep PRs focused and clearly described
- update documentation when behavior changes
Please read CONTRIBUTING.md before opening a pull request.
This repository is distributed under a custom non-commercial source-available license.
Key rules:
- personal, educational, research, and non-commercial use is allowed
- commercial use is not allowed without prior written permission
- attribution to
Ankur Jaiswal,ankurjaiswalofficial@gmail.com, andhttps://github.com/ankurjaiswalofficialmust be preserved as described in the license
Read the full license here: LICENSE









