Contributing
SeeSee is open source and contributions are welcome — whether that’s a bug fix, a new integration example, or just fixing a typo. This guide covers how to set up a development environment and the project’s coding standards.
Development setup
Prerequisites
- Python 3.12+
- pip
- Git
Clone and install
git clone https://github.com/brandonjp/seesee-email.gitcd seesee-emailpython -m venv .venvsource .venv/bin/activate # bash / zsh# source .venv/bin/activate.fish # fishpip install -e ".[dev]"Run the development server
# Starts both HTTP (8080) and SMTP (2525) serverspython -m seesee
# With debug loggingSEESEE_ADMIN_PASSWORD=dev SEESEE_LOG_LEVEL=debug python -m seeseeRun tests
pytest # Full test suitepytest -x # Stop on first failurepytest tests/test_ingest.py # Specific test filepytest -k "test_search" # Tests matching patternLint and format
ruff check . # Check for lint errorsruff format . # Auto-format coderuff format --check . # Check formatting without changingBuild Docker image locally
docker build -t seesee:dev .docker run -p 8080:8080 -p 2525:2525 -e SEESEE_ADMIN_PASSWORD=dev seesee:devBuild docs site locally
The docs site is independent from the Python app — it uses Node.js, not the Python venv.
cd docsnpm installnpm run dev # Dev server at localhost:4321npm run build # Production build to docs/distProject structure
seesee-email/├── seesee/ # Python application package│ ├── __init__.py # Version number (__version__)│ ├── __main__.py # Entry point (python -m seesee)│ ├── main.py # FastAPI app, lifespan, route registration│ ├── config.py # Settings with SEESEE_* env var mapping│ ├── database.py # SQLite + FTS5 schema, queries, migrations│ ├── models.py # Pydantic request/response models│ ├── auth.py # API key hashing, session management│ ├── retention.py # Cleanup scheduler, retention enforcement│ ├── smtp_server.py # aiosmtpd handler, MIME parsing│ ├── routes/│ │ ├── ingest.py # POST /api/v1/log, /api/v1/log/batch│ │ ├── emails.py # GET/DELETE /api/v1/emails, /{id}, /{id}/preview│ │ ├── apps.py # App CRUD + key rotation│ │ ├── stats.py # GET /api/v1/stats│ │ ├── export.py # GET /api/v1/export (GDPR data export)│ │ ├── webhooks.py # POST /api/v1/webhooks/{provider}│ │ ├── admin.py # POST /api/v1/admin/cleanup, debug/persistence│ │ └── ui.py # Web UI page routes│ ├── templates/ # Jinja2 HTML templates│ └── static/ # CSS, JS, favicon├── docs/ # Astro Starlight docs site├── examples/ # Integration snippets (PHP, Python, JS, cURL)├── tests/ # pytest test suite├── Dockerfile # Multi-stage production build├── docker-compose.yml # Coolify-compatible deployment├── pyproject.toml # Package config and dependencies└── .github/workflows/ # CI/CD (Docker → GHCR, docs → GitHub Pages)Code style
- Formatter: Ruff (line length 100)
- Linter: Ruff (PEP 8 enforcement)
- Type hints: Required on all function signatures
- Imports: Sorted by Ruff (isort-compatible)
- Naming:
snake_casefor functions/variables,PascalCasefor classes,UPPER_CASEfor constants - Docstrings: Google format for public functions and classes
- Comments: Explain “why”, not “what”
Testing
SeeSee uses pytest with pytest-asyncio for async test support.
Priority areas to test:
- Ingest endpoints — validation, auth, storage modes
- Search and filter queries — FTS5 behavior, pagination
- Retention logic — count limits, age limits, per-app overrides
- Auth — API key verification, session management
- SMTP parsing — MIME extraction
Test patterns:
- API tests use httpx
AsyncClientwith FastAPI’sTestClient - Database tests use temporary SQLite (in-memory or
tmp_path) - SMTP tests use mock fixtures
Git workflow
- Feature branches required — never commit directly to
main - Branch naming:
feature/,fix/,refactor/,docs/,chore/, orphase-X.X/ - Commit format: Conventional commits:
feat:— new featurefix:— bug fixdocs:— documentationchore:— maintenancerefactor:— code restructuringtest:— test additions
Before merging to main
-
pytestpasses -
ruff check .passes -
ruff format --check .passes - Version bumped if code changed
- CHANGELOG.md updated
- Documentation updated if behavior changed
Version management
SeeSee uses Semantic Versioning (MAJOR.MINOR.PATCH):
- Patch: Bug fixes, minor improvements
- Minor: New features, new endpoints, new UI pages
- Major: Breaking API changes, breaking config changes
The canonical version source is seesee/__init__.py. Also update pyproject.toml and CHANGELOG.md when bumping.
Roadmap
See ROADMAP.md in the repository for the current development phases and planned features.