UNPKG

trash-cleaner

Version:

Finds and deletes trash email in the mailbox

419 lines (312 loc) 13.4 kB
# Trash Cleaner A program to delete trash emails based on keyword and label filters. ## Prerequisites [Node.js & npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) (Node 18+) ## Installation ### Via NPM ```bash npm install -g trash-cleaner ``` ### Via GitHub ``` git clone https://github.com/hasankhan/trash-cleaner cd trash-cleaner # If you want to try out the development version then 'git checkout dev' npm install -g ``` ## IMAP Configuration (Recommended) The simplest way to get started. Works with any email provider. ### Option 1: Secure Login (Recommended) Store credentials securely in your OS keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service): ```bash trash-cleaner init # Create config directory with sample files trash-cleaner login # Prompts for IMAP credentials, saves to OS keychain ``` For other services: ```bash trash-cleaner login -s gmail trash-cleaner login -s outlook ``` To remove stored credentials: ```bash trash-cleaner logout # Remove IMAP credentials from keychain trash-cleaner logout -s gmail ``` ### Option 2: File-based Configuration If your system doesn't have a keychain, credentials fall back to JSON files: 1. Run `trash-cleaner init` to create sample config files 2. Edit `config/imap.credentials.json` with your email settings: ```json { "host": "imap.gmail.com", "port": 993, "user": "your-email@gmail.com", "password": "your-app-password" } ``` ### App Passwords - **Gmail**: [Create an App Password](https://myaccount.google.com/apppasswords) (requires 2FA) - **Outlook**: Use your regular password or an app password - **Yahoo**: Account Security → Generate app password Common IMAP servers: | Provider | Host | Port | |----------|------|------| | Gmail | imap.gmail.com | 993 | | Outlook/Hotmail | outlook.office365.com | 993 | | Yahoo | imap.mail.yahoo.com | 993 | | iCloud | imap.mail.me.com | 993 | > **Note**: Some features (undo) are only available with the Gmail/Outlook API backends. Use `--service gmail` or `--service outlook` for those. ## Gmail API Configuration (Advanced) 1. Create a [Google Cloud Platform project with the API enabled](https://developers.google.com/workspace/guides/create-project). 2. Create [Authorization credentials for a desktop application](https://developers.google.com/workspace/guides/create-credentials) and download `gmail.credentials.json` file in the `config` directory. 3. Rename `keywords.json.sample` file in the `config` directory to `keywords.json` and update its contents. ## Outlook API Configuration (Advanced) 1. Register an application with the [Microsoft identity platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app). 2. Rename `outlook.credentials.json.sample` file in the `config` directory to `outlook.credentials.json` and update its contents. 3. Rename `keywords.json.sample` file in the `config` directory to `keywords.json` and update its contents. ## Get Started Initialize the config directory with sample files: ```bash trash-cleaner init [configDirPath] ``` This creates starter `keywords.json`, `imap.credentials.json`, `gmail.credentials.json`, and `outlook.credentials.json` files. Edit them to match your setup (see configuration sections above). ## Configuring Rules Rules live in `keywords.yaml` in your config directory (`~/.config/trash-cleaner/` by default). The file is a YAML list of rule objects. Each rule tells trash-cleaner which emails to match and what to do with them. > **Note:** JSON config files (`keywords.json`, etc.) are also supported for backward compatibility. If both exist, YAML takes priority. ### Rule Fields | Field | Required | Description | |-------|----------|-------------| | `value` | Yes | **Keyword rules**: A regex pattern to match. **LLM rules**: A natural language description. | | `title` | No | A human-readable name for the rule, shown when it matches. Defaults to `value` if omitted. | | `fields` | No | Comma-separated email fields to search: `from`, `subject`, `snippet`, `body`, or `*` for all. Default: `*` | | `labels` | No | Comma-separated folder/label names to scope the rule: `inbox`, `spam`, `trash`, `junk email`, or `*` for all. Default: `*` | | `action` | No | What to do with matches: `delete`, `archive`, or `mark-as-read`. Default: `delete` | | `type` | No | Rule type: `keyword` (regex, default) or `llm` (external LLM classification). | | `llm` | For LLM rules | Name of the LLM provider (must match a key in `llm-providers.yaml`). | ### Keyword Rules (Regex) Keyword rules use regular expressions to match email content. They are fast and precise. ```yaml - value: casino fields: "*" labels: "*" title: Casino spam - value: credit|loan fields: subject labels: spam, junk email title: Credit scams - value: newsletter fields: subject labels: inbox action: archive title: Newsletters - value: notification fields: subject labels: inbox action: mark-as-read ``` - **Delete all trash**: `value: "."` with `labels: trash, deleted items` — the `.` regex matches any character. - **Match multiple words**: `value: lucky|winner|prize` — uses regex `|` (OR) to match any of the words. - **Match emoji in subject**: `value: "[\\u{1F600}-\\u{1F64F}]"` — uses Unicode character ranges. - Matching is **case-insensitive** and **diacritic-insensitive** (e.g., "café" matches "cafe"). ### LLM Rules (External CLI) LLM rules invoke an external AI tool (Claude, Copilot, Ollama, etc.) to classify emails by meaning. Write a natural language description of what you want to match — the tool decides if each email fits. ```yaml - value: marketing or promotional email labels: "*" type: llm llm: claude action: archive title: Marketing emails - value: someone selling me something labels: inbox type: llm llm: claude ``` #### LLM Provider Configuration Create `llm-providers.yaml` in your config directory (`~/.config/trash-cleaner/`): ```yaml claude: command: claude args: ["--print", "{{prompt}}"] copilot: command: copilot-cli args: ["-p", "{{prompt}}"] ollama: command: ollama args: ["run", "llama3", "{{prompt}}"] ``` Each provider needs: - `command` — the CLI executable name (must be in your PATH) - `args` — arguments array with `{{prompt}}` as a placeholder for the rendered prompt - `prompt` (optional) — custom prompt template; defaults to asking "does this email match?" with true/false response The `{{prompt}}` placeholder in args is replaced with the full prompt containing the rule description and email content. The tool must respond with "true" or "false". - LLM rules are slower than keyword rules (network call per email) but can catch things regex can't. - No data is sent to trash-cleaner servers — classification goes through your configured CLI tool. - Run `trash-cleaner init` to create a sample `llm-providers.yaml`. ### Scoping Rules with Labels and Fields Use `labels` to limit which folders a rule applies to: - `"labels": "inbox"`only match emails in your inbox - `"labels": "spam,junk email"`only match emails in spam/junk folders - `"labels": "trash,deleted items"`only match emails in trash - `"labels": "*"` — match emails in any folder Use `fields` to limit which parts of an email are searched (keyword rules only): - `"fields": "subject"`only search the subject line - `"fields": "subject,body"` — search subject and body - `"fields": "*"` — search all fields (from, subject, snippet, body) ### Example Configuration ```yaml - value: "." fields: "*" labels: trash, deleted items title: Clean trash folder - value: casino|lottery|winner fields: "*" labels: spam, junk email title: Gambling spam - value: unsubscribe fields: body labels: inbox action: archive title: Bulk mail - value: notification fields: subject labels: inbox action: mark-as-read - value: marketing or promotional email labels: inbox type: llm llm: claude action: archive title: Marketing emails ``` Rules are evaluated in order — the **first matching rule wins**. Place more specific rules before general ones. To get the list of all parameters type `trash-cleaner -h` ``` Usage: trash-cleaner [options] Options: -V, --version output the version number -r, --reconfig reconfigures the auth for a service -t, --dry-run perform a dry-run cleanup without deleting the emails -d, --debug output extra debugging info -l, --launch launch the auth url in the browser -q, --quiet suppress verbose output (for cron/scripts) -i, --interactive preview matches and confirm before acting -f, --format <format> output format: text or html (default: "text") -m, --min-age <days> only process emails older than N days -c, --configDirPath <path> the path to config directory (default: "config") -s, --service <service> the email service to use (choices: "imap", "gmail", "outlook", default: "imap") -a, --account <name> the account name for multi-account support (default: "default") -h, --help display help for command ``` ## Commands ### `trash-cleaner init [configDirPath]` Creates a config directory with sample configuration files. ### `trash-cleaner list-rules [configDirPath]` Displays all active keyword rules and allowlist patterns. ### `trash-cleaner validate [configDirPath]` Validates configuration files and reports any issues. ### `trash-cleaner undo [configDirPath]` Shows the last batch of processed emails and offers to restore them. ### `trash-cleaner login [-s service] [-a account]` Prompts for credentials and saves them securely in the OS keychain. Supports `--service imap` (default), `gmail`, or `outlook`. ### `trash-cleaner logout [-s service] [-a account]` Removes stored credentials from the OS keychain. ## Features ### Multi-Account Support Run against different accounts using the `-a` flag: ```bash trash-cleaner -s gmail -a work trash-cleaner -s gmail -a personal ``` Each account stores its own credentials (e.g., `gmail.credentials.work.json`). ### Sender Allowlist Create `config/allowlist.json` to protect specific senders from any actions: ```json [ "boss@company\\.com", ".*@important\\.org" ] ``` Patterns are case-insensitive regular expressions matched against the sender. ### Interactive Mode Use `--interactive` to preview matched emails before taking action: ```bash trash-cleaner --interactive ``` ### Quiet Mode Use `--quiet` for cron jobs or scripts — suppresses spinner and verbose output: ```bash trash-cleaner --quiet ``` ### HTML Reports Generate an HTML report instead of console output: ```bash trash-cleaner --format html ``` This creates a timestamped HTML file in the current directory. ### Retry Logic API calls automatically retry with exponential backoff on transient failures (429, 5xx, network errors). ### Email Age Filter Only process emails older than a certain number of days: ```bash trash-cleaner --min-age 7 ``` ### Config Validation Check your configuration files for errors before running: ```bash trash-cleaner validate ``` ### Undo After processing, actions are logged. Use `trash-cleaner undo` to restore the last batch: ```bash trash-cleaner undo ``` ## Scheduling To run trash-cleaner automatically on a schedule: ### Linux/macOS (cron) Run `crontab -e` and add a line. For example, to run every hour: ``` 0 * * * * /usr/local/bin/trash-cleaner --quiet -c /path/to/config ``` ### macOS (launchd) Create `~/Library/LaunchAgents/com.trash-cleaner.plist`: ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.trash-cleaner</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/trash-cleaner</string> <string>--quiet</string> <string>-c</string> <string>/path/to/config</string> </array> <key>StartInterval</key> <integer>3600</integer> </dict> </plist> ``` Load it with: `launchctl load ~/Library/LaunchAgents/com.trash-cleaner.plist` ### Windows (Task Scheduler) ```powershell schtasks /create /tn "TrashCleaner" /tr "trash-cleaner --quiet -c C:\path\to\config" /sc hourly ``` ## Development ```bash npm install # Install dependencies npm test # Run tests npm run lint # Run ESLint npm run typecheck # Run JSDoc type checking npm run coverage # Generate coverage report ``` ## Releasing Releases are automated via GitHub Actions. To publish a new version: ```bash npm version patch # or minor, or major git push --follow-tags ``` This triggers the publish workflow which runs tests and publishes to npm. Requires `NPM_TOKEN` secret configured in the repository settings.