Dead man's switch email outreach with AI personalization
Project description
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.
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 draftpilot-0.1.0.tar.gz.
File metadata
- Download URL: draftpilot-0.1.0.tar.gz
- Upload date:
- Size: 32.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6df7f23835946835f1d07e711185ca69daf9e42f66c7108d845287a6f8e9c89
|
|
| MD5 |
58856d053da2db73cb38979cf523a0cd
|
|
| BLAKE2b-256 |
c7ad05aa5956795ff58d8c4ae24ef0da5ff5d065eccc4de6b7caa7de576700d1
|
File details
Details for the file draftpilot-0.1.0-py3-none-any.whl.
File metadata
- Download URL: draftpilot-0.1.0-py3-none-any.whl
- Upload date:
- Size: 31.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa649092d1940ea491a8cf66d9266367d3e3e880a6d8606a19cd6c3e6517f121
|
|
| MD5 |
2f22a94972fa5c1177ed6d0b221ed327
|
|
| BLAKE2b-256 |
b15169be1a68bdb9318cde66289b25d2091d8bd275e38ec59e7cde37ecd0d6c4
|