A tool that generates mail filtering rules by learning from how mail is already sorted into IMAP folders. It connects to an IMAP server, scans folders to see which senders ended up where, and produces a Sieve script (or Gmail filter XML) that replicates that sorting automatically.
- Connects to your IMAP account and lists all folders (skipping Inbox, Sent, Drafts, Trash, etc.)
- Scans each folder's messages to build a map of sender domains/addresses to folders
- Resolves conflicts (a domain appearing in multiple folders) by picking the folder with the most messages
- Generates filtering rules — by domain for most senders, by full address for mail providers (Gmail, Outlook, etc.)
For mail domains like gmail.com, matching is done on the full address rather than the domain, since the domain itself isn't meaningful.
Run with no arguments (or --gui) to launch the GUI:
python mailsort.py
python mailsort.py --user you@example.com
python mailsort.py --user you@example.com -o mailsort.sieve
python mailsort.py --user you@example.com --format gmail -o filters.xml
python mailsort.py --user you@example.com --upload
The password can be provided via --password, the IMAP_PASSWORD environment variable, or an interactive prompt.
| Flag | Description |
|---|---|
--host |
IMAP host (default: imap.migadu.com) |
--port |
IMAP port (default: 993) |
--user |
IMAP username (email) |
--max-messages N |
Limit messages scanned per folder (0 = all) |
--min-count N |
Minimum messages before creating a rule (default: 2) |
--format sieve|gmail |
Output format (default: sieve) |
-o FILE |
Write output to file instead of stdout |
-i / --interactive |
Review rules folder-by-folder before generating |
--no-humans |
Filter out likely-human senders, keeping only newsletters/services |
--dry-run |
Show folder summary without generating rules |
--dump-json |
Output sender mapping as JSON |
--upload |
Upload and activate via ManageSieve |
--script-name |
Sieve script name on server (default: mailsort) |
The --no-humans flag uses "heuristics" to classify senders as human or automated. It looks at local-part patterns (e.g. noreply@), subdomains (e.g. mail.), display names, and other signals. This is useful if you only want rules for newsletters and service emails, not personal contacts.
With --upload, the generated Sieve script is uploaded directly to the mail server via ManageSieve and activated. This requires the sievelib package:
pip install sievelib
The GUI provides a tabbed interface for connecting, scanning, reviewing rules (with per-domain/address checkboxes), and generating or uploading the output. It launches by default when run without arguments.
- Python 3.6+
- No external packages required for core functionality
sievelibonly needed for ManageSieve upload (--upload)