QDG Knowledge Base Read-only viewer QWebHub
workflow

Development & Deployment Workflow

Version 1 · Initial workflow page covering local dev setup, running locally, building the exe/service, and the third run_api.cmd deployment path

SmartMail Development & Deployment Workflow

Local development setup

  1. python -m venv .venv then activate it.
  2. pip install -r requirements.txt — note this file does not include pyinstaller, pywin32, or waitress, even though run.py/service_wrapper.py/run_api.cmd all need them and the .spec files need PyInstaller/pywin32. Install separately:
    pip install pyinstaller pywin32 waitress
    
  3. Create/fill an env file under env/ — config/load_config.py picks env/.env.<APP_ENV> (default development; .development/.staging/.production variants all exist as files already). Required keys include CLIENT_ID, TENANT_ID, CLIENT_SECRET, REDIRECT_URI, SCOPES, MONGO_URI, MONGO_DB, DB_BACKEND, OPENAI_API_KEY, OPENAI_MODEL_SUMMARY/_EXTRACT/_REPLY, plus webhook/logging/Redis settings.
  4. Review config/config.ini for non-secret per-environment settings ([default], [dev], [staging], [prod] sections: host/port, log level, Graph base URL/scopes, feature flags). Note config/schema.json is currently an empty file and validates nothing.
  5. Validate config before going further:
    python scripts/check_config.py
    
    Checks TENANT_ID/CLIENT_ID/GRAPH_SCOPES are set (exits 1 if not) and warns if ENABLE_GPT=true but OPENAI_API_KEY is empty.
  6. Initialize the database:
    python -m app.main init-db
    
  7. Authenticate against Microsoft 365 (device-code/interactive):
    python -m app.main login
    

See Database for what step 6 actually creates, and Architecture §4 for why step 7's token cache location matters (app/auth.py uses a CWD-relative cache.bin, not app/config.TOKEN_CACHE_PATH).

Running locally

Two different entry points, on two different ports:

  • python run.py — emulates the packaged desktop exe: starts waitress on 0.0.0.0:5001, opens the browser at /outlook. python run.py login runs just the auth flow and exits.
  • python -m app.main web or python -m app.main dashboard (or running app/main.py with no subcommand) — starts the Flask dev server directly on port 5002 instead.

Pick run.py to test the shipped experience; use the app.main CLI entry for quick iteration or any of its other subcommands (inbox, create-draft, gpt-classify, etc. — see CLI Quick Reference).

Building the desktop executable

pyinstaller SmartMail.spec

Entry point run.py; bundles only env/.env.development as data (everything else resolved via normal import discovery). Produces dist/SmartMail.exe (console app, one-file, UPX-compressed).

Building / installing the Windows service

pyinstaller SmartMail_Service.spec

Entry point service_wrapper.py; bundles env/.env.development and the whole app/ directory, plus explicit pywin32 hidden-imports (win32timezone, win32service, win32serviceutil, win32event, servicemanager). Produces dist/SmartMailService.exe.

Install/manage (run as Administrator), standard win32serviceutil conventions:

SmartMailService.exe install
SmartMailService.exe start
SmartMailService.exe stop
SmartMailService.exe remove

Service name SmartMailService, listens on 0.0.0.0:5001 via waitress, logs to service_debug.log (overwritten on every start — no rotation). Unlike the desktop exe, the service does not check for a valid token at startup — it will start and simply serve 401s from Graph-backed routes until login has been run separately.

A third deployment path: run_api.cmd + wsgi.py

wsgi.py is a plain WSGI entrypoint (application = app), not referenced by either .spec file. run_api.cmd uses it directly:

D:\GITHUB\SmartMail\.venv\Scripts\waitress-serve.exe --listen=124.43.18.139:5002 wsgi:application

appending logs to logs\api.log. This is a plain batch launcher (not a registered Windows service) bound to a specific internal IP on port 5002 — presumably intended for a server host where it's started manually or via a scheduled task. ⚠ The script's hardcoded path (D:\GITHUB\SmartMail) doesn't match this checkout's actual path (D:\SmartMail) — update it before relying on this script, or it will fail to find the venv/working directory.

What's gitignored (must be recreated locally, not present on a fresh clone)

Per .gitignore: app/cache.bin, .env, .venv, __pycache__/, *.pyc, *.bin, *.log, logs, *.db//smartmail.db, /token_cache.json, build, *.exe. A fresh clone needs steps 1–7 above run from scratch; don't expect smartmail.db, log files, or the token cache to already exist.

Not found in the repo

No CI configuration (.github/workflows, Azure Pipelines, etc.) was found — builds and deploys described above are run manually today.

Updated by Claude on Aug. 12, 2026, 9:09 a.m. · Task: updatewiki create project documentation (Workflow)