Skip to content

Repository files navigation

EmailHelper

An AI-powered email sorting agent that classifies, prioritizes, summarizes, and organizes your inbox into IMAP folders — hosted entirely on Google Cloud Run. Supports any email provider that speaks IMAP (Gmail, Outlook, Yahoo, iCloud, Fastmail, custom servers).


What It Does

  • Connects to your email accounts via IMAP (provider-agnostic)
  • Automatically classifies every email into a category and moves it into the matching IMAP folder
  • Scores each email by priority so the important stuff rises to the top
  • Generates a one-line AI summary so you never have to open spam
  • Files receipts and bills into Receipts/YYYY/ folders organized by year
  • Bulk-cleans your existing backlog (handles thousands of emails in batches)
  • Auto-unsubscribes from mailing lists using List-Unsubscribe email headers
  • Presents everything in a clean, sortable web inbox you self-host

Email Categories & IMAP Folders

Every email is moved into its matching IMAP folder after classification. Folders are created automatically if they don't exist.

Folder What goes here
EmailHelper/ActionRequired Emails that need a reply, decision, or task
EmailHelper/JobOpportunities Recruiter outreach, interview requests, application updates
EmailHelper/Deals Promo codes, limited-time sales, subscription offers
EmailHelper/Bills Invoices, payment confirmations, bank alerts
EmailHelper/Receipts/YYYY Purchase receipts filed by year (e.g.Receipts/2024)
EmailHelper/Newsletters Subscribed digests and editorial content
EmailHelper/Personal Real humans you know
EmailHelper/Notifications App alerts, social pings, shipping updates
EmailHelper/Spam Unsolicited bulk mail, phishing attempts
EmailHelper/Trash Confirmed junk moved by the bulk cleaner

Receipts live under Bills for the catch-all but get their own year-based subfolder tree under Receipts/ for browsability.


Architecture

Email Providers (Gmail, Outlook, Yahoo, iCloud, custom IMAP)
        │
        │ IMAP (universal protocol)
        ▼
Cloud Scheduler (every 2 min)
        │ triggers
        ▼
Cloud Run Job: email-poller
    ├── Connect to each account's IMAP server
    ├── Fetch unseen emails since last check (cursor per account)
    ├── Publish raw emails → Cloud Pub/Sub
    └── Update last_checked timestamp in Firestore

Cloud Pub/Sub Topic: raw-emails
        │ triggers (one message per email)
        ▼
Cloud Run Job: email-processor
    ├── Parse email (headers, body, attachments metadata)
    ├── Call Claude API (Sonnet) → category + priority score + summary
    ├── Store full email body → Cloud Storage bucket (email-bodies/)
    ├── Store attachments → Cloud Storage bucket (email-attachments/)
    ├── Move email into correct IMAP folder
    │   └── Receipts → Receipts/YYYY subfolder by email date
    └── Write metadata + AI results → Firestore

Cloud Run Job: bulk-cleaner          [on-demand]
    ├── Fetch ALL emails (not just unseen) — handles existing backlog
    ├── Dry-run mode: shows what would be moved/deleted first
    ├── Classifies in batches (100 at a time, rate-limit aware)
    ├── Logs results → Cloud Storage bucket (job-logs/)
    └── Moves confirmed spam/junk → IMAP Trash

Cloud Run Job: unsubscriber          [on-demand]
    ├── Reads List-Unsubscribe headers from classified newsletters
    ├── Fires HTTP unsubscribe requests or sends unsubscribe reply emails
    ├── Marks sender as unsubscribed in Firestore (never fires on bills/banks)
    ├── Logs all actions → Cloud Storage bucket (job-logs/)
    └── Moves existing emails from unsubscribed senders → Trash

Cloud Run Service: email-api         [always on]
    ├── User account management
    ├── IMAP credential storage (via Secret Manager)
    ├── REST API consumed by UI
    ├── Trigger endpoints for bulk-cleaner and unsubscriber
    └── Future: webhook receiver for Gmail/Outlook push

Cloud Run Service: email-ui          [always on]
    └── Next.js inbox — sorted, filtered, summarized, folder view

