AI-Powered Email Intelligence Platform - Real-time IMAP synchronization with AI categorization, Elasticsearch search, and Slack integration.
- Features
- Architecture
- Tech Stack
- Prerequisites
- Quick Start
- Detailed Setup
- Configuration
- Usage
- API Documentation
- Project Structure
- Troubleshooting
- Contributing
- Multi-Account Support: Sync multiple IMAP accounts simultaneously (minimum 2 accounts)
- Persistent IMAP Connections: Uses IMAP IDLE mode for instant email notifications (no polling/cron jobs)
- Historical Backfill: Automatically fetches and indexes the last 30 days of emails on first sync
- Real-time Updates: New emails appear instantly in the dashboard via WebSocket
- Full-Text Search: Search across email subject, body, sender name, and email address
- Locally Hosted: Docker-based Elasticsearch instance for complete data privacy
- Powerful Filtering: Filter by account, folder (INBOX, Sent, Archive), and AI labels
- Fast & Scalable: Elasticsearch indexing ensures sub-second search results
Intelligent email classification using rule-based AI with the following labels:
- Interested π’ - Positive responses, meetings accepted, engagement signals
- Meeting Booked π΅ - Calendar invites, confirmed meetings, scheduled calls
- Not Interested β« - Rejections, opt-outs, negative responses
- Spam π΄ - Marketing emails, automated messages, suspicious content
- Out of Office π‘ - Auto-replies, vacation messages
- Slack Notifications: Instant notifications to Slack for every "Interested" email
- Webhook Support: Trigger external automations via webhooks for "Interested" emails
- Configurable: Easy webhook URL configuration via environment variables
NEW: Intelligent reply suggestions using Retrieval-Augmented Generation with OpenAI
- Context-Aware Responses: AI analyzes email content and retrieves relevant context from your knowledge base
- OpenAI GPT-4o-mini: Generates professional, personalized reply suggestions
- Vector Embeddings: Uses text-embedding-3-small for semantic similarity search
- Knowledge Base: Store training data with context-response pairs
- One-Click Copy: Copy suggested replies to clipboard
- Real-Time Generation: Get AI suggestions directly in the email dashboard
- Persistent Storage: All suggestions saved to database for tracking and analytics
Example Use Case: Job application emails
- Training data: "Include meeting booking link: https://cal.com/example when recruiter shows interest"
- AI automatically suggests replies with appropriate links when detecting recruitment interest
- Professional tone maintained across all suggestions
- Modern Design: Beautiful gradient-based UI with Remix Icons
- Real-time Stats: Live email count cards (Total, Interested, Meetings, Not Interested)
- Live Updates: WebSocket-powered real-time email list updates
- Color-Coded Labels: Visual categorization with professional color scheme
- Responsive: Mobile-friendly layout with Tailwind CSS v4
- Advanced Filtering: Filter by account, folder, and search functionality
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Frontend (Next.js) β
β http://localhost:3000 β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Dashboard β β Search β β Filters β β
β β (Stats UI) β β (Real-time) β β (Account/Folder)β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β WebSocket + REST API
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Backend (Node.js + Express) β
β http://localhost:4000 β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β API Server β β WebSocket β β IMAP Sync β β
β β (Express) β β (Socket.IO) β β Service β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β AI Classifierβ β Labeler β β Event Bus β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββΌβββββββββββββββββββββ
βΌ βΌ βΌ
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β PostgreSQL β βElasticsearch β β Slack β
β (Prisma) β β (Search) β β (Webhooks) β
β localhost:5432β β localhost:9200β β β
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
- IMAP Service connects to Gmail accounts via IDLE mode
- New emails trigger events on the event bus
- AI Classifier analyzes and labels emails
- Persistence Layer stores in PostgreSQL + Elasticsearch
- WebSocket broadcasts to connected frontend clients
- Slack Integration sends notifications for interested emails
- Frontend receives real-time updates and displays in UI
- Next.js 14.0.0 - React framework with API routes
- TypeScript 5.9.3 - Type-safe development
- Tailwind CSS 4.0 - Modern utility-first CSS
- React Icons - Professional Remix icon library
- Socket.IO Client - Real-time WebSocket communication
- SWR - React hooks for data fetching
- Node.js (ES Modules) - JavaScript runtime
- Express 4.x - Web framework for REST API
- Socket.IO 4.x - WebSocket server for real-time updates
- ImapFlow - IMAP client with IDLE support
- Prisma - Modern database ORM
- Elasticsearch Client - Search engine integration
- Pino - Fast JSON logger
- OpenAI 6.8.1 - AI-powered reply suggestions with GPT-4o-mini and embeddings
- PostgreSQL 16 - Primary database
- Elasticsearch 8.15.3 - Search and analytics engine
- Kibana 8.15.3 - Elasticsearch visualization
- Docker Compose - Container orchestration
Before you begin, ensure you have the following installed:
For each Gmail account you want to sync:
- Enable 2-Factor Authentication in your Google Account
- Go to: https://myaccount.google.com/apppasswords
- Create an App Password for "Mail"
- Copy the 16-character password (format:
xxxx xxxx xxxx xxxx)
git clone https://github.com/sh3bh1t/ReachInbox.git
cd ReachInboxdocker compose up -dWait 30 seconds for Elasticsearch to initialize.
Verify services are running:
docker psYou should see:
onebox_pg(PostgreSQL)onebox_es(Elasticsearch)onebox_kibana(Kibana)
cd apps/imap-sync
# Install dependencies
pnpm install
# Generate Prisma client
npx prisma generate
# Run database migrations
npx prisma migrate deploy
# Start backend server
pnpm devBackend will start on port 4000 and immediately begin syncing emails.
Open a new terminal:
cd apps/web
# Install dependencies (if not already done)
pnpm install
# Start Next.js development server
pnpm devFrontend will start on port 3000
π Open your browser: http://localhost:3000
You should see:
- Beautiful dashboard with gradient UI
- Stats cards (Total, Interested, Meetings, Not Interested)
- Real-time connection indicator (green dot = connected)
- Email list (will populate in 1-2 minutes as sync completes)
NODE_ENV=development
# Account A (Gmail)
A_IMAP_HOST=imap.gmail.com
A_IMAP_PORT=993
A_IMAP_SECURE=true
A_IMAP_USER=your-email@gmail.com
A_IMAP_PASS=your-app-password
A_FOLDERS=INBOX
# Account B (Gmail)
B_IMAP_HOST=imap.gmail.com
B_IMAP_PORT=993
B_IMAP_SECURE=true
B_IMAP_USER=second-email@gmail.com
B_IMAP_PASS=second-app-password
B_FOLDERS=INBOX
# Database (update with your PostgreSQL credentials)
DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=public"
# Elasticsearch
ELASTIC_URL=http://localhost:9200
# Slack Webhook (Optional)
INTERESTED_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
# OpenAI API (for AI-powered suggested replies)
OPENAI_API_KEY=sk-proj-...your-api-key...
OPENAI_CHAT_MODEL=gpt-4o-mini
OPENAI_EMBED_MODEL=text-embedding-3-smallImportant:
- Replace
your-email@gmail.comwith your actual Gmail addresses - Replace
your-app-passwordwith the 16-character App Password from Google - Replace
USER:PASSWORD@HOST:PORT/DATABASEwith your PostgreSQL credentials:- For local Docker setup:
onebox:onebox@localhost:5432/onebox - For custom setup: Update with your database credentials
- For local Docker setup:
- OpenAI API Key: Get from https://platform.openai.com/api-keys (required for AI reply suggestions)
- You can add more accounts by following the same pattern (C_, D_, etc.)
cd apps/imap-sync
# Generate Prisma client (do this after any schema changes)
npx prisma generate
# Apply migrations
npx prisma migrate deploy
# Optional: Open Prisma Studio to view data
npx prisma studioNEXT_PUBLIC_API_URL=http://localhost:4000This tells the frontend where to find the backend API.
- Visit https://platform.openai.com/api-keys
- Create a new API key
- Add to
apps/imap-sync/.env:OPENAI_API_KEY=sk-proj-...your-api-key... OPENAI_CHAT_MODEL=gpt-4o-mini OPENAI_EMBED_MODEL=text-embedding-3-small
Create your training data in apps/imap-sync/scripts/rag-bootstrap.ts:
const chunks: { text: string; source: string }[] = [
{
source: 'agenda',
text: 'I am applying for a backend engineering job position. ' +
'If the lead is interested or wants to move forward, I should share my meeting booking link: https://cal.com/example. ' +
'My goal is to be polite, concise, and always thank them for their interest.'
},
{
source: 'product',
text: 'The product I am selling is myself as a backend engineer: experience with Node.js, TypeScript, IMAP, Elasticsearch, Prisma, and Slack/webhook integrations. ' +
'I want to highlight reliability, clean code, and ability to ship end-to-end features.'
},
// Add your own context-response pairs
];cd apps/imap-sync
# Install dependencies (if not done already)
pnpm install
# Bootstrap the knowledge base with embeddings
npx tsx scripts/rag-bootstrap.tsOutput:
Embedding: agenda β I am applying for a backend engineering job position...
β
Embedded knowledge chunk (source: agenda): I am applying for a backend engineering job position...
Embedding: product β The product I am selling is myself as a backend engineer...
β
Embedded knowledge chunk (source: product): The product I am selling is myself as a backend engineer...
Done.
# Test with a sample email
npx tsx scripts/suggest-reply.tsExample Output:
--- Suggested Reply ---
Thank you for your interest! I'd be happy to discuss the backend engineering role further.
You can book a convenient time here: https://cal.com/example
Looking forward to connecting!
- Open http://localhost:3000
- Hover over any email
- Click β¨ AI Reply button
- Wait for AI to generate suggestion
- Copy suggested reply with one click
Knowledge Base Tips:
- Add context about your business, products, or services
- Include common objections and how to handle them
- Store meeting links, pricing, FAQ responses
- Update regularly based on successful email conversations
- Use descriptive
sourcetags for organization (e.g., 'pricing', 'objection', 'faq')
To add additional email accounts, edit apps/imap-sync/.env:
# Account C
C_IMAP_HOST=imap.gmail.com
C_IMAP_PORT=993
C_IMAP_SECURE=true
C_IMAP_USER=third-email@gmail.com
C_IMAP_PASS=third-app-password
C_FOLDERS=INBOX,Sent
# Account D (Yahoo example)
D_IMAP_HOST=imap.mail.yahoo.com
D_IMAP_PORT=993
D_IMAP_SECURE=true
D_IMAP_USER=your-yahoo@yahoo.com
D_IMAP_PASS=your-yahoo-app-password
D_FOLDERS=INBOXEdit apps/imap-sync/src/ai/rules.ts to modify classification logic:
// Example: Add custom rules for your business
if (subject.includes('partnership') || body.includes('collaborate')) {
return { label: 'Interested', confidence: 0.9 };
}Edit apps/imap-sync/src/imap/ImapSyncService.ts:
// Change from 30 days to 60 days
const since = new Date(Date.now() - 60 * 24 * 60 * 60 * 1000);- Search: Type keywords to search across all emails (subject, body, sender)
- Filter by Account: Select specific email account from dropdown
- Filter by Folder: Choose INBOX, Sent, or Archive
- View Labels: Color-coded badges show AI categorization
- Real-time Updates: New emails appear automatically (watch the connection status)
- AI Reply Suggestions: Hover over any email to see the β¨ AI Reply button
- Hover over any email in the inbox
- Click the "β¨ AI Reply" button (appears on hover)
- Wait 2-3 seconds while AI analyzes the email and generates suggestion
- Review the suggested reply in the purple gradient card
- Click "Copy" to copy the suggestion to clipboard
- Paste into your email client or modify as needed
Features:
- β¨ Context-aware suggestions based on your knowledge base
- π One-click copy to clipboard
- π¨ Beautiful purple gradient UI
- β‘ Fast generation (2-3 seconds)
- πΎ All suggestions saved to database
- π Re-generate anytime by clicking button again
- Click on any email card to see full details
- Emails are sorted by date (newest first)
- Today's emails show time, older emails show date
Backend Terminal will show:
π API Server running on http://localhost:4000
π WebSocket ready for real-time updates
[INFO] IMAP connected: your-email@gmail.com
[INFO] Backfilling emails since 2025-10-14
[INFO] Email indexed: Re: Important Meeting
[INFO] AI Label: Interested (confidence: 0.95)
Frontend shows:
- Green dot = WebSocket connected
- Real-time email count in stats cards
- New emails appear at the top automatically
Search emails in Elasticsearch
Query Parameters:
q(string): Search queryaccount(string): Filter by account emailfolder(string): Filter by folder namesize(number): Max results (default: 25)
Example:
curl "http://localhost:4000/search?q=meeting&account=user@gmail.com&size=10"Response:
{
"hits": [
{
"id": "email-id",
"accountUser": "user@gmail.com",
"folder": "INBOX",
"subject": "Re: Meeting Tomorrow",
"snippet": "Thanks for scheduling...",
"from": {
"name": "John Doe",
"email": "john@example.com"
},
"date": "2025-11-13T10:30:00Z",
"label": "Interested",
"uid": 12345,
"uidValidity": 1
}
]
}Get list of all synced accounts
Example:
curl http://localhost:4000/accountsResponse:
["user1@gmail.com", "user2@gmail.com"]Get AI-powered suggested reply for an email (RAG feature)
Request Body:
{
"accountUser": "user@gmail.com",
"folder": "INBOX",
"uidValidity": 1,
"uid": 12345
}Example:
curl -X POST http://localhost:4000/suggest-reply \
-H "Content-Type: application/json" \
-d '{
"accountUser": "user@gmail.com",
"folder": "INBOX",
"uidValidity": 1,
"uid": 12345
}'Response:
{
"suggestion": "Thank you for your interest! I'd be happy to discuss this further. You can book a time that works for you here: https://cal.com/example. Looking forward to connecting!"
}How it works:
- Retrieves email from database using unique identifiers
- Generates embeddings for email content using OpenAI text-embedding-3-small
- Performs semantic similarity search against knowledge base
- Feeds top 3 relevant context chunks to GPT-4o-mini
- Generates professional, contextually-appropriate reply
- Stores suggestion in database for tracking
// Connection (automatic via socket.io-client)
const socket = io('http://localhost:4000');Event: email:new
Emitted when a new email is received
socket.on('email:new', (email) => {
console.log('New email:', email.subject);
// Update UI automatically
});Payload:
{
"accountUser": "user@gmail.com",
"folder": "INBOX",
"subject": "New Lead Inquiry",
"from": {
"name": "Potential Client",
"email": "client@example.com"
},
"label": "Interested"
}ReachInbox/
βββ apps/
β βββ imap-sync/ # Backend service
β β βββ src/
β β β βββ api/ # REST API & WebSocket
β β β β βββ server.ts # Express + Socket.IO server
β β β β βββ handlers.ts # API route handlers
β β β βββ ai/ # AI classification
β β β β βββ classifier.ts
β β β β βββ rules.ts # Classification rules
β β β βββ config/
β β β β βββ env.ts # Environment config
β β β βββ consumers/
β β β β βββ Labeler.ts # AI labeling consumer
β β β βββ core/
β β β β βββ events.ts # Event bus
β β β β βββ logger.ts # Pino logger
β β β β βββ types.ts # TypeScript types
β β β βββ imap/ # IMAP sync logic
β β β β βββ ImapClient.ts
β β β β βββ ImapAccount.ts
β β β β βββ ImapSyncService.ts
β β β β βββ parsers.ts
β β β βββ integrations/
β β β β βββ SlackInterestedSink.ts
β β β βββ notifications/
β β β β βββ slack.ts
β β β β βββ webhook.ts
β β β βββ persistence/ # Database & Elasticsearch
β β β β βββ PgSink.ts # PostgreSQL sink
β β β β βββ esSink.ts # Elasticsearch sink
β β β β βββ esClient.ts
β β β β βββ esBootstrap.ts
β β β β βββ prisma.ts
β β β β βββ ...
β β β βββ index.ts # Main entry point
β β βββ prisma/
β β β βββ schema.prisma # Database schema
β β β βββ migrations/ # Database migrations
β β βββ .env # Environment variables
β β βββ package.json
β β βββ tsconfig.json
β β
β βββ web/ # Frontend (Next.js)
β βββ pages/
β β βββ _app.tsx # App wrapper
β β βββ index.tsx # Dashboard page
β β βββ api/
β β βββ search.ts # API proxy (optional)
β βββ styles/
β β βββ global.css # Tailwind CSS
β βββ .env.local # Frontend env vars
β βββ next.config.js
β βββ package.json
β βββ postcss.config.cjs
β βββ tsconfig.json
β
βββ docker-compose.yml # Docker services
βββ .gitignore
βββ README.md
# Check Docker is running
docker --version
# View container logs
docker logs onebox_pg
docker logs onebox_es
docker logs onebox_kibana
# Restart services
docker compose down
docker compose up -dError: Connection refused or index not found
Solution:
# Check Elasticsearch health
curl http://localhost:9200/_cluster/health
# Wait for status: "yellow" or "green"
# If needed, recreate index
cd apps/imap-sync
pnpm dev # Will auto-create index on startupError: Authentication failed
Solution:
- Verify Gmail App Password is correct (16 characters, no spaces)
- Check 2FA is enabled on your Google Account
- Try generating a new App Password
- Check
.envfile for typos in email/password
Error: Connection timeout
Solution:
- Check firewall settings
- Verify port 993 is not blocked
- Try different network (some corporate networks block IMAP)
Checklist:
- β
Backend is running (
http://localhost:4000/accountsreturns accounts) - β
Elasticsearch has emails (
curl http://localhost:9200/emails/_count) - β WebSocket is connected (green dot in UI)
- β Wait 1-2 minutes for initial sync to complete
Debug:
# Check backend logs for sync progress
cd apps/imap-sync
pnpm dev
# Check Elasticsearch count
curl http://localhost:9200/emails/_count
# Test API directly
curl http://localhost:4000/search?size=5Error: EADDRINUSE: address already in use
Solution:
# Find process using port 4000
netstat -ano | findstr :4000
# Kill the process (Windows)
taskkill /PID <PID> /F
# Or change port in .env
PORT=4001# Reset database (WARNING: deletes all data)
cd apps/imap-sync
npx prisma migrate reset
# Regenerate client
npx prisma generate
# Reapply migrations
npx prisma migrate deploy# Backend tests
cd apps/imap-sync
pnpm test
# Frontend tests
cd apps/web
pnpm test# Open Prisma Studio (visual database editor)
cd apps/imap-sync
npx prisma studio
# Create new migration
npx prisma migrate dev --name your_migration_name
# View database directly
psql postgresql://onebox:onebox@localhost:5432/onebox# Backend logs (pretty printed)
cd apps/imap-sync
pnpm dev
# Elasticsearch logs
docker logs onebox_es
# PostgreSQL logs
docker logs onebox_pg# Backend
cd apps/imap-sync
pnpm build
pnpm start
# Frontend
cd apps/web
pnpm build
pnpm start- Multi-account IMAP synchronization (2+ accounts)
- Real-time email sync using IMAP IDLE (no polling)
- 30-day historical email backfill
- Elasticsearch integration for full-text search
- PostgreSQL storage for reliable persistence
- AI-based email categorization (5 labels)
- Slack notifications for interested emails
- Webhook integration for automation
- WebSocket real-time updates to frontend
- Professional dashboard UI with Tailwind CSS v4
- Search by subject, body, sender
- Filter by account and folder
- Color-coded label visualization
- Real-time stats cards
- Responsive mobile-friendly design
- REST API for email search
- Docker-based infrastructure
- TypeScript throughout
- Event-driven architecture
- Prisma ORM for type-safe database queries
-
Environment Variables:
- Set
NODE_ENV=production - Use secure passwords
- Configure production Slack webhooks
- Update
NEXT_PUBLIC_API_URLto production URL
- Set
-
Database:
- Use managed PostgreSQL (AWS RDS, DigitalOcean, etc.)
- Run migrations:
npx prisma migrate deploy - Set up automated backups
-
Elasticsearch:
- Use managed Elasticsearch (Elastic Cloud, AWS OpenSearch)
- Configure authentication
- Set up index lifecycle policies
-
Backend:
- Build:
pnpm build - Use process manager (PM2, systemd)
- Set up monitoring and logging
- Configure rate limiting
- Build:
-
Frontend:
- Build:
pnpm build - Deploy to Vercel, Netlify, or custom server
- Configure CDN for static assets
- Build:
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the ISC License.
sh3bh1t
- GitHub: @sh3bh1t
- Next.js team for the amazing React framework
- Prisma for the excellent ORM
- Elastic for Elasticsearch
- The open-source community
If you encounter any issues or have questions:
- Check the Troubleshooting section
- Search existing GitHub Issues
- Create a new issue with detailed information
Built with β€οΈ using TypeScript, Next.js, and Node.js