“Tell MailSentinel what matters. Never miss an important email again.”
MailSentinel is a personal, privacy-focused email monitoring application with a responsive, installable Progressive Web App (PWA) client and an autonomous background synchronization daemon.
It continuously monitors incoming emails, deterministically evaluates your customizable rules, detects deadlines, calculates urgency, and delivers instant browser push alerts and in-app notifications.
- 📱 Installable PWA (Android & Desktop): Mobile-first dark interface with light mode toggle. Installable directly onto Android home screens via Chrome/Firefox/Edge with native-like push notifications and app badging.
- 🎯 Deterministic Matching Engine:
- Sender email matching (normalized, exact).
- Sender domain matching with boundary enforcement (e.g.,
@university.edumatchessub.university.edu, but prevents substring spoofing likefakeuniversity.edu). - Sender display name & organization matching.
- Keyword and phrase matching with word boundary protections.
- Excluded keywords (instantly suppresses false-positive matches).
- Subject-only vs full-message matching.
- Match-Any vs Match-All rule semantics.
- 🚨 Intelligent Priority & Deadline Detection:
- Priority levels:
Critical,High,Normal,Low. - Timezone-aware deadline detection: extracts explicit dates (e.g., "due by November 15, 2026", "within 48 hours", "due tomorrow") and flags ambiguous dates without hallucinating.
- Urgency escalation: flags critical markers like "offer expires", "immediate action required", "payment past due".
- Priority levels:
- 🔒 Security & Minimum Privilege Scopes:
- Uses Google's official OAuth 2.0 flow with PKCE code challenges and state CSRF validation.
- Requests only read-only scope (
https://www.googleapis.com/auth/gmail.readonly). - Tokens are encrypted at rest with AES-256-GCM using derived keys.
- Never stores your Google password or exposes refresh tokens to the frontend.
- 🔄 Background Incremental Synchronization:
- Tracks Gmail
historyIdcheckpoints. - Automatic token refresh before expiration.
- Reconciliation fallback if history cursors expire.
- Background polling worker (configurable 30s–300s) + instant "Sync Now" trigger.
- Strict idempotency: processed email deduplication prevents redundant notifications.
- Tracks Gmail
- 🔔 Real Web Push & In-App Alerts:
- Standards-compliant VAPID Web Push notifications delivered through Service Workers.
- Configurable Quiet Hours (e.g., 22:00 to 07:00 in your local timezone) with Critical bypass.
- Full audit trail of delivery attempts with retry capabilities.
- Direct "Open in Gmail" action button launching the exact email thread.
MailSentinel/
├── public/ # Static assets, Web App Manifest & Service Worker
│ ├── manifest.json # PWA manifest for Android "Add to Home Screen"
│ ├── sw.js # Service Worker: Web Push & offline shell cache
│ └── favicon.svg # SVG shield icon
├── src/
│ ├── client/ # React 18 + TailwindCSS PWA Frontend
│ │ ├── components/ # Modals, Navbar, Toast, Rule Editor, Rule Tester
│ │ ├── views/ # 6 core views (Overview, Rules, Emails, History, Accounts, Settings)
│ │ ├── context/ # Global state provider & refresh coordinator
│ │ └── hooks/ # Web Push registration & permissions
│ ├── server/ # Express + TypeScript Backend
│ │ ├── crypto/ # AES-256-GCM token encryption/decryption
│ │ ├── db/ # Atomic persistent database store (WAL/atomic file swap)
│ │ ├── rules/ # Rule matcher & priority/deadline classifier
│ │ ├── gmail/ # Official Google OAuth 2.0 & Gmail API client
│ │ ├── sync/ # Background email synchronization worker
│ │ ├── notifications/ # Web Push & in-app dispatcher
│ │ ├── routes/ # REST API endpoints
│ │ └── index.ts # Server entry point
│ └── tests/ # Vitest automated test suite (26 passing tests)
├── Dockerfile # Multi-stage production container
├── docker-compose.yml # Container orchestration
└── package.json
- Node.js 18+ (tested with Node 22 LTS)
- npm or pnpm
git clone <repo-url>
cd "notification app"
npm installCopy .env.example to .env:
cp .env.example .envGenerate a secure 32+ character encryption secret and VAPID keys:
# Generate VAPID keys
npx web-push generate-vapid-keysUpdate your .env with the generated keys:
PORT=3001
NODE_ENV=development
BASE_URL=http://localhost:3000
API_BASE_URL=http://localhost:3001
# Google Cloud OAuth (see detailed guide below)
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-your-client-secret
GOOGLE_REDIRECT_URI=http://localhost:3001/api/auth/google/callback
# Security & Push
ENCRYPTION_SECRET=your_super_secret_32_character_hex_key_here!
VAPID_PUBLIC_KEY=your-vapid-public-key
VAPID_PRIVATE_KEY=your-vapid-private-key
VAPID_SUBJECT=mailto:admin@example.com# Terminal 1: Run the backend server
npm run dev:server
# Terminal 2: Run the Vite frontend with hot module reload
npm run dev:clientOpen http://localhost:3000 in your browser.
npm run build
npm startThe production server serves both the API and the compiled React PWA on http://localhost:3001.
To connect your Gmail account, follow this 5-minute setup:
- Go to Google Cloud Console: console.cloud.google.com
- Create a Project: Click the project dropdown at the top and select New Project (e.g.,
MailSentinel). - Enable Gmail API:
- In the search bar, search for Gmail API.
- Click Enable.
- Configure OAuth Consent Screen:
- Go to APIs & Services → OAuth consent screen.
- Choose External user type and click Create.
- App Name:
MailSentinel - User support email: Select your email.
- Developer contact: Enter your email.
- Click Save and Continue.
- Under Scopes, click Add or Remove Scopes, and search for:
https://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/userinfo.emailhttps://www.googleapis.com/auth/userinfo.profile
- Click Save and Continue.
- Under Test Users, click Add Users and add your personal Gmail address.
- Create Credentials:
- Go to APIs & Services → Credentials.
- Click Create Credentials → OAuth client ID.
- Application type: Web application.
- Name:
MailSentinel Web Client. - Under Authorized redirect URIs, click Add URI and enter:
(Or your production domain callback, e.g.
http://localhost:3001/api/auth/google/callbackhttps://your-domain.com/api/auth/google/callback) - Click Create.
- Copy Credentials to
.env:- Copy the generated Client ID into
GOOGLE_CLIENT_ID. - Copy the Client Secret into
GOOGLE_CLIENT_SECRET.
- Copy the generated Client ID into
- Open MailSentinel in Chrome for Android (e.g.
http://<your-lan-ip>:3001or your deployed HTTPS URL). - Tap the browser menu (three dots in the top right).
- Tap Add to Home screen (or Install app).
- Launch MailSentinel from your home screen or app drawer.
- In Settings, tap Subscribe Device to Push and allow notifications when prompted.
MailSentinel comes with automated unit and integration tests covering:
- Sender, domain, and keyword matching semantics.
- Boundary protection preventing substring spoofing.
- Excluded keywords match suppression.
- Deterministic priority classification and deadline parsing.
- AES-256-GCM token encryption and tampering rejection.
- Database CRUD and message deduplication.
Run all tests:
npm testRun end-to-end server verification:
npm run test:e2e- Onboarding Flow: Launching with a clean database opens the 5-step guided onboarding wizard.
- Rule Creation & CRUD: Create rules with multiple domains, senders, keywords, and excluded keywords; toggle enable/disable; test with live simulator.
- Google OAuth Flow: Initiate Google OAuth; state token and PKCE code challenge verify CSRF safety; callback stores encrypted tokens.
- Background Sync Worker: Incremental history cursor poll runs automatically every 60s; manual "Sync Now" button triggers immediate sync.
- Priority Classification: Emails with "deadline: Oct 25" or "immediate action required" escalate to Critical.
- Open in Gmail: Clicking "Open in Gmail" opens the exact thread in Gmail.
- Web Push Alerts: Triggering a test alert displays the system notification with action buttons.
Run with Docker Compose:
docker-compose up -d --buildView logs:
docker-compose logs -fThe container automatically persists your database in a named Docker volume (sentinel-data).
- Zero Content Retention: MailSentinel only retains message metadata (sender, subject, snippet, and match rationale) necessary to display why an alert was triggered. Full email bodies are not persisted.
- Encrypted at Rest: Google OAuth refresh and access tokens are encrypted with AES-256-GCM using scrypt key derivation.
- Read-Only Scope: The application can never send, delete, or modify emails.
- Account Disconnection: Clicking "Disconnect" in Connected Accounts immediately purges stored OAuth credentials and can optionally delete all historic alert data.