Skip to content

Latest commit

 

History

History
149 lines (109 loc) · 6.43 KB

File metadata and controls

149 lines (109 loc) · 6.43 KB

AreYouSievious

License: MIT

Self-hosted Sieve filter management for people who'd rather not write Sieve by hand.

Visual rule builder + raw editor + ManageSieve protocol. No database, no stored credentials. Your rules live on your mail server where they belong.

Live instance: areyousievious.com

Screenshots

Login

Dashboard

Rule Editor

Features

  • Visual rule builder — create filters with a point-and-click UI
  • Raw Sieve editor — full control when you need it
  • Import/export — backup and restore .sieve files
  • Folder management — browse and create IMAP folders
  • Zero persistence — no database, no stored passwords, credentials live in memory for 30 minutes max
  • Self-hostable — one Docker container, no external dependencies
  • Dark mode — because obviously

Quick Start (Docker)

git clone https://github.com/derekslenk/AreYouSievious.git
cd AreYouSievious
docker compose up -d --build

Or run the published image:

docker run -d -p 8091:8091 \
  -e AYS_IMAP_HOST=mail.example.com \
  -e AYS_IMAP_USER=you@example.com \
  ghcr.io/derekslenk/areyousievious:latest

Open http://localhost:8091 and log in with your IMAP credentials.

Environment Variables

Variable Default Description
AYS_ENV prod dev enables /docs, /redoc, /openapi.json. Anything else (including unset) returns 404 on those URLs — production deploys should leave it unset to avoid leaking the API surface (Sec M-5).
AYS_MAX_BODY_BYTES 1048576 (1 MiB) Maximum accepted request body size. Larger requests get HTTP 413 from middleware before reaching any route (CWE-770). Both Content-Length and the actual streamed body are checked.
AYS_CORS_ORIGINS https://areyousievious.com Comma-separated allowed origins
AYS_SECURE_COOKIES (unset) Set to true when behind HTTPS reverse proxy
AYS_SESSION_IDLE_TIMEOUT 1800 (30 min) Seconds of inactivity after which a session stops being accepted — immediately and always. Its credentials are freed a little later, by the periodic sweep, which runs when a request touches the store and at most once a minute; a session nobody returns to therefore stays resident until some other request arrives, as there is no background sweeper. Also the max_age on the session and CSRF cookies, so the browser hint and the server's enforcement cannot drift apart.
AYS_SESSION_MAX_LIFETIME 28800 (8 h) Absolute cap counted from login and NOT refreshed by use. Without it the timeout was idle-only, so a client polling /api/auth/status kept a plaintext password resident for as long as it cared to poll.
AYS_IMAP_INSECURE (unset) ⚠️ Testing only. 1 / true / yes disables outbound IMAP TLS chain + hostname verification (for self-signed mail servers). Leaving this unset is mandatory in production — without it, an on-path attacker can MITM the IMAP login and steal credentials (CWE-295).
AYS_TRUSTED_PROXIES (unset) CSV of CIDRs that may set X-Forwarded-For / X-Real-IP (e.g. 127.0.0.1/32,10.0.0.0/8). When unset, those headers are ignored and the rate limiter uses the direct peer — right when the app faces clients directly, since any caller could otherwise spoof the headers to bypass throttling (CWE-348). Behind a reverse proxy the direct peer is the proxy for every request, so leaving it unset gives all clients one shared rate-limit bucket and five failed logins lock out everyone. The app warns at startup when it is empty; see docs/DEPLOY.md.
AYS_IMAP_TIMEOUT 10 Seconds before an outbound IMAP connect or read aborts.
AYS_SIEVE_CONNECT_TIMEOUT 10 Seconds before an outbound ManageSieve TCP connect aborts. A blackhole mail server would otherwise pin the threadpool worker for the OS default (~2 min).
AYS_SIEVE_IO_TIMEOUT 30 Seconds before an outbound ManageSieve read or write aborts on a connected socket.

Every variable above is read exactly once, at startup, into the frozen Settings value in backend/config.py — that module is the single list of what this app can be configured with. Values are floored where a zero would mean "wait forever", and an unparseable value falls back to the default rather than failing the process.

Quick Start (Manual)

# Frontend
cd frontend && npm install && npm run build

# Backend
cd backend && pip install -r requirements.txt
python app.py --port 8091 --static ../frontend/dist

Requirements

Your mail server needs:

  • IMAP (port 993, SSL) — for authentication and folder listing
  • ManageSieve (port 4190) — for filter management (RFC 5804)

Most self-hosted mail servers support this out of the box (Dovecot, Mailcow, Mail-in-a-Box, etc).

Stack

  • Frontend: Svelte + Vite
  • Backend: Python + FastAPI
  • Protocol: ManageSieve (RFC 5804) + IMAP
  • Database: None. State lives on your mail server.

Production Deployment

For public-facing deployments, put it behind a reverse proxy with TLS:

server {
    listen 443 ssl;
    server_name your-domain.com;

    # ... SSL config ...

    location / {
        proxy_pass http://127.0.0.1:8091;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Bind Docker to localhost only:

ports:
  - "127.0.0.1:8091:8091"

Set AYS_SECURE_COOKIES=true and AYS_CORS_ORIGINS=https://your-domain.com.

Security

  • Credentials are held in memory only, never written to disk
  • Sessions expire after 30 minutes of inactivity
  • SSRF protection prevents connections to private/internal networks
  • Rate limiting on login (5 attempts per 5 minutes per IP)
  • HttpOnly, Secure, SameSite=Strict session cookies

See the privacy policy for the full story.

Docs

License

MIT