Firestore (free tier)
    ├── users/
    ├── email_accounts/      (per-user IMAP configs)
    ├── emails/              (metadata + AI labels + GCS body reference)
    ├── polling_state/       (last_checked cursor per account)
    └── unsubscribe_log/     (sender → status + timestamp)

Cloud Storage buckets (free tier — 5GB)
    ├── email-bodies/        (full email text, one file per email)
    ├── email-attachments/   (attachment files)
    └── job-logs/            (bulk cleaner + unsubscriber run reports)

Secret Manager
    ├── IMAP credentials (encrypted)
    ├── OAuth tokens (future: Gmail API, Microsoft Graph)
    └── ANTHROPIC_API_KEY

IMAP Folder Structure

Folders are created inside an EmailHelper/ namespace to keep them separate from your existing inbox structure.

EmailHelper/
├── ActionRequired
├── JobOpportunities
├── Deals
├── Bills
├── Newsletters
├── Personal
├── Notifications
├── Spam
├── Trash
└── Receipts
    ├── 2020
    ├── 2021
    ├── 2022
    ├── 2023
    ├── 2024
    ├── 2025
    └── 2026

Core Components

Email Poller

Cloud Run Job triggered every 2 minutes by Cloud Scheduler. Connects to each registered IMAP account, fetches emails received since the last check (tracked by a cursor in the database), and publishes them to Pub/Sub. Exits after each run — no persistent connection required.

Email Processor

Cloud Run Job triggered by each Pub/Sub message. Parses the raw email, sends it to Claude API for classification, then moves the email into the correct IMAP folder. Receipts and bills get an extra step: the email date is extracted and used to route them into the correct Receipts/YYYY subfolder.

Bulk Cleaner

On-demand Cloud Run Job for processing your existing email backlog (tested with 6,000+ emails). Runs in two modes:

  • Dry run — classifies and previews what would be moved, no changes made
  • Execute — moves emails in batches of 100, respects Claude API rate limits, logs all actions

Moves confirmed spam and junk to IMAP Trash. Does not permanently delete — you review and empty trash yourself.

Unsubscriber

On-demand Cloud Run Job that reads List-Unsubscribe headers (RFC 2369) from classified newsletters and marketing emails. Fires unsubscribe requests via HTTP (for URL-type headers) or sends an unsubscribe reply email (for mailto: headers). Blocked from running on emails categorized as bills, banks, job opportunities, or action-required. After unsubscribing, moves all existing emails from that sender to Trash.

API Service

FastAPI service — the only always-running component. Handles IMAP credential management, serves the REST API to the UI, and exposes trigger endpoints to launch the bulk cleaner and unsubscriber jobs on demand.

UI Service

Next.js web app. Displays your sorted inbox grouped by folder/category, shows AI summaries, priority scores, and lets you trigger bulk actions. Accessible from any browser — you host it, no third party sees your emails.


Provider Support

Phase 1 — IMAP Universal (current)

Provider IMAP Host Notes
Gmail imap.gmail.com:993 Requires App Password if 2FA enabled
Outlook / Hotmail outlook.office365.com:993 Requires App Password
Yahoo imap.mail.yahoo.com:993 Requires App Password
iCloud imap.mail.me.com:993 Requires App-Specific Password
Fastmail imap.fastmail.com:993 Standard IMAP
Custom server configurable Any IMAP-compliant server

Phase 2 — Push Notifications (planned)

Replace polling with real-time push for supported providers:

  • Gmail: Gmail API + Cloud Pub/Sub watch
  • Outlook: Microsoft Graph API subscriptions

GCP Services Used

Service Free Tier Purpose
Cloud Run 2M requests/mo, 360K vCPU-sec API, UI, poller, processor, bulk cleaner, unsubscriber
Cloud Pub/Sub 10GB messages/month Email queue between poller and processor
Firestore 1GB, 50K reads/day, 20K writes/day Email metadata, labels, user state, unsubscribe log
Cloud Storage 5GB storage, 1GB egress/month Email bodies, attachments, job logs
Cloud Scheduler 3 free jobs Poller cron every 2 minutes
Secret Manager 6 secret versions free Credentials + API keys
Artifact Registry 500MB free Docker images

