Back to Projects
Email Automation

Bhavya Mailer

"Self-hosted Gmail outreach automation with intelligent follow-up sequencing"

0
Poll Interval
0
Contact States
0
Encryption
0-ms
Cold Storage

░▒▓ Overview

A self-hosted Gmail outreach tool that monitors every email Bhavya sends, automatically queues follow-ups, and handles replies, bounces, and out-of-office responses — all without leaving his own machine.

Built around a privacy-first principle: Gmail is connected via Google OAuth, tokens are AES-256-GCM encrypted at rest, and no email body content is ever logged. The system watches for events, not content.

ACTIVE — follow-ups queued
REPLIED — cancelled
BOUNCED — daemon detected
OOO — follow-ups continue
PAUSED — manually held
BLACKLISTED — never tracked
COMPLETED — all sent
IGNORED — thread removed

░▒▓ How It Works

[@]
Send
Bhavya sends cold email
[~]
Poll
History API every 15 min
[?]
Classify
Reply / Bounce / OOO
[T]
Schedule
Working hours gate
>>
Follow Up
Reply in same thread

░▒▓ Key Features

[@]

Gmail History API Polling

Uses Gmail's incremental History API every 15 minutes — no Pub/Sub, no public endpoint required. Works perfectly on a local machine.

[!]

Bounce Detection

Parses MAILER-DAEMON replies to detect hard bounces. Immediately cancels all pending follow-ups and marks contact as BOUNCED.

[~]

OOO Handling

Detects auto-replies, extracts alt contact email from OOO body, and optionally emails the alt contact — all without stopping scheduled follow-ups.

[T]

Working Hours Gate

Configurable timezone and send window. Bhavya's timezone is the source of truth — the server's local time is never used for scheduling.

{{}}

Template System

Per-follow-up templates with {{name}}, {{company}}, {{days}} variables. Each follow-up number has its own editable template.

[#]

Thread-Safe Follow-ups

Follow-ups are replies in the original Gmail thread, not new emails. If Bhavya manually follows up, the system detects it and resets the clock.

░▒▓ Tech Stack

Framework

Next.js 14
App Router — API routes + dashboard UI in one repo
TypeScript
Strict mode throughout

Auth & Security

NextAuth v5
Google OAuth — connects Bhavya's own Gmail account
AES-256-GCM
OAuth tokens encrypted at rest — never stored plaintext

Data

Prisma + SQLite
Self-hosted — no cloud DB, everything stays local
Zod
Validates all API request bodies at the boundary

Jobs

BullMQ
Background workers for polling and follow-up delivery
Redis
Queue backend for BullMQ job scheduling

Email

Gmail History API
Incremental polling — no Pub/Sub, no public webhook needed
googleapis
Official Google client library for Gmail send + thread API

Testing

Vitest
Unit + integration tests with 80%+ coverage gate
Playwright
E2E smoke tests on seeded SQLite database
MSW v2
Mocks Gmail API in integration tests — no real network calls

░▒▓ Key Decisions

The architecture was driven by the constraint of running fully self-hosted:

# Why History API over Pub/Sub?
# Pub/Sub requires a public HTTPS endpoint.
# Self-hosted on localhost = no domain = no Pub/Sub.
# History API polling via BullMQ is clean, testable, reliable.

polling_strategy:
  method:     Gmail History API (incremental)
  interval:  15 minutes (BullMQ repeatable job)
  no_webhook: true  # works on any machine, no port forwarding

# Why SQLite over Postgres?
# Single-user tool. One person, one machine.
# Zero ops overhead. Ships with the app.

follow_up_threading:
  method: Gmail threadId reply (not new email)
  subject: "Re: {original_subject}"
  clock_reset_on_manual: true  # Bhavya replies = reset 7-day timer

░▒▓ My Role

>_

Sole Developer

Designed and built the entire system end-to-end — from the Gmail History API polling loop and BullMQ job workers to the Next.js dashboard UI and all six REST API layers.

[*]

Privacy Architecture

Designed the AES-256-GCM token encryption layer, scoped all DB queries to userId from session, and enforced a principle that email content is never stored or logged — only metadata.

[ ]

Test Infrastructure

Built the full Vitest integration test suite: per-suite temp SQLite databases, MSW v2 Gmail API mocking, BullMQ module mocks, and a GitHub Actions CI pipeline with unit → integration → E2E ordering.