AI-powered email personalization tool with Gmail and Google Sheets integration for Google Workspace organizations.
- Google Cloud Secret Manager: Centralized LLM API key management for team-wide use
- Google Workspace Integration: OAuth-based authentication for Gmail and Sheets APIs
- Internal Use Only: Configured for your organization's workspace members
- Smart Navigation: Auto-opens the right tab based on setup completion
- Auto-Save Configuration: All settings save automatically on blur
- Config Tab: Connect Google account, configure sheets, and select LLM model
- Context Tab: Create and edit email templates with variable placeholders
- Email Tab: Generate personalized emails, send to contacts, and track status
- Privacy Protected: Contact data never sent to AI - only your template
- Persistent Storage: Configuration and model selections saved across restarts
Prerequisites:
- Google Workspace organization
- Google Cloud Project with billing enabled
- Admin access to configure OAuth and Secret Manager
Setup Steps:
-
OAuth Configuration - See OAUTH_SETUP.md
- Create Google Cloud Project
- Enable Gmail API, Google Sheets API, and Secret Manager API
- Configure OAuth consent screen as "Internal"
- Create OAuth credentials
- Add credentials to
.envfile
-
Secret Manager Setup - See SECRET_MANAGER_SETUP.md
- Create secret
llm-api-keyin Secret Manager - Store your Gemini API key (or OpenAI key)
- Grant IAM permissions to users
- Update
GCP_PROJECT_IDin.env
- Create secret
-
Build and Distribute
npm install npm run electron:build
- Distribute the packaged app to team members
- Users will authenticate via OAuth on first run
Once the app is set up by your admin:
- Launch the app - It will open on the Configuration tab
- Connect Google Account:
- Click "Connect Google Account"
- Authorize in your browser
- Grant permissions for Gmail, Sheets, and Secret Manager
- Configure Integration:
- Enter your name and Gmail address (auto-saves on blur)
- Paste your Google Sheet URL
- Test the sheet connection
- Select LLM Model:
- Click "Fetch Models" to load available Gemini models
- Select your preferred model (e.g., gemini-1.5-flash)
- Settings save automatically
- Create Template - Navigate to Context tab
- Write your email template
- Use
{{firstName}}and{{lastName}}placeholders
- Send Emails - Navigate to Email tab
- Generate personalized emails with AI
- Review, edit, and send
The app will remember your settings and automatically open the Email tab on next launch.
See USER_SETUP_GUIDE.md for detailed instructions and troubleshooting.
# Copy environment template
cp .env.example .env
# Add your OAuth credentials and GCP project ID to .env:
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
GCP_PROJECT_ID=your-project-id
# Install dependencies
npm install
# Run in development mode
npm run electron:dev
# Build for production
npm run electron:build- OAuth 2.0: All Google API access via user's OAuth tokens
- Secret Manager: LLM API key stored centrally, fetched per-request
- Encrypted Storage: Configuration stored using electron-store encryption
- Content Security Policy: Strict CSP in production, relaxed for HMR in dev
- Context Isolation: Electron security best practices enabled
See SECURITY.md for detailed security architecture.
-
Main Process (
src/main/):index.ts- Electron app lifecycle and window managementgmail.ts- Gmail API OAuth and email sendingsheets.ts- Google Sheets API integrationsecrets.ts- Secret Manager API clientpreload.ts- Secure IPC bridge
-
Renderer Process (
src/renderer/):App.tsx- Main app with smart tab navigationcomponents/ConfigTab.tsx- Auto-save configuration UIcomponents/ContextTab.tsx- Template editorcomponents/EmailTab.tsx- Email generation and sendingservices/llm.ts- LLM API integration (Gemini/OpenAI)
-
Download the app:
- Go to the Releases page: https://github.com/democracy-lab/ai-mail/releases
- Look for the latest release (e.g.,
v1.0.0). - Download the
ai-mail-setup-X.X.X.exe(NSIS Installer) orai-mail-portable-X.X.X.exe(Run without installing).
-
First-time setup:
- Launch the app. The "Smart Navigation" will guide you through the initial configuration:
- User Info: Enter your name and work email.
- Google Account: Sign in with your work account (OAuth).
- Google Sheet: Paste the link to your contact spreadsheet.
- LLM: Select your preferred AI model (Gemini/OpenAI).
- Launch the app. The "Smart Navigation" will guide you through the initial configuration:
-
Secure API Access: The app uses Google Cloud Secret Manager to fetch the shared API key. Ensure your Google account has been granted the
Secret Manager Secret Accessorrole in the GCP project.
-
Clone the repository:
git clone https://github.com/democracy-lab/ai-email.git cd ai-email -
Install dependencies:
npm install
-
Environment Setup:
- Copy
.env.exampleto.env. - Configure
GCP_PROJECT_ID=ai-mail-app-486520. - Follow OAUTH_SETUP.md for Google credentials.
- Copy
-
Run in Development:
npm run dev
-
Build for Production:
- On Windows, enable Developer Mode in settings to allow symbolic links.
- Run:
npm run electron:build.
The app validates and auto-saves all settings:
- User Information: Name and Gmail address (validates email format)
- Google Account: OAuth connection with test button
- Google Sheets:
- Paste full spreadsheet URL (auto-extracts ID)
- Specify sheet tab name
- Validates required columns
- LLM Configuration:
- Fetch available models from API
- Select model (saves with cached model list)
- API key managed centrally via Secret Manager
Status messages appear inline with each section showing success/error feedback.
- Write your email template in the rich text editor
- Use placeholders:
{{firstName}},{{lastName}} - Template auto-saves as you type
- Placeholders replaced locally after AI generation
Important: Only the template is sent to the LLM. Contact names are filled in afterwards, preserving privacy.
- Load Contacts: Fetches from Google Sheets via API
- Generate Email:
- Sends template to LLM
- LLM creates personalized email structure
- Placeholders replaced with contact info
- Review & Edit: Full rich-text editing before sending
- Send:
- Test button sends to yourself
- Send button uses Gmail API
- Updates sheet with status and Gmail Message ID
- Navigate: Previous/Next buttons to process multiple contacts
Required columns:
Email Address- Contact's emailFirst Name- For {{firstName}} placeholderLast Name- For {{lastName}} placeholder
Optional columns (auto-created if missing):
Team Member- Who sent the email (your name)Status- sent/skipped/errorDate Sent- TimestampGmail Message ID- For tracking
The app validates column presence and shows clear error messages if sheet structure is incorrect.
Multiple team members can use the app simultaneously:
- Each person authenticates with their own Google account
- Shared LLM API key accessed via Secret Manager (requires IAM permission)
- App updates "Team Member" column after sending
- Contacts with filled "Team Member" column are skipped
- No conflicts or overwrites between users
- Electron - Desktop application framework
- React 18 - UI framework
- TypeScript - Type safety throughout
- Vite - Fast build tool with HMR
- Tailwind CSS - Utility-first styling
- react-quill - Rich text email editor
- googleapis - Gmail and Sheets API clients
- google-auth-library - OAuth 2.0 authentication
- @google-cloud/secret-manager - Centralized API key storage
- electron-store - Encrypted local configuration
- Content Security Policy - XSS protection
Required in .env:
GOOGLE_CLIENT_ID=xxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxx
GCP_PROJECT_ID=your-gcp-projectThe app requests these scopes:
https://www.googleapis.com/auth/gmail.send- Send emailshttps://www.googleapis.com/auth/gmail.readonly- Test connectionhttps://www.googleapis.com/auth/spreadsheets- Read/write sheetshttps://www.googleapis.com/auth/cloud-platform- Access Secret Manager
- Development: Relaxed CSP allows
unsafe-evalfor Vite HMR - Production: Strict CSP with no eval, whitelisted API domains
- See SECURITY.md for details
Google Account won't connect
- Check OAuth credentials in
.env - Verify OAuth consent screen is set to "Internal"
- Ensure user is part of your Google Workspace
Can't access Secret Manager
- Verify user has "Secret Manager Secret Accessor" IAM role
- Check secret name is exactly
llm-api-key - Confirm
GCP_PROJECT_IDmatches your GCP project
Sheet validation fails
- Required columns must be exact:
Email Address,First Name,Last Name - Column headers must be in the first row
- Verify user's Google account has edit access to sheet
Model fetch fails
- Ensure Secret Manager connection works
- Check API key in Secret Manager is valid
- Try disconnecting and reconnecting Google account
LLM errors
- Verify model is selected in Configuration
- Check API key in Secret Manager is valid
- For Gemini: ensure model name format is correct (e.g.,
gemini-1.5-flash)
List formatting problems
- LLM uses single newlines for list items
- Double newlines create paragraph breaks
- Check generated email preview before sending
See USER_SETUP_GUIDE.md for more troubleshooting steps.
- README.md - This file, overview and quick start
- OAUTH_SETUP.md - Complete OAuth configuration guide
- SECRET_MANAGER_SETUP.md - Secret Manager setup instructions
- SECURITY.md - Security architecture and CSP details
- USER_SETUP_GUIDE.md - End-user setup and troubleshooting
- spec.md - Technical specification and architecture
MIT