this a project for email filtering
Find a file
lorentz 5af3fef37d Add REST API, DB user management, and API documentation
Adds a JSON REST API at /api/v1/ (Bearer token auth via API_KEYS env var)
exposing the full pipeline — email processing, log querying, sender profiles,
purge rules, whitelist, and analysis — for external consumers like OpenClaw.

Adds a /dbusers web UI for generating PostgreSQL roles with read_only,
modify, or full permission levels; credentials shown once and never stored.

Includes Alembic migration 0005 for the db_api_users tracking table and
API.md with full endpoint documentation and integration examples.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 14:47:39 -04:00
howl Add REST API, DB user management, and API documentation 2026-04-02 14:47:39 -04:00
migrations Add REST API, DB user management, and API documentation 2026-04-02 14:47:39 -04:00
tests Initial commit: Howl M365 email management daemon 2026-04-01 16:02:24 -04:00
.env.example Initial commit: Howl M365 email management daemon 2026-04-01 16:02:24 -04:00
.gitignore Initial commit: Howl M365 email management daemon 2026-04-01 16:02:24 -04:00
alembic.ini Initial commit: Howl M365 email management daemon 2026-04-01 16:02:24 -04:00
API.md Add REST API, DB user management, and API documentation 2026-04-02 14:47:39 -04:00
NEXT_STEPS.md Initial commit: Howl M365 email management daemon 2026-04-01 16:02:24 -04:00
pyproject.toml Add web UI, sender profiles, purge rules, and infosec action 2026-04-02 14:12:56 -04:00
README.md Initial commit: Howl M365 email management daemon 2026-04-01 16:02:24 -04:00
SCHEMA.md Add web UI, sender profiles, purge rules, and infosec action 2026-04-02 14:12:56 -04:00
seed_from_pulse.py Add web UI, sender profiles, purge rules, and infosec action 2026-04-02 14:12:56 -04:00
SETUP.md Initial commit: Howl M365 email management daemon 2026-04-01 16:02:24 -04:00

Howl

An M365 email management daemon that uses the Microsoft Graph API and Claude AI to automatically classify and route incoming email based on your customer, vendor, and whitelist database.

How it works

Inbox (M365)
    │
    ▼
Graph API polls for unread mail
    │
    ▼
PostgreSQL lookup — is the sender a customer, vendor, or trusted contact?
    │
    ▼
Claude (LLM) classifies the email using sender context + body content
    │
    ▼
Business rules applied (whitelist always wins, low-confidence → hold for review)
    │
    ▼
Action taken: move to folder / flag / escalate with notification
    │
    ▼
email_log table records every decision for audit and retry

Features

  • Supports both shared mailboxes (app-only, no user login) and personal mailboxes (delegated device-code auth)
  • No emails are ever deleted — only moved, flagged, or escalated
  • Dry-run mode — analyze and log without touching any email
  • Idempotent — safe to restart; already-processed messages are skipped
  • Automatic retry — failed messages are retried on the next poll cycle
  • Full audit log — every classification, confidence score, and action is stored in PostgreSQL

Folder routing

Sender type LLM classification Action
Customer Inquiry / correspondence Move to Customers folder
Vendor Invoice / notification Move to Vendors folder
Whitelist Trusted contact Mark read, stay in Inbox
Any Urgent / escalation Move to Escalate + webhook notification
Any Uncertain (low confidence) Move to Needs Review
Unknown Spam / newsletter Move to Junk Email

Quick start

# 1. Create and activate a virtual environment
python3 -m venv .venv && source .venv/bin/activate

# 2. Install dependencies
pip install -e ".[dev]"

# 3. Configure environment
cp .env.example .env
# Edit .env with your Azure, Anthropic, and PostgreSQL credentials

# 4. Run database migrations
alembic upgrade head

# 5. Test with dry-run (no email mutations)
howl dry-run --limit 10

# 6. Start the daemon
howl run

CLI commands

Command Description
howl run Start the daemon (blocking, polls on schedule)
howl dry-run [--limit N] Classify up to N emails, log results, take no action
howl status [--limit N] Display recent email_log entries in a table

Project structure

howl/
├── howl/
│   ├── config.py           # All configuration (pydantic-settings + .env)
│   ├── main.py             # CLI entry point (Typer)
│   ├── logging_config.py   # structlog setup (JSON or text)
│   ├── db/
│   │   ├── engine.py       # Async SQLAlchemy engine
│   │   ├── models.py       # ORM models
│   │   └── queries.py      # lookup_sender(), email log helpers
│   ├── graph/
│   │   ├── auth.py         # MSAL token provider (client-credentials or delegated)
│   │   └── client.py       # Graph API: list, read, move, flag messages
│   ├── llm/
│   │   ├── client.py       # Anthropic SDK wrapper with retry
│   │   ├── prompts.py      # Prompt builder (system prompt + per-email user turn)
│   │   └── schemas.py      # EmailClassification model + tool definition
│   ├── pipeline/
│   │   ├── processor.py    # EmailProcessor — orchestrates the full pipeline
│   │   ├── classifier.py   # Business rule overrides on LLM output
│   │   └── actions.py      # ActionExecutor — Graph mutations + webhook
│   └── daemon/
│       └── scheduler.py    # APScheduler poll loop + graceful shutdown
├── migrations/             # Alembic database migrations
├── tests/                  # Unit and integration tests
├── .env.example            # Configuration template
├── SETUP.md                # Detailed setup and configuration guide
└── NEXT_STEPS.md           # Roadmap and future improvements

Running tests

pytest tests/ -q                          # All tests (no external services needed)
pytest tests/ -q -m "not integration"    # Unit tests only (default)
pytest tests/ -q -m integration          # Requires real M365 + Anthropic credentials

Requirements

  • Python 3.11+
  • PostgreSQL 14+
  • Microsoft Azure app registration with Mail.Read + Mail.ReadWrite permissions
  • Anthropic API key