Infrastructure cost: $0/month within free tier limits. Only real cost: Claude Sonnet API — ~$10–15 one-time for the 6,000 email bulk run, ~$0.10/day ongoing.


Project Structure

EmailHelper/
├── services/
│   ├── api/                      # FastAPI — auth, REST endpoints, job triggers
│   │   ├── Dockerfile
│   │   ├── main.py
│   │   ├── routers/
│   │   │   ├── accounts.py       # IMAP account CRUD
│   │   │   ├── emails.py         # Fetch/filter classified emails
│   │   │   ├── jobs.py           # Trigger bulk-cleaner / unsubscriber
│   │   │   └── auth.py           # User authentication
│   │   └── providers/
│   │       ├── base.py           # Abstract EmailProvider interface
│   │       └── imap.py           # Generic IMAP + folder management
│   ├── processor/                # Cloud Run Job — AI classification + folder move
│   │   ├── Dockerfile
│   │   ├── main.py
│   │   ├── classifier.py         # Claude Sonnet API integration
│   │   ├── folder_router.py      # IMAP folder move logic + Receipts/YYYY routing
│   │   └── body_store.py         # Upload email body/attachments to GCS
│   ├── poller/                   # Cloud Run Job — IMAP polling
│   │   ├── Dockerfile
│   │   └── main.py
│   ├── bulk_cleaner/             # Cloud Run Job — backlog processing + trash
│   │   ├── Dockerfile
│   │   └── main.py
│   ├── unsubscriber/             # Cloud Run Job — List-Unsubscribe firing
│   │   ├── Dockerfile
│   │   └── main.py
│   └── ui/                       # Next.js inbox frontend
│       ├── Dockerfile
│       ├── app/
│       └── components/
├── shared/
│   ├── firestore.py              # Firestore client + collection helpers
│   ├── gcs.py                    # Cloud Storage read/write helpers
│   └── pubsub.py                 # Pub/Sub helpers
├── infra/
│   └── terraform/                # All GCP infrastructure as code
├── docker-compose.yml            # Local dev
└── DEVELOPMENT.md                # Build progress and decisions log

Local Development

git clone https://github.com/dayian326/emailhelper
cd EmailHelper
docker-compose up

# API:  http://localhost:8000
# UI:   http://localhost:3000

Required environment variables (or Secret Manager in GCP):

ANTHROPIC_API_KEY=
DATABASE_URL=
PUBSUB_TOPIC=raw-emails
GOOGLE_CLOUD_PROJECT=

Deployment

# Build and push all images
docker build -t gcr.io/$PROJECT/email-api ./services/api
docker build -t gcr.io/$PROJECT/email-processor ./services/processor
docker build -t gcr.io/$PROJECT/email-poller ./services/poller
docker build -t gcr.io/$PROJECT/bulk-cleaner ./services/bulk_cleaner
docker build -t gcr.io/$PROJECT/unsubscriber ./services/unsubscriber

# Deploy infrastructure + services
cd infra/terraform
terraform apply

AI Classification Output

Emails are classified by Claude Sonnet (Anthropic API). The processor receives:

{
  "category": "receipt",
  "priority": 3,
  "summary": "Amazon order #112-9284 confirmed, total $47.23, delivery Friday.",
  "action_required": false,
  "folder": "EmailHelper/Receipts/2025",
  "sender_is_list": true,
  "body_gcs_path": "email-bodies/user123/2025/abc-email-id.txt"
}

Priority is scored 1–10. Anything 7+ surfaces at the top of the inbox regardless of category. sender_is_list: true marks emails eligible for unsubscription. body_gcs_path points to the full email text stored in Cloud Storage — kept out of Firestore to stay within free tier document size limits.

About

AI-powered email sorting agent - classifies, summarizes, and prioritizes your inbox using Gemini AI. Self-hosted on Google Cloud Run with IMAP support for Gmail, Outlook, Yahoo, and more.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages