A powerful CLI tool that finds and sets company logos as your contact photos in Microsoft 365, Outlook, and Gmail
Project description
BrandBox
Ditch the colorful circles, add some branding to your inbox.
Microsoft Setup · Google Setup · Report Bugs · Request Features
Why It Exists
Every version of Outlook and Gmail shows a colored circle with the sender's initials next to their name. When your inbox is full of "JD", "AS", and "MT", you're left squinting at colored circles trying to remember who's who.
BrandBox fixes that. It fetches each sender's company logo and uploads it as their contact photo via the Microsoft Graph API and Google People API. It works at the account backend level, so logos propagate everywhere automatically — desktop Outlook, Outlook on the web, Gmail mobile, Google Contacts, and all other connected clients.
No more colored circles. Just recognizable brand logos in your inbox.
Features
| Feature | Description |
|---|---|
| Logo Injection | Replaces generic initials with real company logos in Outlook and Gmail |
| Cross-Client Sync | Logos appear on desktop, web, and mobile — set once at the API level |
| Smart Logo Pipeline | SVG-first with 7 sources: SimpleIcons → VectorLogo.Zone → Wikimedia Commons → Hunter → DeBounce → LogoKit → Brandfetch. SVGs provide inherent transparency — no white backgrounds in dark-mode Outlook/Gmail. Rasterized at 400×400px via cairosvg for crisp, high-resolution logos |
| Smart Image Processing | Auto-crops transparency, scales to fill 200×200 preserving aspect ratio, centers on transparent canvas |
| Multi-Provider | Microsoft 365, Outlook.com, Hotmail, Gmail, Google Workspace — all at once |
| Local Privacy | All data stays on your machine; nothing leaves except API calls for photos |
| Incremental Runs | Logo cache and contact state tracking make repeat runs near-instant |
| Inbox Scan | Optionally creates contacts for recent senders (only when a logo is found) |
| Logo Provider Label | Optional --logo-provider flag shows the logo source (e.g. [hunter], [simpleicons]) next to each logo in the progress output |
| Scan-Inbox Progress | Real-time progress bar with per-sender status, MofN counters, and elapsed time during inbox scan — no more silent waiting |
Compatibility
| Provider | Supported account types |
|---|---|
| Microsoft | Microsoft 365 work/school, Personal/Family, Outlook.com, Hotmail, Live |
| Gmail (personal), Google Workspace (business) |
[!Note] On-premises Exchange (non-hybrid) and IMAP/POP3 accounts are not supported. If you have Gmail connected inside Outlook, add it separately as a Google provider account — see the Google setup guide.
Both providers can run simultaneously. brandbox processes all authenticated accounts in a single --run.
Requirements
- Python 3.11+
- A free Azure App Registration for Microsoft 365 accounts → full setup guide
- A free Google Cloud project for Gmail / Workspace accounts → full setup guide
Installation
With uv (recommended)
uv tool install brandbox
With pip
pip install brandbox
From source
git clone https://github.com/divisionseven/brandbox
cd brandbox
uv sync
uv run brandbox --help
Verify
brandbox --version
# Output: brandbox <version>
Setup
Microsoft 365 Setup — Azure App Registration
- Follow the Microsoft setup guide to create an Azure App Registration
- Copy the client ID from the Azure portal
- Set the environment variable:
export BRANDBOX_CLIENT_ID="your-client-id-here"
Add to ~/.zshrc or ~/.zshenv to persist across shell sessions. See the Microsoft setup guide for the recommended macOS Keychain approach.
Google / Gmail Setup — Google Cloud Project
- Follow the Google setup guide to create a Google Cloud project and download OAuth credentials
- Set the path to your credentials JSON file:
export BRANDBOX_GOOGLE_CREDENTIALS="$HOME/.config/brandbox/google_credentials.json"
Add to ~/.zshrc or ~/.zshenv to persist across shell sessions.
Usage
Add an account
Authenticate your first account. You'll be prompted to choose a provider:
brandbox --add-account
Or specify the provider directly:
brandbox --add-account --provider microsoft
brandbox --add-account --provider google
A browser window (Google) or device code prompt (Microsoft) will guide you through sign-in. Repeat for each account across both providers.
List accounts
brandbox --list-accounts
Run logo injection
Process all authenticated accounts and inject logos:
brandbox --run
Expected output:
┌──────────────────────────────────────────────────┐
│ brandbox v0.1.0 │
│ Inject company logos into Outlook and Gmail │
└──────────────────────────────────────────────────┘
── you@company.com · Microsoft 365 · 1 of 1 ──
Contacts 147 found
Processing contacts ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 147/147 15s
✓ Alice Johnson company.com
✓ Bob Smith acmecorp.com
· Charlie Davis gmail.com (personal domain)
✓ Eve Williams example.io
...
✓ 118 set · 22 already processed · 4 no logo · 2 personal domain · 1 failed
Also create contacts for recent senders
Logos only show for people already in your contacts. This flag scans recent inbox senders and creates a contact for each one — but only if a logo can be found first. No logo = no contact created.
brandbox --run --scan-inbox
[!Note] A full
--runwith--scan-inboxcan take 10+ minutes depending on inbox size and number of contacts. So if you are processing a large number of contacts, or a full inbox, please be patient as brandbox works its magic.
Preview without making changes
brandbox --run --dry-run
Re-process contacts that already have logos
brandbox --run --overwrite
Show logo provider labels
Shows the source provider (e.g. [hunter], [simpleicons]) next to each logo
in the progress output:
brandbox --run --logo-provider
Refresh all logos from scratch
Clears the cached logo files and re-fetches everything on the next run:
brandbox --clear-cache --run
Reset processed-contact state
Forces brandbox to re-evaluate every contact on the next run:
brandbox --reset-state --run
Show data directory
brandbox --data-dir
Command Reference
Click to expand full command reference
| Flag | Description |
|---|---|
--add-account |
Authenticate a new account |
--add-account --provider microsoft |
Authenticate a Microsoft 365 account |
--add-account --provider google |
Authenticate a Google / Workspace account |
--list-accounts |
List all authenticated accounts |
--run |
Inject logos for all accounts |
--run --dry-run |
Preview without making changes |
--run --overwrite |
Re-process contacts that already have logos |
--run --scan-inbox |
Also create contacts from recent senders (logo required) |
--run --logo-provider |
Show logo source label (e.g. [hunter]) next to each logo |
--clear-cache |
Delete all cached logos (re-fetched on next --run) |
--reset-state |
Reset processed-contact state (re-evaluate all contacts) |
--data-dir |
Show the brandbox data directory path |
--version / -V |
Print version number |
Environment variables
| Variable | Description |
|---|---|
BRANDBOX_CLIENT_ID |
Azure App Registration client ID (Microsoft auth) |
BRANDBOX_GOOGLE_CREDENTIALS |
Path to Google OAuth credentials JSON file |
After Running
Outlook and Gmail cache contact photos and won't show updates until they reload:
| Client | What to do |
|---|---|
| Outlook for Mac | Quit fully (⌘Q) and reopen |
| Outlook for Windows | Close fully and reopen |
| Outlook on the web | Hard-refresh (⌘+Shift+R / Ctrl+Shift+R) |
| Outlook mobile | Close and reopen the app |
| Gmail (web) | Hard-refresh the page |
| Gmail mobile | Close and reopen the app |
| Google Contacts | Logos appear immediately after running |
Data & Privacy
Logo APIs (no personal data)
When fetching company logos, BrandBox sends only the company domain name (e.g. stripe.com) to these services:
| Service | Data sent |
|---|---|
| SimpleIcons CDN | Domain slug only (stripe) |
| VectorLogo.Zone | Domain slug only (stripe) |
| Wikimedia Commons | Domain-based filename lookup. Includes User-Agent: Brandbox/1.0 header. |
| Hunter.io | Domain in URL (stripe.com) |
| DeBounce | Domain in URL (stripe.com) |
| LogoKit | Domain in URL (stripe.com) + public free-tier token |
| Brandfetch | Domain in URL (stripe.com) |
No authentication tokens, no user identifiers, and no personal data are sent to any logo API.
Provider APIs (your data, your account)
All contact operations go through your authenticated provider account (Google or Microsoft 365) under your own OAuth token. No third party has access to this data.
Microsoft Graph API (Mail.Read, Contacts.ReadWrite scopes):
- Contacts: Reads your contact list (
id,displayName,emailAddresses). Uploads company logos as contact photos. - Inbox scan (
--scan-inbox): Reads only thefromfield of recent inbox messages to discover new sender email addresses. Message subjects, bodies, and attachments are never requested or read. - Contact creation: New contacts are created with a display name and email address, derived from the sender's email (e.g.
john.doe@co.com→John Doe).
Google People API (contacts, contacts.other.readonly, gmail.readonly scopes):
- Contacts: Reads your contact list (names, email addresses). Uploads company logos as contact photos.
- Inbox scan (
--scan-inbox): Uses theotherContactsendpoint — Google's pre-computed list of people you've interacted with. This is populated from your Gmail activity but accessed via the People API, not by reading individual messages. - Contact creation: Same as Microsoft — new contacts created with display name and email.
Authentication
- Google: OAuth 2.0 browser flow via
InstalledAppFlow. Tokens stored locally in~/.local/share/brandbox/tokens/and never shared with third parties. - Microsoft: MSAL device code flow. Tokens cached locally in the same directory.
Local storage
All data is stored locally on your machine — none of this data is ever transmitted:
| File | Contents |
|---|---|
cache/*.png |
Downloaded company logos (processed as 200×200 PNGs) |
cache/*.miss |
Empty sentinel files marking domains with no logo (prevents retries) |
state.json |
Processing state: which contacts have been processed per account (contact IDs + domains only) |
tokens/google_*.json |
Google OAuth credentials |
tokens/microsoft.json |
Microsoft MSAL token cache |
Platform-specific data directory paths:
| Platform | Path |
|---|---|
| macOS | ~/Library/Application Support/brandbox/ |
| Windows | %LOCALAPPDATA%\brandbox\brandbox\ |
| Linux | ~/.local/share/brandbox/ |
Run brandbox --data-dir to see the exact path.
[!Important] Keep the
tokens/directory private. It contains OAuth refresh tokens. Never share this or commit it to version control.
Telemetry
BrandBox does not collect telemetry, analytics, crash reports, or usage data of any kind. No data is ever sent to services other than the logo APIs and authentication providers listed above. There are no "phone-home" calls, no tracking pixels, and no third-party analytics SDKs.
See our security documentation to report any security issues.
Testing
# Using uv (recommended)
uv run pytest tests/ -v
# Using pip
pytest tests/ -v
Documentation
| Document | Description |
|---|---|
| Microsoft 365 Setup | How to configure Azure App Registration for Outlook contacts |
| Google Setup | How to configure Google Cloud project for Gmail contacts |
| How It Works | Technical deep dive into the logo pipeline, contact discovery, and provider architecture |
Contributing
Contributions are welcome! Please open an issue before submitting a large PR to discuss your proposed changes.
git clone https://github.com/divisionseven/brandbox
cd brandbox
uv sync
uv run brandbox --help
See our Contributing Guide.
Run the linter and type checker before submitting:
uv run ruff check src/
uv run mypy src/
License
Distributed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file brandbox-0.2.0.tar.gz.
File metadata
- Download URL: brandbox-0.2.0.tar.gz
- Upload date:
- Size: 926.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d539bbb321fa1887f6001d19391926f9d14bad83a136ea2a64094e59e8e53a12
|
|
| MD5 |
fe34c863466ef570d90d3d8ba47391f8
|
|
| BLAKE2b-256 |
69f4abcb106b6dcbf19c305433fabefdc70724f06cca5091de5b6c649a5f8984
|
Provenance
The following attestation bundles were made for brandbox-0.2.0.tar.gz:
Publisher:
release.yml on divisionseven/brandbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
brandbox-0.2.0.tar.gz -
Subject digest:
d539bbb321fa1887f6001d19391926f9d14bad83a136ea2a64094e59e8e53a12 - Sigstore transparency entry: 1588614002
- Sigstore integration time:
-
Permalink:
divisionseven/brandbox@363e032c3a77fc171b8a1183004bd2f3c935e7c9 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/divisionseven
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@363e032c3a77fc171b8a1183004bd2f3c935e7c9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file brandbox-0.2.0-py3-none-any.whl.
File metadata
- Download URL: brandbox-0.2.0-py3-none-any.whl
- Upload date:
- Size: 27.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c44a84e087b88ee5dd9cbdf0865ee7162d50e250968864e6dad58c0cc2f16b8b
|
|
| MD5 |
9f49faed0d9ed9cee1fcaaf4e2dc064a
|
|
| BLAKE2b-256 |
7db6cfc280fcc212737774d1c4d92b02356853d385fd5a932e0ebf890a249912
|
Provenance
The following attestation bundles were made for brandbox-0.2.0-py3-none-any.whl:
Publisher:
release.yml on divisionseven/brandbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
brandbox-0.2.0-py3-none-any.whl -
Subject digest:
c44a84e087b88ee5dd9cbdf0865ee7162d50e250968864e6dad58c0cc2f16b8b - Sigstore transparency entry: 1588614057
- Sigstore integration time:
-
Permalink:
divisionseven/brandbox@363e032c3a77fc171b8a1183004bd2f3c935e7c9 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/divisionseven
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@363e032c3a77fc171b8a1183004bd2f3c935e7c9 -
Trigger Event:
push
-
Statement type: