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
- 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
.sievefiles - 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
git clone https://github.com/derekslenk/AreYouSievious.git
cd AreYouSievious
docker compose up -d --buildOr 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:latestOpen http://localhost:8091 and log in with your IMAP credentials.
| 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) | 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.
# Frontend
cd frontend && npm install && npm run build
# Backend
cd backend && pip install -r requirements.txt
python app.py --port 8091 --static ../frontend/distYour 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).
- Frontend: Svelte + Vite
- Backend: Python + FastAPI
- Protocol: ManageSieve (RFC 5804) + IMAP
- Database: None. State lives on your mail server.
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.
- 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.


