diff --git a/CHANGELOG.md b/CHANGELOG.md index 68d9274..65cb495 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,22 +5,56 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.0.11] - 2025-10-20 + +Summary: Added[7], Changed[7], Chore[12], Continuous Integration[5], Documentation[24], Fixed[7], Testing[12] + +### Added + + - ✨ feat(test): add junit report + - ✨ feat(ci): introduce nextest test runner + - ✨ feat(retention): implement retention policy configuration + - ✨ feat(error): add invalid message age error + - ✨ feat(retention): enhance message age with parsing and validation + - ✨ feat(retention): introduce message age specification + - ✨ feat(retention): enhance retention policy configuration + +### Fixed + + - 🐛 fix(rule_processor): correct spelling of "behaviour" + - ✅ fix(message-list): improve idioms (avoid redundant clone, extend labels, safer message extraction) + - ✅ fix(clippy): move tests module to file end to satisfy items_after_test_module lint + - 🐛 fix(retention): fix debug string formatting in retention struct + - 🐛 fix(cli): correct error mapping in add_cli + - 🐛 fix(rules): handle message age creation error + - 🐛 fix(build): correct readme generation script + +### Changed + + - ♻️ refactor: remove redundant credential module + - ♻️ refactor(message-list): introduce GmailService abstraction and refactor to use it; fix borrows and lifetimes + - ♻️ refactor(message-list): extract helper to append messages from ListMessagesResponse and add unit test + - ♻️ refactor(rule_processor): extract process_label and add internal ops trait for unit testing + - ♻️ refactor(rule_processor): add TRASH_LABEL, correct Gmail scopes, early returns, and improve idioms + - refactor(rules): replace unwrap() with explicit error handling and propagate errors safely + - refactor(rules): apply idiomatic patterns and resolve clippy warnings + ## [0.0.10] - 2025-10-16 -Summary: Added[11], Changed[15], Chore[11], Fixed[3] +Summary: Added[11], Changed[15], Chore[12], Fixed[3] ### Added - ✨ feat(cli): add default subcommand for rule execution - ✨ feat(config): implement config builder pattern for ClientConfig + - ✨ feat(cli): load configurations from toml file + - ✨ feat(client_config): add config root parsing with regex - ✨ feat(utils): add test utils module - ✨ feat(deps): add lazy-regex crate - ✨ feat(dependencies): add lazy-regex dependency - ✨ feat(config): add ConfigRoot enum for flexible path handling - ✨ feat(core): add client config - ✨ feat(config): introduce client configuration - - ✨ feat(cli): load configurations from toml file - - ✨ feat(client_config): add config root parsing with regex - ✨ feat(cli): add config file support ### Fixed @@ -32,12 +66,12 @@ Summary: Added[11], Changed[15], Chore[11], Fixed[3] ### Changed - ♻️ refactor(cli): extract action execution into a function - - ♻️ refactor(cli): extract rule execution to separate function - ♻️ refactor(cli): rename get_config to get_rules + - ♻️ refactor(cli): extract rule execution to separate function - ♻️ refactor(config): improve ConfigRoot to handle different root types + - ♻️ refactor(utils): improve config directory creation - ♻️ refactor(cli): use ClientConfig struct for gmail client - ♻️ refactor(gmail): use client config for gmail client - - ♻️ refactor(utils): improve config directory creation - ♻️ refactor(rules): remove credentials config - ♻️ refactor(cli): remove config from run args - ♻️ refactor(eol_rule): improve labels handling @@ -440,7 +474,8 @@ Summary: Added[4], Build[3], Chore[21], Continuous Integration[4], Documentation - ✨ feat(vscode): add custom dictionary entry for ltex - ✨ feat(project): add initial Cargo.toml for cull-gmail tool -[Unreleased]: https://github.com/jerus-org/cull-gmail/compare/v0.0.9...HEAD +[Unreleased]: https://github.com/jerus-org/cull-gmail/compare/v0.0.10...HEAD +[0.0.10]: https://github.com/jerus-org/cull-gmail/compare/v0.0.9...v0.0.10 [0.0.9]: https://github.com/jerus-org/cull-gmail/compare/v0.0.8...v0.0.9 [0.0.8]: https://github.com/jerus-org/cull-gmail/compare/v0.0.7...v0.0.8 [0.0.7]: https://github.com/jerus-org/cull-gmail/compare/v0.0.6...v0.0.7 diff --git a/Cargo.lock b/Cargo.lock index 4dcdcea..895109e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -370,7 +370,7 @@ dependencies = [ [[package]] name = "cull-gmail" -version = "0.0.10" +version = "0.0.11" dependencies = [ "chrono", "clap", diff --git a/Cargo.toml b/Cargo.toml index 5c938e9..50844f2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cull-gmail" description = "Cull emails from a gmail account using the gmail API" -version = "0.0.10" +version = "0.0.11" authors = ["Jeremiah Russell "] edition = "2024" rust-version = "1.88" diff --git a/PRLOG.md b/PRLOG.md index dad2004..9ff9c86 100644 --- a/PRLOG.md +++ b/PRLOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.0.11] - 2025-10-20 ### Added @@ -255,7 +255,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#84]: https://github.com/jerus-org/cull-gmail/pull/84 [#85]: https://github.com/jerus-org/cull-gmail/pull/85 [#86]: https://github.com/jerus-org/cull-gmail/pull/86 -[Unreleased]: https://github.com/jerus-org/cull-gmail/compare/v0.0.10...HEAD +[0.0.11]: https://github.com/jerus-org/cull-gmail/compare/v0.0.10...v0.0.11 [0.0.10]: https://github.com/jerus-org/cull-gmail/compare/v0.0.9...v0.0.10 [0.0.9]: https://github.com/jerus-org/cull-gmail/compare/v0.0.8...v0.0.9 [0.0.8]: https://github.com/jerus-org/cull-gmail/compare/v0.0.7...v0.0.8 diff --git a/README.md b/README.md index 5a0b533..81b26b8 100644 --- a/README.md +++ b/README.md @@ -31,46 +31,945 @@ The `cull-gmail` provides a software library and command line program to enable ## Main Features -- login to get authorization -- backup the mailbox -- filtered lists of the contents -- move email matching a filtered list to trash -## cull-gmail Library Documentation +- list labels and messages to aid planning rules +- configure the rules list +- run the rules list +- run the rules list be default +- configure api client by file or environment variables +### Running the optional Gmail integration test -The `cull-gmail` library provides types to enable the culling of emails using the Gmail API including the following steps: -- login to get authorization -- backup the mailbox -- filtered lists of the contents -- move email matching a filtered list to trash +An optional, ignored integration test exercises the Gmail API end-to-end (networked). It is ignored by default and will not run in CI. -### Installation +Steps to run locally: -Add the library to your program's `Cargo.toml` using `cargo add`: +1. Ensure you have valid OAuth client credentials configured for the library (see `ClientConfig::builder()` usage in docs). +2. Run the test explicitly with the ignored flag: ```bash -$ cargo add cull-gmail +cargo test --test gmail_message_list_integration -- --ignored ``` -Or by configuring the dependencies manually in `Cargo.toml`: +Notes: +- The test performs a lightweight listing (max 10 messages) and should be safe, but it still uses your Gmail account. +- Do not run this in CI; it is intended only for local verification. -```toml -[dependencies] -cull-gmail = "0.0.10" -``` +# cull-gmail CLI Documentation -## cull-gmail CLI +A command-line program for managing Gmail messages using the Gmail API. The tool provides subcommands for label querying, message querying, rule configuration, and rule execution to trash/delete messages with built-in safety features like dry-run mode. -A command line program to cull emails from Gmail using the Gmail API. The tool has sub-commands to for authorization, planning and executing the move of select email to the Gmail trash folder from which they will be automatically deleted after thirty days. +## Installation -### Installation - -Install cull-gmail using Cargo: +### From Crates.io ```bash cargo install cull-gmail ``` +### From Source + +```bash +git clone https://github.com/jerus-org/cull-gmail.git +cd cull-gmail +cargo install --path . +``` + +### Verify Installation + +```bash +cull-gmail --version +``` + +## Authentication Setup + +### 1. Google Cloud Console Setup + +1. Visit the [Google Cloud Console](https://console.cloud.google.com/) +2. Create a new project or select an existing one +3. Enable the Gmail API: + - Go to "APIs & Services" > "Library" + - Search for "Gmail API" and enable it +4. Create OAuth2 credentials: + - Go to "APIs & Services" > "Credentials" + - Click "Create Credentials" > "OAuth client ID" + - Choose "Desktop application" + - Download the JSON file + +### 2. Configure cull-gmail + +1. Create the configuration directory: + ```bash + mkdir -p ~/.cull-gmail + ``` + +2. Copy your OAuth2 credential file: + ```bash + cp ~/Downloads/client_secret_*.json ~/.cull-gmail/client_secret.json + ``` + +3. Create configuration file `~/.cull-gmail/cull-gmail.toml`: + ```toml + credential_file = "client_secret.json" + config_root = "~/.cull-gmail" + rules = "rules.toml" + execute = false # Start in dry-run mode + ``` + +### 3. First Run Authentication + +Run any command to trigger the OAuth flow: + +```bash +cull-gmail labels +``` + +This will: +1. Open your browser for Google authentication +2. Prompt you to grant Gmail access +3. Save tokens to `~/.cull-gmail/gmail1/` + +## Configuration + +### Configuration File + +**Location**: `~/.cull-gmail/cull-gmail.toml` + +```toml +# OAuth2 credential file (relative to config_root) +credential_file = "client_secret.json" + +# Configuration directory +config_root = "~/.cull-gmail" + +# Rules file +rules = "rules.toml" + +# Default execution mode (false = dry-run, true = execute) +execute = false + +# Alternative: Direct OAuth2 configuration +# client_id = "your-client-id.apps.googleusercontent.com" +# client_secret = "your-client-secret" +# token_uri = "https://oauth2.googleapis.com/token" +# auth_uri = "https://accounts.google.com/o/oauth2/auth" +``` + +### Environment Variables + +Override any configuration setting: + +```bash +export APP_CREDENTIAL_FILE="client_secret.json" +export APP_EXECUTE="true" +export APP_CLIENT_ID="your-client-id" +export APP_CLIENT_SECRET="your-client-secret" +export APP_CONFIG_ROOT="/custom/config/path" +``` + +## Command Structure + +```bash +cull-gmail [OPTIONS] [COMMAND] +``` + +### Global Options + +- `-v, --verbose...`: Increase logging verbosity (can be used multiple times) +- `-q, --quiet...`: Decrease logging verbosity +- `-h, --help`: Show help +- `-V, --version`: Show version + +### Commands + +- `labels`: List available Gmail labels +- `messages`: Query and operate on messages +- `rules`: Configure and run retention rules + +## Command Reference + +### Labels Command + +List all labels in your Gmail account: + +```bash +cull-gmail labels +``` + +**Example Output**: +``` +INBOX: INBOX +IMPORTANT: IMPORTANT +CHAT: CHAT +SENT: SENT +DRAFT: DRAFT +promotions: Label_1234567890 +old-emails: Label_0987654321 +``` + +### Messages Command + +Query and operate on Gmail messages. + +#### Syntax + +```bash +cull-gmail messages [OPTIONS] +``` + +#### Options + +- `-l, --labels `: Filter by labels (can be used multiple times) +- `-m, --max-results `: Maximum results per page [default: 200] +- `-p, --pages `: Maximum number of pages (0=all) [default: 1] +- `-Q, --query `: Gmail query string + +#### Actions + +- `list`: Display message information +- `trash`: Move messages to trash +- `delete`: Permanently delete messages + +#### Examples + +**List recent messages**: +```bash +cull-gmail messages -m 10 list +``` + +**List promotional emails older than 6 months**: +```bash +cull-gmail messages -Q "label:promotions older_than:6m" list +``` + +**Move old promotional emails to trash**: +```bash +cull-gmail messages -Q "label:promotions older_than:1y" trash +``` + +**Permanently delete very old messages**: +```bash +cull-gmail messages -Q "older_than:5y -label:important" delete +``` + +**Query with multiple labels**: +```bash +cull-gmail messages -l "promotions" -l "newsletters" -Q "older_than:3m" list +``` + +**Process all pages (not just first page)**: +```bash +cull-gmail messages -p 0 -Q "older_than:2y" list +``` + +### Rules Command + +Manage retention rules for automated email lifecycle management. + +#### Syntax + +```bash +cull-gmail rules +``` + +#### Subcommands + +- `config`: Configure retention rules +- `run`: Execute configured rules + +### Rules Config Command + +Configure retention rules: + +```bash +cull-gmail rules config +``` + +#### Config Actions + +- `rules`: Manage rule definitions +- `label`: Add/remove labels from rules +- `action`: Set action (trash/delete) on rules + +**Example Rules Configuration**: + +Create/edit `~/.cull-gmail/rules.toml`: + +```toml +[rules."1"] +id = 1 +retention = { age = "y:1", generate_label = true } +labels = ["old-emails"] +action = "Trash" + +[rules."2"] +id = 2 +retention = { age = "m:6", generate_label = true } +labels = ["promotions", "newsletters"] +action = "Trash" + +[rules."3"] +id = 3 +retention = { age = "y:5", generate_label = true } +labels = ["archive"] +action = "Delete" +``` + +### Rules Run Command + +Execute configured rules: + +```bash +cull-gmail rules run [OPTIONS] +``` + +#### Options + +- `-e, --execute`: Actually perform actions (without this, runs in dry-run mode) +- `-t, --skip-trash`: Skip rules with "trash" action +- `-d, --skip-delete`: Skip rules with "delete" action + +#### Examples + +**Dry-run all rules** (safe, no changes made): +```bash +cull-gmail rules run +``` + +**Execute all rules**: +```bash +cull-gmail rules run --execute +``` + +**Execute only delete rules**: +```bash +cull-gmail rules run --execute --skip-trash +``` + +**Execute only trash rules**: +```bash +cull-gmail rules run --execute --skip-delete +``` + +## Gmail Query Syntax + +The `-Q, --query` option supports Gmail's powerful search syntax: + +### Date Queries + +```bash +# Relative dates +-Q "older_than:1y" # Older than 1 year +-Q "newer_than:30d" # Newer than 30 days +-Q "older_than:6m" # Older than 6 months + +# Absolute dates +-Q "after:2023/1/1" # After January 1, 2023 +-Q "before:2023/12/31" # Before December 31, 2023 +``` + +### Label Queries + +```bash +# Has label +-Q "label:promotions" +-Q "label:important" + +# Does NOT have label (note the minus sign) +-Q "-label:important" +-Q "-label:spam" +``` + +### Content Queries + +```bash +# Subject line +-Q "subject:newsletter" +-Q "subject:(unsubscribe OR newsletter)" + +# From/To +-Q "from:noreply@example.com" +-Q "to:me@example.com" + +# Message content +-Q "unsubscribe" +-Q "has:attachment" +``` + +### Status Queries + +```bash +# Read status +-Q "is:unread" +-Q "is:read" + +# Star status +-Q "is:starred" +-Q "-is:starred" + +# Size +-Q "size:larger_than:10M" +-Q "size:smaller_than:1M" +``` + +### Combined Queries + +```bash +# Complex combinations +-Q "label:promotions older_than:6m -is:starred" +-Q "from:newsletters@example.com older_than:1y has:attachment" +-Q "subject:newsletter OR subject:promo older_than:3m" +``` + +## Common Workflows + +### 1. Clean Up Promotional Emails + +```bash +# Step 1: Preview what will be affected +cull-gmail messages -Q "label:promotions older_than:6m" list + +# Step 2: Move to trash (can be recovered for 30 days) +cull-gmail messages -Q "label:promotions older_than:6m" trash +``` + +### 2. Archive Old Conversations + +```bash +# Archive conversations older than 2 years (excluding starred) +cull-gmail messages -Q "older_than:2y -is:starred -label:important" trash +``` + +### 3. Delete Very Old Messages + +```bash +# Permanently delete messages older than 5 years (be careful!) +cull-gmail messages -Q "older_than:5y -is:starred -label:important" delete +``` + +### 4. Rule-Based Automation + +```bash +# Set up rules in ~/.cull-gmail/rules.toml, then: + +# Preview what rules will do +cull-gmail rules run + +# Execute rules +cull-gmail rules run --execute +``` + +### 5. Scheduled Cleanup + +Add to your crontab for weekly cleanup: + +```bash +# Edit crontab +crontab -e + +# Add this line (runs every Sunday at 2 AM) +0 2 * * 0 /home/user/.cargo/bin/cull-gmail rules run --execute >> /var/log/cull-gmail.log 2>&1 +``` + +## Safety Features + +### Dry-Run Mode + +- **Default behaviour**: All operations are dry-run unless explicitly executed +- **Messages**: Use `list` action to preview what would be affected +- **Rules**: Run without `--execute` flag to see what would happen + +### Confirmation and Logging + +- All operations are logged with detailed information +- Use `-v` for verbose logging to see exactly what's happening +- Check log output before running destructive operations + +### Recoverable Operations + +- **Trash**: Messages moved to trash can be recovered for 30 days +- **Delete**: Permanent deletion - cannot be undone + +## Logging and Debugging + +### Environment Variables + +```bash +# Set log level +export RUST_LOG=cull_gmail=debug + +# Enable all logging +export RUST_LOG=debug +``` + +### Verbosity Levels + +```bash +# Quiet (errors only) +cull-gmail -q messages list + +# Normal (default) +cull-gmail messages list + +# Verbose (info level) +cull-gmail -v messages list + +# Very verbose (debug level) +cull-gmail -vv messages list + +# Maximum verbosity (trace level) +cull-gmail -vvv messages list +``` + +### Log Information + +- **Error**: Critical issues +- **Warn**: Non-fatal issues, dry-run notifications +- **Info**: General operation info, message subjects, counts +- **Debug**: Detailed API calls, query strings +- **Trace**: Very detailed debugging information + +## Troubleshooting + +### Authentication Issues + +**Problem**: "Authentication failed" or "Invalid credentials" + +**Solutions**: +1. Verify OAuth2 credential file exists and is valid JSON +2. Check OAuth client is configured as "Desktop Application" +3. Clear token cache: `rm -rf ~/.cull-gmail/gmail1` +4. Re-run authentication: `cull-gmail labels` + +**Problem**: "Access denied" or "Insufficient permissions" + +**Solutions**: +1. Verify Gmail API is enabled in Google Cloud Console +2. Check OAuth scopes include Gmail access +3. Re-authenticate with proper permissions + +### Query Issues + +**Problem**: "No messages found" when you expect results + +**Solutions**: +1. Test query in Gmail web interface first +2. Check label names: `cull-gmail labels` +3. Verify query syntax (no typos) +4. Use `-v` flag to see the actual query being sent + +**Problem**: Query returns unexpected results + +**Solutions**: +1. Use `messages list` to preview before `trash`/`delete` +2. Check for operator precedence in complex queries +3. Test simpler queries first, then combine + +### Performance Issues + +**Problem**: Operations are slow or timeout + +**Solutions**: +1. Reduce page size: `-m 100` +2. Limit pages: `-p 5` instead of `-p 0` +3. Use more specific queries to reduce result sets +4. Check Gmail API quotas in Google Cloud Console + +### Configuration Issues + +**Problem**: "Configuration not found" or "Config parse error" + +**Solutions**: +1. Verify config file path: `~/.cull-gmail/cull-gmail.toml` +2. Check TOML syntax +3. Ensure OAuth2 credential file path is correct +4. Use absolute paths if relative paths fail + +## Exit Codes + +- **0**: Success +- **101**: Error (check stderr for details) + +## Examples + +### Basic Message Management + +```bash +# List all labels +cull-gmail labels + +# List first 50 messages +cull-gmail messages -m 50 list + +# List promotional emails from last year +cull-gmail messages -Q "label:promotions after:2023/1/1" list +``` + +### Batch Operations + +```bash +# Move old promotional emails to trash +cull-gmail messages -Q "label:promotions older_than:1y" trash + +# Permanently delete very old messages (careful!) +cull-gmail messages -Q "older_than:5y -is:starred" delete +``` + +### Rule-Based Management + +```bash +# Preview all rules +cull-gmail rules run + +# Execute only trash rules +cull-gmail rules run --execute --skip-delete + +# Execute all rules +cull-gmail rules run --execute +``` + +## See Also + +- [Library Documentation](lib.md) - Rust API reference and programming examples +- [API Documentation](https://docs.rs/cull-gmail) - Generated API reference +- [Repository](https://github.com/jerus-org/cull-gmail) - Source code, examples, and issue tracking +- [Gmail API Documentation](https://developers.google.com/gmail/api) - Google's official API docs +- [Gmail Search Operators](https://support.google.com/mail/answer/7190?hl=en) - Complete Gmail query syntax +# cull-gmail Library Documentation + +The `cull-gmail` library provides a Rust API for managing Gmail messages through the Gmail API. It enables programmatic email culling operations including authentication, message querying, filtering, and batch operations (trash/delete). + +## Installation + +Add the library to your `Cargo.toml`: + +```toml +[dependencies] +cull-gmail = "0.0.11" +tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +``` + +## Quick Start + +Here's a minimal example to get started: + +```rust path=null start=null +use cull_gmail::{ClientConfig, GmailClient, Result}; + +#[tokio::main] +async fn main() -> Result<()> { + // Load configuration from file or environment + let config = ClientConfig::builder() + .with_credential_file("credential.json") + .build(); + + // Create Gmail client and authenticate + let mut client = GmailClient::new_with_config(config).await?; + + // List first 10 messages + client.set_max_results(10); + client.get_messages(1).await?; + client.log_messages().await?; + + Ok(()) +} +``` + +## Core Types + +### GmailClient + +The main client for interacting with Gmail API: + +```rust path=null start=null +use cull_gmail::{GmailClient, MessageList}; + +// Create client with configuration +let mut client = GmailClient::new_with_config(config).await?; + +// Query messages with Gmail search syntax +client.set_query("older_than:1y label:promotions"); +client.add_labels(&["INBOX".to_string()])?; +client.set_max_results(200); + +// Get messages (0 = all pages, 1 = first page only) +client.get_messages(0).await?; + +// Access message data +let messages = client.messages(); +let message_ids = client.message_ids(); +``` + +### ClientConfig + +Handles authentication and configuration: + +```rust path=null start=null +use cull_gmail::ClientConfig; + +// From credential file +let config = ClientConfig::builder() + .with_credential_file("path/to/credential.json") + .with_config_path(".cull-gmail") + .build(); + +// From individual OAuth2 parameters +let config = ClientConfig::builder() + .with_client_id("your-client-id") + .with_client_secret("your-client-secret") + .with_auth_uri("https://accounts.google.com/o/oauth2/auth") + .with_token_uri("https://oauth2.googleapis.com/token") + .add_redirect_uri("http://localhost:8080") + .build(); +``` + +### Rules and Retention Policies + +Define automated message lifecycle rules: + +```rust path=null start=null +use cull_gmail::{Rules, Retention, MessageAge, EolAction}; + +// Create a rule set +let mut rules = Rules::new(); + +// Add retention rules +rules.add_rule( + Retention::new(MessageAge::Years(1), true), + Some(&"old-emails".to_string()), + false // false = trash, true = delete +); + +rules.add_rule( + Retention::new(MessageAge::Months(6), true), + Some(&"promotions".to_string()), + false +); + +// Save rules to file +rules.save()?; + +// Load existing rules +let loaded_rules = Rules::load()?; +``` + +### Message Operations + +Batch operations on messages: + +```rust path=null start=null +use cull_gmail::{RuleProcessor, EolAction}; + +// Set up rule and dry-run mode +client.set_execute(false); // Dry run - no actual changes +let rule = rules.get_rule(1).unwrap(); +client.set_rule(rule); + +// Find messages matching rule for a label +client.find_rule_and_messages_for_label("promotions").await?; + +// Check what action would be performed +if let Some(action) = client.action() { + match action { + EolAction::Trash => println!("Would move {} messages to trash", client.messages().len()), + EolAction::Delete => println!("Would delete {} messages permanently", client.messages().len()), + } +} + +// Execute for real +client.set_execute(true); +match client.action() { + Some(EolAction::Trash) => client.batch_trash().await?, + Some(EolAction::Delete) => client.batch_delete().await?, + None => println!("No action specified"), +} +``` + +## Configuration + +### OAuth2 Setup + +1. Create OAuth2 credentials in [Google Cloud Console](https://console.cloud.google.com/) +2. Download the credential JSON file +3. Configure the client: + +```rust path=null start=null +let config = ClientConfig::builder() + .with_credential_file("path/to/credential.json") + .build(); +``` + +### Configuration File + +The library supports TOML configuration files (default: `~/.cull-gmail/cull-gmail.toml`): + +```toml +credentials = "credential.json" +config_root = "~/.cull-gmail" +rules = "rules.toml" +execute = false + +# Alternative: direct OAuth2 parameters +# client_id = "your-client-id" +# client_secret = "your-client-secret" +# token_uri = "https://oauth2.googleapis.com/token" +# auth_uri = "https://accounts.google.com/o/oauth2/auth" +``` + +### Environment Variables + +Override configuration with environment variables: + +```bash +export APP_CREDENTIALS="/path/to/credential.json" +export APP_EXECUTE="true" +export APP_CLIENT_ID="your-client-id" +export APP_CLIENT_SECRET="your-client-secret" +``` + +## Error Handling + +The library uses a comprehensive error type: + +```rust path=null start=null +use cull_gmail::{Error, Result}; + +match client.get_messages(1).await { + Ok(_) => println!("Success!"), + Err(Error::NoLabelsFound) => println!("No labels found in mailbox"), + Err(Error::LabelNotFoundInMailbox(label)) => println!("Label '{}' not found", label), + Err(Error::GoogleGmail1(e)) => println!("Gmail API error: {}", e), + Err(e) => println!("Other error: {}", e), +} +``` + +Common error types: +- `NoLabelsFound`: Mailbox has no labels +- `LabelNotFoundInMailbox(String)`: Specific label not found +- `RuleNotFound(usize)`: Rule ID doesn't exist +- `GoogleGmail1(Box)`: Gmail API errors +- `StdIO(std::io::Error)`: File I/O errors +- `Config(config::ConfigError)`: Configuration errors + +## Async Runtime + +The library requires an async runtime (Tokio recommended): + +```toml +[dependencies] +tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +``` + +```rust path=null start=null +#[tokio::main] +async fn main() -> cull_gmail::Result<()> { + // Your code here + Ok(()) +} +``` + +## Gmail Query Syntax + +The library supports Gmail's search syntax for message queries: + +```rust path=null start=null +// Date-based queries +client.set_query("older_than:1y"); // Older than 1 year +client.set_query("newer_than:30d"); // Newer than 30 days +client.set_query("after:2023/1/1"); // After specific date + +// Label-based queries +client.set_query("label:promotions"); // Has promotions label +client.set_query("-label:important"); // Does NOT have important label + +// Content queries +client.set_query("subject:newsletter"); // Subject contains "newsletter" +client.set_query("from:noreply@example.com"); // From specific sender + +// Combined queries +client.set_query("label:promotions older_than:6m -is:starred"); +``` + +## Performance & Limits + +### Pagination + +- Default page size: 200 messages +- Use `client.set_max_results(n)` to adjust +- Use `client.get_messages(0)` to get all pages +- Use `client.get_messages(n)` to limit to n pages + +### Rate Limits + +- The library uses the official `google-gmail1` crate +- Built-in retry logic for transient errors +- Respects Gmail API quotas and limits + +### Batch Operations + +- Batch delete/trash operations are more efficient than individual calls +- Operations are atomic - either all succeed or all fail + +## Logging + +The library uses the `log` crate for logging: + +```rust path=null start=null +use env_logger; + +// Initialize logging +env_logger::init(); + +# Set log level via environment variable +# RUST_LOG=cull_gmail=debug cargo run +``` + +Log levels: +- `error`: Critical errors +- `warn`: Warnings (e.g., missing labels, dry-run mode) +- `info`: General information (e.g., message subjects, action results) +- `debug`: Detailed operation info +- `trace`: Very detailed debugging info + +## Security Considerations + +### OAuth2 Token Storage +- Tokens are stored in `~/.cull-gmail/gmail1` by default +- Tokens are automatically refreshed when expired +- Revoke access in [Google Account settings](https://myaccount.google.com/permissions) + +### Required Scopes +The library requires the `https://mail.google.com/` scope for full Gmail access. + +### OAuth2 File Security +- Store OAuth2 credential files securely (not in version control) +- Use restrictive file permissions (600) +- Consider using environment variables in production + +## Troubleshooting + +### Authentication Issues +1. Verify OAuth2 credential file path and JSON format +2. Check OAuth2 client is configured for "Desktop Application" +3. Ensure redirect URI matches configuration +4. Clear token cache: `rm -rf ~/.cull-gmail/gmail1` + +### No Messages Found +1. Verify label names exist: `client.show_label()` +2. Test query syntax in Gmail web interface +3. Check for typos in label names or query strings + +### Rate Limiting +1. Reduce page size: `client.set_max_results(100)` +2. Add delays between operations +3. Check [Gmail API quotas](https://developers.google.com/gmail/api/reference/quota) + +## See Also + +- [CLI Documentation](main.md) - Complete guide to the command-line interface +- [Examples Directory](../examples/) - Additional code examples and sample configurations +- [API Documentation](https://docs.rs/cull-gmail) - Generated API reference +- [Repository](https://github.com/jerus-org/cull-gmail) - Source code and issue tracking + ## License By contributing to cull-gmail, you agree that your contributions will be licensed under the MIT License. This means: diff --git a/docs/lib.md b/docs/lib.md index f92912c..f294f2d 100644 --- a/docs/lib.md +++ b/docs/lib.md @@ -8,7 +8,7 @@ Add the library to your `Cargo.toml`: ```toml [dependencies] -cull-gmail = "0.0.10" +cull-gmail = "0.0.11" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } ```