DraftPilot
AI writes Gmail drafts. You review. Undeleted drafts auto-send.
Most AI email tools send for you or wait for you to click Send. DraftPilot does neither: it drafts to Gmail, you review, and if you don't delete it, it fires automatically after 6 hours. Human judgment, zero manual effort.
How It Works
1. You provide a CSV of companies + a YAML profile with your info
2. DraftPilot generates personalized emails via LLM
3. Drafts appear in Gmail under a labeled folder
4. You review - delete the bad ones, leave the good ones
5. After 6 hours - undeleted drafts auto-send (the dead man's switch)
CSV + Profile --> LLM generates email --> Gmail draft created
|
You review in Gmail
/ \
Delete it Leave it
| |
Cancelled Auto-sends
after 6 hours
Features
- Dead man's switch - Drafts auto-send after a configurable delay. Delete to cancel, ignore to approve.
- AI personalization - Uses any OpenAI-compatible LLM (Cerebras, Groq, OpenAI) to write emails tailored to each company
- 30+ anti-cliche rules - A rules engine that prevents "I hope this finds you well", "passionate", and other template-sounding phrases
- Multi-source email finder - Scrapes job boards, company websites, and Hunter.io to find real recruitment emails
- MX validation - Checks if email domains actually accept mail before sending
- Full audit trail - SQLite database tracks every email: pending, drafted, sent, cancelled, error
- HTML emails - Clickable links for portfolio and CV in the signature
- Bilingual - Generates emails in French or English based on company language
- Rate limiting - Smart backoff and retry logic for LLM APIs
- Cron-ready - Set it up once and it runs daily
Quick Start
Install
pip install draftpilot
Or from source:
git clone https://github.com/Alae-J/draftpilot.git
cd draftpilot
pip install -e .
Configure
# Copy example configs
mkdir -p config
cp examples/profile.yaml config/
cp examples/templates.yaml config/
# Edit with your info
nano config/profile.yaml
# Set your LLM API key
export CEREBRAS_API_KEY="your-key-here"
Authenticate with Gmail
draftpilot auth
This opens a browser for Google OAuth. You need a Google Cloud project with Gmail API enabled. Setup guide.
Run
# Generate drafts from a company list
draftpilot draft --csv companies.csv --batch 20
# Check your Gmail - review the drafts under the "DraftPilot" label
# Delete any you don't like
# Trigger the dead man's switch (or let cron do it)
draftpilot send
# Check stats
draftpilot status --list
CLI Commands
| Command | Description |
|---|---|
draftpilot draft |
Generate personalized email drafts |
draftpilot send |
Auto-send drafts past their validation window |
draftpilot status |
Display pipeline statistics |
draftpilot find |
Find recruitment emails via web scraping |
draftpilot validate |
Validate emails (syntax + MX check) |
draftpilot auth |
Gmail OAuth setup |
Draft options
draftpilot draft --csv companies.csv # company list
draftpilot draft --batch 30 # emails per run (default: 50)
draftpilot draft --delay 12 # hours before auto-send (default: 6)
draftpilot draft --dry-run # generate without creating drafts
Find emails
# Input: CSV with company_name and website columns
# Output: CSV with company_name, email, website, description, language, sector
draftpilot find --csv company_names.csv
draftpilot find --csv company_names.csv --no-hunter # skip Hunter.io
draftpilot find --csv company_names.csv --no-llm # skip LLM descriptions
Configuration
Profile (config/profile.yaml)
Your personal info, skills, experience, and preferences. See examples/profile.yaml for the full template.
Key sections:
name: "Your Name"
email: "you@gmail.com"
phone: "+1 234 567 8900"
portfolio: "https://your-site.com"
education:
school: "Your University"
school_short: "University" # used in subject lines
experience:
- name: "Project X"
role: "Developer"
description: "What you built"
tech: "Python, React"
# LLM provider (any OpenAI-compatible API)
llm:
base_url: "https://api.cerebras.ai/v1"
model: "qwen-3-235b-a22b-instruct-2507"
api_key_env: "CEREBRAS_API_KEY"
# Email signature (uses $variable substitution)
signature:
fr: "$name | $school_short\n$phone | <a href=\"$portfolio\">Portfolio</a>"
en: "$name | $school_short\n$phone | <a href=\"$portfolio\">Portfolio</a>"
Templates (config/templates.yaml)
Controls the email structure and rules. Ships with French and English templates. See examples/templates.yaml.
The rules engine enforces:
- Greeting on its own line
- Company-first opening (not self-introduction)
- No cliches ("I hope this finds you well", "passionate", etc.)
- Word limit (150 words max)
- Proper accent marks in French
- Call-to-action with specific days
- And 20+ more rules
LLM Providers
DraftPilot works with any OpenAI-compatible API:
| Provider | Free Tier | Model |
|---|---|---|
| Cerebras | 14,400 req/day, 1M tokens/day | Qwen 235B |
| Groq | 1,000 req/day, 100K tokens/day | Llama 3.3 70B |
| OpenAI | Pay per use | GPT-4o |
| Together | Free tier available | Llama 3.3 70B |
Just change llm.base_url and llm.model in your profile.
Gmail Setup
- Go to Google Cloud Console
- Create a project and enable the Gmail API
- Go to APIs & Services > Credentials > Create Credentials > OAuth 2.0 Client ID
- Select Desktop app, download the JSON
- Save as
config/credentials.json - Add yourself as a test user under OAuth consent screen > Test users
- Run
draftpilot auth
Cron Setup (Automated Daily Runs)
# Edit crontab
crontab -e
# Add these lines:
CEREBRAS_API_KEY=your-key-here
# Generate drafts every day at 8am
0 8 * * * cd /path/to/project && /path/to/venv/bin/draftpilot draft >> logs/generate.log 2>&1
# Check and send every 30 minutes
*/30 * * * * cd /path/to/project && /path/to/venv/bin/draftpilot send >> logs/send.log 2>&1
Email Finder Pipeline
DraftPilot includes a multi-source email finder that scrapes real email addresses:
- Rekrute.com - Morocco's largest job board (extracts emails from job postings)
- Company websites - Scrapes /contact, /careers, /recrutement pages for mailto: links
- Hunter.io API - Domain-based email search (50 free credits/month)
- MX validation - Filters out domains that don't accept email
# Input: just company names and websites
echo "company_name,website
TechCorp,https://techcorp.com
StartupX,https://startupx.ma" > targets.csv
# Find their emails
draftpilot find --csv targets.csv
# Output: targets_found.csv with email, description, language, sector
Responsible Use
This tool is designed for targeted, relevant, professional outreach - not bulk spam.
By using this tool, you agree to:
- Comply with CAN-SPAM, GDPR, CASL, and your local email laws
- Only email addresses where you have a legitimate professional basis
- Include opt-out mechanisms in all sent emails
- Honor opt-out requests immediately
- Not use this tool to send unsolicited bulk commercial email
The authors are not responsible for misuse. Email scraping and cold outreach may be regulated or restricted in your jurisdiction.
Project Structure
draftpilot/
├── src/draftpilot/
│ ├── cli.py # Typer CLI with 6 subcommands
│ ├── config.py # Config loading, LLM client, signature rendering
│ ├── generator.py # LLM email generation + post-processing
│ ├── drafts.py # Phase 1: CSV -> LLM -> Gmail drafts
│ ├── sender.py # Phase 2: Dead man's switch auto-sender
│ ├── gmail.py # Gmail API wrapper
│ ├── db.py # SQLite state tracking
│ ├── finder.py # Multi-source email discovery
│ ├── validator.py # Email syntax + MX validation
│ └── dashboard.py # Rich terminal stats display
├── config/
│ ├── profile.yaml # Your info (not committed)
│ └── templates.yaml # Email templates + rules
├── examples/ # Example configs to copy
├── tests/
├── pyproject.toml
└── LICENSE # Apache 2.0
Contributing
See CONTRIBUTING.md for setup instructions and guidelines.
License
Apache 2.0 - See LICENSE for details.
Metadata
Release files for draftpilot 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| draftpilot-0.1.0.tar.gz | 32.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| draftpilot-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 64.5 kB
Release files / draftpilot-0.1.0.tar.gz
| Download URL | draftpilot-0.1.0.tar.gz |
|---|---|
| Size | 32.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a6df7f23835946835f1d07e711185ca69daf9e42f66c7108d845287a6f8e9c89
|
|
BLAKE2b-256 checksum How to use checksums |
c7ad05aa5956795ff58d8c4ae24ef0da5ff5d065eccc4de6b7caa7de576700d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / draftpilot-0.1.0-py3-none-any.whl
| Download URL | draftpilot-0.1.0-py3-none-any.whl |
|---|---|
| Size | 31.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fa649092d1940ea491a8cf66d9266367d3e3e880a6d8606a19cd6c3e6517f121
|
|
BLAKE2b-256 checksum How to use checksums |
b15169be1a68bdb9318cde66289b25d2091d8bd275e38ec59e7cde37ecd0d6c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|