SaveGmail is a Python script for archiving Gmail messages as PDFs and saving their attachments locally. It uses the Gmail API for email access and Playwright/Chromium for PDF generation.
- Lists available Gmail messages directly in the terminal
- Lets you choose emails interactively by number, ranges, or multiple ranges
- Downloads selected emails as PDFs with complete metadata
- Extracts and saves email attachments
- Preserves HTML email formatting where possible
- Moves successfully processed Gmail messages to the Gmail trash
- Provides a manual option to empty the Gmail trash
- Secure OAuth 2.0 authentication
- Local Playwright/Chromium setup through the launcher
- Python 3.6 or higher
- Google Cloud Platform project with Gmail API enabled
- OAuth 2.0 credentials file (
credentials.json) in the project directory
-
Clone the repository:
git clone https://github.com/C0sm0cats/GMAIL.git cd GMAIL -
Make the launcher executable if needed:
chmod +x run-savegmail.sh
-
Run the launcher once to bootstrap the local Python environment:
./run-savegmail.sh --help
The launcher creates a local
.venvwhen it is missing, installs the Python dependencies, and installs the Playwright Chromium browser binaries inside that virtual environment.
-
Google Cloud Platform setup
- Create a project on Google Cloud Console
- Enable Gmail API
- Create OAuth 2.0 credentials
- Download
credentials.jsonto the project directory
-
Download directory
The default download path is defined in
savegmail.py:DOWNLOAD_PATH = '~/Downloads/'
You can either change that variable in the script or override it at runtime:
./run-savegmail.sh --download-path /path/to/archive/
Run:
./run-savegmail.shBy default, the script lists Gmail messages without requiring the old HasAttachment label workflow. You then select which messages to download from the terminal.
Supported selections:
1,3,5 numbers separated by commas or spaces
2-6 number range
2-6,8-10 multiple ranges
1,3,7-9 mix of numbers and ranges
all select everything listed
q quit without downloading
After a selected email is successfully saved locally, the script moves the corresponding Gmail message to the Gmail trash.
Use Gmail search syntax with --query:
./run-savegmail.sh --query "has:attachment"
./run-savegmail.sh --query "newer_than:30d"
./run-savegmail.sh --query "from:example@example.com"./run-savegmail.sh --max 100./run-savegmail.sh --trashThis option only empties the Gmail trash. It is not run automatically after downloads.
./run-savegmail.sh --helpFor each selected message, SaveGmail:
- retrieves the email through the Gmail API
- extracts metadata such as subject, sender, recipients, and date
- renders the message body to PDF using Playwright/Chromium
- saves attachments in the configured download directory
- moves the processed Gmail message to the Gmail trash
- Verify
credentials.jsonexists in the project directory - Check that Gmail API is enabled in Google Cloud Console
- If the OAuth token is invalid, remove
token.jsonand run the script again
- Check destination directory permissions
- Ensure sufficient disk space
- Use
--download-pathto test another output directory
- Use
./run-savegmail.shinstead of runningpython savegmail.pydirectly - The launcher keeps Playwright, its bundled driver runtime, and its Chromium browser binaries inside the local
.venv
The older HasAttachment / HasAttachment/SavedAsPDF Gmail label workflow is no longer required by the current interactive version. If needed, you can still list only attachment-bearing emails with:
./run-savegmail.sh --query "has:attachment"Contributions are welcome! Feel free to open an issue or submit a pull request.
This project is licensed under the MIT License. See the LICENSE file for details.
Built with ❤️ by C0sm0cats