9.1 KiB
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:
[dependencies]
cull-gmail = "0.1.5"
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
Quick Start
Here's a minimal example to get started:
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:
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:
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:
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:
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
- Create OAuth2 credentials in Google Cloud Console
- Download the credential JSON file
- Configure the client:
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):
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:
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:
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 labelsLabelNotFoundInMailbox(String): Specific label not foundRuleNotFound(usize): Rule ID doesn't existGoogleGmail1(Box<google_gmail1::Error>): Gmail API errorsStdIO(std::io::Error): File I/O errorsConfig(config::ConfigError): Configuration errors
Async Runtime
The library requires an async runtime (Tokio recommended):
[dependencies]
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
#[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:
// 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-gmail1crate - 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:
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 errorswarn: Warnings (e.g., missing labels, dry-run mode)info: General information (e.g., message subjects, action results)debug: Detailed operation infotrace: Very detailed debugging info
Security Considerations
OAuth2 Token Storage
- Tokens are stored in
~/.cull-gmail/gmail1by default - Tokens are automatically refreshed when expired
- Revoke access in Google Account settings
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
- Verify OAuth2 credential file path and JSON format
- Check OAuth2 client is configured for "Desktop Application"
- Ensure redirect URI matches configuration
- Clear token cache:
rm -rf ~/.cull-gmail/gmail1
No Messages Found
- Verify label names exist:
client.show_label() - Test query syntax in Gmail web interface
- Check for typos in label names or query strings
Rate Limiting
- Reduce page size:
client.set_max_results(100) - Add delays between operations
- Check Gmail API quotas
See Also
- CLI Documentation - Complete guide to the command-line interface
- Examples Directory - Additional code examples and sample configurations
- API Documentation - Generated API reference
- Repository - Source code and issue tracking