Invoice Pilot is a fully automated invoice and bank statement management tool built with Rust. This project is completely free to use, modify, and distribute under the MIT License.
- What It Does
- Features
- Prerequisites
- Installation
- Configuration
- Usage
- How It Works
- Supported Financial Institutions
- Scheduling
- Troubleshooting
- Development
- Contributing
- License
✅ Fetches invoices and bank statements from Gmail
✅ Automatically detects financial institutions (banks, brokerages, exchanges, payment processors)
✅ Downloads all attachments from matching emails
✅ Organizes files by institution in Google Drive with proper capitalization
✅ Creates smart filenames with sender names (e.g., langfuse-gmbh-invoice-12345.pdf)
✅ Prevents duplicates by checking existing files
✅ Runs manually or on schedule
- Dual Google account support (separate accounts for Gmail and Drive)
- OAuth2 authentication with token caching
- Automatic token refresh
- Gmail search for invoices/faturas/bank statements with attachments
- Smart filename prefixing with sender names
- Automatic financial institution detection for banks, brokerages, exchanges, and payment processors
- Financial institution folder organization (separate folders per institution with proper capitalization)
- Google Drive upload with automatic folder creation
- Manual and scheduled execution modes with Docker-based automation
- Automatic monthly scheduling - runs on configured day without user interaction
- Duplicate detection and skipping
- Comprehensive error handling and logging
- Install Rust: https://rustup.rs/
- Cargo will be installed automatically with Rust
You need TWO Google Cloud projects (or one project with two OAuth2 clients):
- Go to Google Cloud Console
- Create a new project or select existing one
- Enable Gmail API:
- Navigate to "APIs & Services" > "Library"
- Search for "Gmail API"
- Click "Enable"
- Create OAuth2 Credentials:
- Go to "APIs & Services" > "Credentials"
- Click "Create Credentials" > "OAuth client ID"
- Application type: Desktop app
- Name: "invoice pilot - Gmail"
- Click "Create"
- Save the Client ID and Client Secret
- Configure OAuth consent screen:
- Go to "APIs & Services" > "OAuth consent screen"
- Add scope:
https://www.googleapis.com/auth/gmail.readonly
- Create another project or use the same project
- Enable Google Drive API:
- Navigate to "APIs & Services" > "Library"
- Search for "Google Drive API"
- Click "Enable"
- Create OAuth2 Credentials:
- Go to "APIs & Services" > "Credentials"
- Click "Create Credentials" > "OAuth client ID"
- Application type: Desktop app
- Name: "invoice pilot - Drive"
- Click "Create"
- Save the Client ID and Client Secret
- Configure OAuth consent screen:
- Go to "APIs & Services" > "OAuth consent screen"
- Add scope:
https://www.googleapis.com/auth/drive.file
# Clone the repository
git clone https://github.com/adolfousier/invoicepilot.git
cd invoice-pilot
# Build the project
cargo build --release
# The binary will be at target/release/invoice-pilot-
Copy the example environment file:
cp .env.example .env
-
Edit
.envand fill in your credentials:# Gmail account credentials (Account A) GOOGLE_GMAIL_CLIENT_ID=your-gmail-client-id.apps.googleusercontent.com GOOGLE_GMAIL_CLIENT_SECRET=your-gmail-client-secret # Drive account credentials (Account B) GOOGLE_DRIVE_CLIENT_ID=your-drive-client-id.apps.googleusercontent.com GOOGLE_DRIVE_CLIENT_SECRET=your-drive-client-secret # Drive folder path (will be created if it doesn't exist) GOOGLE_DRIVE_FOLDER_LOCATION=billing/all-expenses/2025 # Day of month to fetch invoices (1-31) FETCH_INVOICES_DAY=5 # Keywords to search for (comma-separated) TARGET_KEYWORDS_TO_FETCH_AND_DOWNLOAD="invoice, invoices, fatura, faturas, statement, bank, extrato, movimientos, financial, fiscal, tributary"
On first run, you'll need to authorize both accounts:
cargo run -- manualThis will:
- Open a browser for Gmail authorization (Account A)
- Open a browser for Drive authorization (Account B)
- Cache tokens locally at
~/.config/invoice-pilot/ - Fetch invoices from the previous month and upload to Drive
cargo run -- manualcargo run -- manual --date-range 2024-09-01:2024-10-12Run on a schedule using systemd timer or cron:
cargo run -- scheduledThis will only execute if today matches FETCH_INVOICES_DAY from .env.
cargo run -- auth gmailcargo run -- auth drivecargo run -- auth reset- Searches Gmail for emails containing your configured keywords (invoice, fatura, statement, bank, etc.)
- Downloads ALL attachments from matching emails
- Creates smart filenames with sender names (e.g.,
langfuse-gmbh-invoice-12345.pdf)
- Identifies banks, brokerages, exchanges, and payment processors from email content
- Organizes files by institution in separate folders with proper capitalization
- Supports 100+ European banks, Wise, Revolut, Coinbase, Stripe, PayPal, and more
- Uses keywords like "bank", "banco", "statement", "financial", "fiscal", "tributary"
- Creates monthly folders automatically (e.g.,
2025/,2024/) - Creates institution-specific folders (e.g.,
Stripe/,Wise/,Coinbase/) - Uploads files with proper organization
- Prevents duplicates by checking existing files
- Wise (formerly TransferWise)
- Revolut
- Nubank
- Bunq
- Monzo
- Starling Bank
- Chime
- PayPal
- Stripe
- Adyen
- Mollie
- Santander
- BBVA
- CaixaBank
- ING
- Deutsche Bank
- HSBC
- Barclays
- And many more European banks
- Interactive Brokers
- Charles Schwab
- E*TRADE
- TD Ameritrade
- Fidelity
- Robinhood
- Webull
- Coinbase
- Binance
- Kraken
- Coinbase Pro
- Binance US
If FETCH_INVOICES_DAY is set in your .env file, Invoice Pilot can run automatically on the specified day of each month. The scheduled command will automatically spin up a Docker container to execute the job, ensuring isolation and reliability.
In automated mode, cached OAuth tokens are used, so no user interaction or browser opening is required. The job runs in a container with mounted volumes for configuration and tokens.
To use automated execution:
- Build the Docker image:
cd docker && docker-compose build - Run the scheduled command:
cargo run -- scheduled(or./target/release/invoice-pilot scheduled)
If you prefer external scheduling, you can still set up systemd timers or cron jobs as described below.
-
Create the service file
/etc/systemd/system/invoice-pilot.service:[Unit] Description=Invoice Pilot [Service] Type=oneshot User=your-username WorkingDirectory=/path/to/invoice-pilot ExecStart=/path/to/invoice-pilot/target/release/invoice-pilot scheduled Environment="PATH=/usr/local/bin:/usr/bin:/bin"
-
Create the timer file
/etc/systemd/system/invoice-pilot.timer:[Unit] Description=Invoice Pilot Monthly Check [Timer] OnCalendar=*-*-{FETCH_INVOICES_DAY} Persistent=true [Install] WantedBy=timers.target
Replace
{FETCH_INVOICES_DAY}with your configured day (e.g.,05for the 5th of each month). -
Enable and start the timer:
sudo systemctl daemon-reload sudo systemctl enable invoice-pilot.timer sudo systemctl start invoice-pilot.timer # Check status sudo systemctl status invoice-pilot.timer
Add to your crontab (crontab -e):
# Run on the configured day of each month at 9 AM
0 9 {FETCH_INVOICES_DAY} * * cd /path/to/invoice-pilot && /path/to/invoice-pilot/target/release/invoice-pilot scheduled >> /var/log/invoice-pilot.log 2>&1Replace {FETCH_INVOICES_DAY} with your configured day (e.g., 5 for the 5th of each month).
The OAuth callback uses port 8080. If it's in use:
- Close any running instances of the tool
- Check for other services using port 8080
- Kill the process:
lsof -ti:8080 | xargs kill -9
If you get authorization errors:
- Check that APIs are enabled in Google Cloud Console
- Verify OAuth2 scopes are configured correctly
- Re-authenticate:
cargo run -- auth reset - Make sure redirect URI is set to
http://localhost:8080in Google Cloud Console
Tokens auto-refresh, but if you encounter issues:
cargo run -- auth reset
cargo run -- manual- Check the date range
- Verify your Gmail account has emails matching the search criteria
- Try searching manually in Gmail with the query shown in logs
- Ensure your keywords include terms like "statement", "bank", or specific bank names
- Check if bank statements are being sent to a different email address
# Run all tests
cargo test
# Run with output
cargo test -- --nocapturesrc/
├── auth/ # OAuth2 authentication
│ ├── oauth.rs # Base OAuth2 logic
│ ├── gmail_auth.rs # Gmail-specific auth
│ └── drive_auth.rs # Drive-specific auth
├── gmail/ # Gmail API client
│ ├── client.rs # HTTP client
│ ├── search.rs # Email search with bank detection
│ └── attachment.rs # Attachment download with sender/bank extraction
├── drive/ # Google Drive API client
│ ├── client.rs # HTTP client
│ ├── folder.rs # Folder management
│ └── upload.rs # File upload
├── scheduler/ # Scheduling logic
│ └── runner.rs # Date calculations
├── config/ # Configuration
│ └── env.rs # .env parsing
├── cli/ # CLI interface
│ └── args.rs # Argument parsing
└── main.rs # Application entry point
- Never commit
.envfile or tokens to version control - Tokens are stored in
~/.config/invoice-pilot/with user-only permissions - OAuth2 uses PKCE for enhanced security
- All API calls use HTTPS
We welcome contributions from everyone! This is an open-source project, and we value any help you can provide.
- Fork the repository on GitHub
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes with tests if applicable
- Commit your changes:
git commit -m 'feat: add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request with a clear description of your changes
- Code Style: Follow Rust best practices and existing code style
- Tests: Add tests for new functionality when possible
- Documentation: Update documentation for new features
- Breaking Changes: Clearly mark breaking changes in PR descriptions
- Use the GitHub issue tracker to report bugs
- Include steps to reproduce, expected behavior, and actual behavior
- For feature requests, describe the problem and proposed solution
- New Bank/Institution Support: Add detection for new financial institutions
- Improved Error Handling: Enhance error messages and recovery
- Performance Optimizations: Speed up Gmail search or file uploads
- Documentation: Improve README or add usage examples
- Testing: Add more comprehensive test coverage
- Clone the repository:
git clone https://github.com/adolfousier/invoicepilot.git - Set up development environment:
cargo build - Run existing tests:
cargo test - Make your changes
- Test thoroughly:
cargo build && cargo test - Submit your pull request
Thank you for contributing to Invoice Pilot! 🚀
This project is licensed under the MIT License - see the LICENSE file for details.
This software is completely free to use, modify, and distribute for any purpose.
For issues, questions, or contributions, please open an issue on GitHub.