{"id":48130505,"url":"https://github.com/samrathreddy/mail-tracker","last_synced_at":"2026-04-04T16:37:38.510Z","repository":{"id":343936849,"uuid":"1002110426","full_name":"samrathreddy/mail-tracker","owner":"samrathreddy","description":"Self-hosted email open tracking with Cloudflare Workers. Privacy-first Mailtrack alternative with Chrome extension, bot filtering, and zero infrastructure.","archived":false,"fork":false,"pushed_at":"2026-03-27T13:04:12.000Z","size":133,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-27T22:46:12.424Z","etag":null,"topics":["chrome-extension","cloudflare","cloudflare-kv","cloudflare-workers","email-analytics","email-tracker","email-tracking","emailtracker","gmail","kv-storage","mail-tracker","mailtrack-alternative","open-source","privacy","read-receipts","self-hosted","serverless","tracking-pixel"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/samrathreddy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-14T18:28:35.000Z","updated_at":"2026-03-27T13:04:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/samrathreddy/mail-tracker","commit_stats":null,"previous_names":["samrathreddy/mail-tracker"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/samrathreddy/mail-tracker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samrathreddy%2Fmail-tracker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samrathreddy%2Fmail-tracker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samrathreddy%2Fmail-tracker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samrathreddy%2Fmail-tracker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/samrathreddy","download_url":"https://codeload.github.com/samrathreddy/mail-tracker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samrathreddy%2Fmail-tracker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31405706,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chrome-extension","cloudflare","cloudflare-kv","cloudflare-workers","email-analytics","email-tracker","email-tracking","emailtracker","gmail","kv-storage","mail-tracker","mailtrack-alternative","open-source","privacy","read-receipts","self-hosted","serverless","tracking-pixel"],"created_at":"2026-04-04T16:37:36.032Z","updated_at":"2026-04-04T16:37:38.490Z","avatar_url":"https://github.com/samrathreddy.png","language":"JavaScript","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"extension/icons/icon128.png\" alt=\"Mail Tracker Logo\" width=\"128\" height=\"128\"\u003e\n  \n  # Mail Tracker\n\n  ### Know when your emails are opened — automatically, privately, and for free.\n\n  [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL%203.0-blue.svg)](LICENSE)\n  [![Cloudflare Workers](https://img.shields.io/badge/Cloudflare-Workers-orange)](https://workers.cloudflare.com/)\n  [![Chrome Extension](https://img.shields.io/badge/Chrome-Extension-green)](https://developer.chrome.com/docs/extensions/)\n  \n  **⚡ Install in 5 minutes** | Self-hosted | 100% Free\n\u003c/div\u003e\n\n---\n\nA lightweight email open tracking system with WhatsApp-style read receipts for Gmail. Built with Cloudflare Workers (serverless backend) + Chrome extension (auto-tracking)\n\n---\n\n## ✨ Features\n\n- **🚀 Auto-tracking** — Invisible pixel injected automatically when you send Gmail emails\n- **✓✓ WhatsApp-style read indicators** — See ✓ (sent) and ✓✓ (read) next to recipients in Gmail\n- **🔔 Real-time notifications** — Chrome notifications + Slack/Discord webhooks when emails are opened\n- **🛡️ Privacy-first** — Self-hosted on your Cloudflare account, your data stays yours\n- **🤖 Smart filtering** — Excludes bot proxies, and automatically detects \u0026 filters your own opens via the extension\n- **💰 100% free** — Runs on Cloudflare's generous free tier (100k requests/day)\n- **📊 Detailed analytics** — IP, country, device, timestamp for every open\n\n---\n\n## 🎬 Demo\n\n\n\nhttps://github.com/user-attachments/assets/5470a2ce-9076-407d-8961-1ade0ea8329f\n\n\n\n---\n\n## 🚀 Quick Start\n\n### Prerequisites\n\n- Node.js v18+ ([install](https://nodejs.org/))\n- Free Cloudflare account ([sign up](https://dash.cloudflare.com/sign-up))\n- Chrome browser\n- Gmail account\n\n### Installation (5 minutes)\n\n**1. Clone and deploy backend:**\n\n```bash\ngit clone https://github.com/samrathreddy/mail-tracker.git\ncd mail-tracker\npnpm install\npnpm exec wrangler login\npnpm exec wrangler kv namespace create \"TRACKER\"\n# Copy the KV namespace ID from output\ncp wrangler.example.toml wrangler.toml\n# Edit wrangler.toml and paste your KV namespace ID\npnpm run deploy\n# Save your worker URL: https://mail-tracker.YOUR-SUBDOMAIN.workers.dev\n```\n\n**2. Set password (optional but recommended):**\n\n```bash\npnpm exec wrangler secret put DASHBOARD_PASSWORD\n# Enter a secure password when prompted\n```\n\n**3. Install Chrome extension:**\n\n1. Open `chrome://extensions`\n2. Enable **Developer mode** (top-right toggle)\n3. Click **Load unpacked** → select `extension/` folder\n4. Click the extension icon → enter your worker URL and password → **Save \u0026 Connect**\n\n**4. Done!** Send a Gmail email and watch the magic happen ✨\n\n---\n\n## 📖 How It Works\n\n```\n┌─────────────┐\n│ You compose │\n│ Gmail email │\n└──────┬──────┘\n       │\n       ▼\n┌─────────────────────────────┐\n│ Extension auto-injects      │\n│ invisible 1x1 tracking pixel│\n│ per recipient               │\n└──────┬──────────────────────┘\n       │\n       ▼\n┌─────────────────────────────┐\n│ Recipient opens email       │\n│ → pixel loads               │\n└──────┬──────────────────────┘\n       │\n       ▼\n┌─────────────────────────────┐\n│ Cloudflare Worker logs:     │\n│ • IP, country, device       │\n│ • Timestamp                 │\n│ • Filters bots \u0026 duplicates │\n└──────┬──────────────────────┘\n       │\n       ▼\n┌─────────────────────────────┐\n│ Self-open detection:        │\n│ • Extension detects pixel   │\n│   in thread DOM             │\n│ • Tells worker to reclassify│\n│   open as \"self-view\"       │\n└──────┬──────────────────────┘\n       │\n       ▼\n┌─────────────────────────────┐\n│ Cron (every 1 min) checks:  │\n│ • Open still genuine?       │\n│   → Send Slack/Discord/     │\n│     Chrome notification     │\n│ • Open was self-view?       │\n│   → Skip silently           │\n└─────────────────────────────┘\n```\n\n---\n\n## 🎯 Use Cases\n\n- **Sales \u0026 outreach** — Know when prospects open your cold emails\n- **Job applications** — See if recruiters opened your application\n- **Customer support** — Confirm customers received your response\n- **Personal** — Check if friends/family read your important emails\n- **Freelancers** — Track proposal and invoice opens\n\n---\n\n## 🆚 Why Mail Tracker?\n\n| Feature | Mail Tracker | Mailtrack | Streak | Superhuman | HubSpot |\n|---------|:------------:|:---------:|:------:|:----------:|:-------:|\n| **Price** | **Free forever** | $9.99/mo | $49/mo | $30/mo | $45/mo |\n| **Self-hosted** | ✅ Your infra | ❌ Cloud | ❌ Cloud | ❌ Cloud | ❌ Cloud |\n| **Open source** | ✅ AGPL-3.0 | ❌ | ❌ | ❌ | ❌ |\n| **No data collection** | ✅ | ❌ | ❌ | ❌ | ❌ |\n| **Auto-tracking** | ✅ | ✅ | ✅ | ✅ | ✅ |\n| **Read indicators** | ✅ WhatsApp-style | ✅ | ✅ | ✅ | ❌ |\n| **Slack/Discord webhooks** | ✅ | ❌ | ❌ | ❌ | ✅ |\n| **Bot filtering** | ✅ | ✅ Limited | ✅ Limited | ✅ | ✅ |\n| **Zero infrastructure** | ✅ CF free tier | N/A | N/A | N/A | N/A |\n\n---\n\n## 📚 Full Documentation\n\n### Part 1: Deploy the Backend (Cloudflare Worker)\n\n#### Step 1 — Clone and install\n\n```bash\ncd ~/mail-tracker\npnpm install\n```\n\nYou should see wrangler installed in `node_modules/`.\n\n#### Step 2 — Log in to Cloudflare\n\n```bash\npnpm exec wrangler login\n```\n\nThis opens your browser. Log in to your Cloudflare account and authorize Wrangler.\n\nTo verify it worked:\n```bash\npnpm exec wrangler whoami\n```\nYou should see your account name and ID.\n\n#### Step 3 — Create a KV namespace\n\nKV is Cloudflare's key-value database. The worker uses it to store tracking data.\n\n```bash\npnpm exec wrangler kv namespace create \"TRACKER\"\n```\n\nYou'll see output like:\n```\n⛅️ wrangler\n{ binding = \"TRACKER\", id = \"abc123def456...\" }\n```\n\n**Copy that `id` value.** You'll need it in the next step.\n\n#### Step 4 — Configure wrangler.toml\n\nCopy the example config and paste your KV namespace ID:\n\n```bash\ncp wrangler.example.toml wrangler.toml\n```\n\nThen open `wrangler.toml` and replace the placeholder `id`:\n\n```toml\nname = \"mail-tracker\"\nmain = \"src/index.js\"\ncompatibility_date = \"2024-01-01\"\n\n[[kv_namespaces]]\nbinding = \"TRACKER\"\nid = \"abc123def456...\"   # ← paste YOUR id here\n```\n\n\u003e Note: `wrangler.toml` is gitignored since it contains your KV namespace ID. The repo ships `wrangler.example.toml` as a template.\n\n#### Step 5 — Test locally (optional)\n\n```bash\npnpm dev\n```\n\nOpen [http://localhost:8787](http://localhost:8787) in your browser. You should see the Mail Tracker dashboard. Press `Ctrl+C` to stop.\n\n#### Step 6 — Deploy to Cloudflare\n\n```bash\npnpm run deploy\n```\n\nOutput will show your live URL:\n```\nPublished mail-tracker (1.2s)\n  https://mail-tracker.YOUR-SUBDOMAIN.workers.dev\n```\n\n**Save this URL** — you'll enter it in the extension settings.\n\n#### Step 7 — Set Dashboard Password (Highly Recommended)\n\nProtect your tracking data with a password:\n\n```bash\npnpm exec wrangler secret put DASHBOARD_PASSWORD\n```\n\nWhen prompted, enter a secure password. This password will be required to:\n- Access the web dashboard\n- Use the Chrome extension\n- View tracking stats\n\n**Note:** Secrets are stored encrypted in Cloudflare, not in `.env` or `wrangler.toml`. The `.env.example` file is just a template for reference.\n\n**Important:** The tracking pixel endpoint (`/t/:id`) remains open so emails can load properly.\n\nTo verify: open `https://mail-tracker.YOUR-SUBDOMAIN.workers.dev` in your browser. You should be prompted for a password. Enter any username (it's ignored) and the password you just set.\n\n#### Step 8 — Set Up Webhook Notifications (Optional)\n\nGet real-time notifications on Slack or Discord when emails are opened:\n\n**For Slack:**\n1. Go to https://api.slack.com/messaging/webhooks\n2. Create a new webhook for your workspace\n3. Copy the webhook URL\n4. Run: `pnpm exec wrangler secret put SLACK_WEBHOOK_URL`\n5. Paste your webhook URL when prompted\n\n**For Discord:**\n1. Open your Discord server settings → Integrations → Webhooks\n2. Click \"New Webhook\"\n3. Copy the webhook URL\n4. Run: `pnpm exec wrangler secret put DISCORD_WEBHOOK_URL`\n5. Paste your webhook URL when prompted\n\nNotifications are delivered within ~1 minute of a genuine open. Self-opens are automatically filtered out — you'll never get notified for opening your own emails.\n\n---\n\n### Part 2: Install the Chrome Extension\n\n#### Step 1 — Open Chrome extensions page\n\nNavigate to:\n```\nchrome://extensions\n```\n\n#### Step 2 — Enable Developer Mode\n\nToggle **Developer mode** ON (top-right corner of the page).\n\n#### Step 3 — Load the extension\n\n1. Click **Load unpacked**\n2. Navigate to and select the `extension/` folder inside your project:\n   ```\n   ~/mail-tracker/extension/\n   ```\n3. The extension should appear in your extensions list\n\n#### Step 4 — Pin the extension\n\nClick the **puzzle piece icon** (Extensions) in Chrome's toolbar, then click the **pin icon** next to \"Mail Tracker\" so it's always visible.\n\n#### Step 5 — Connect to your Worker\n\n1. Click the **Mail Tracker icon** in the toolbar\n2. You'll see the Settings screen asking for a server URL\n3. Enter your Worker URL from Part 1:\n   ```\n   https://mail-tracker.YOUR-SUBDOMAIN.workers.dev\n   ```\n4. If you set a password in Part 1, Step 7, enter it in the **Dashboard password** field\n5. Click **Save \u0026 Connect**\n6. If it says \"Connected!\" — you're done!\n\n**Note:** If you didn't set a password, leave the password field empty.\n\n---\n\n### Part 3: Usage\n\n#### Automatic Gmail Tracking (default: ON)\n\nJust use Gmail normally:\n\n1. Open [Gmail](https://mail.google.com) and compose an email\n2. Write your email and click **Send**\n3. The extension automatically:\n   - Reads the To/CC/BCC recipients\n   - Creates a tracking pixel for each recipient\n   - Injects the invisible pixel into the email body\n   - Lets the email send normally\n4. When a recipient opens the email, you'll get a Chrome notification:\n   \u003e \"bob@example.com opened your email\"\n\n**WhatsApp-Style Read Indicators:**\n- **✓ Single gray tick** - Email sent but not opened yet\n- **✓✓ Double blue tick** - Email opened by recipient\n- **Hover tooltips** show \"Opened X times, Last opened: timestamp\"\n- **Appears in Gmail sent folder** next to recipient names\n\nYou can click the extension icon anytime to see:\n- All tracked emails with recipient names\n- Open counts and timestamps\n- Detailed event logs (IP, country, device)\n\n#### Manual Tracker Creation\n\nFor non-Gmail use (other email clients, websites, etc.):\n\n1. Click the extension icon\n2. Click **+ Manual**\n3. Click a tracker to see its detail view\n4. Click the **HTML Snippet** or **Tracking URL** box to copy it\n5. Paste into your email HTML or webpage\n\n#### Toggle Auto-Tracking\n\n1. Click the extension icon\n2. Click the **gear icon** (Settings)\n3. Toggle **Auto-track Gmail** on or off\n\n#### Tracking Protection\n\nYour own opens are automatically filtered through multiple layers:\n- **Self-view detection** — When you open a sent email, the extension detects the tracking pixel in the thread DOM and tells the worker to reclassify that open as a self-view. Works regardless of IP, VPN, or network changes.\n- **Sender IP exclusion** — Fallback filter: your IP at pixel creation time is stored. Opens from that IP are filtered.\n- **Bot filtering** — Outlook SafeLinks, Yahoo proxy, and other email prefetchers are detected and excluded.\n- **Dedup window** — duplicate loads within 5 seconds (preview panes, double-loads) are ignored.\n- **Deferred notifications** — Slack/Discord webhooks are queued and only sent after the self-view window passes (~10s), so you never get notified for your own opens.\n\nIn the extension, you'll see:\n- **Real Opens** — genuine recipient opens only\n- **Filtered** — count of blocked hits (your own opens + bots)\n- **Sender Protection** — shows \"Active\" per tracker\n\n---\n\n## API Reference\n\nAll endpoints return JSON except `/` (HTML dashboard) and `/t/:id` (serves PNG image).\n\n### Authentication\n\nIf you set `DASHBOARD_PASSWORD`, all endpoints except `/t/:id` require HTTP Basic Authentication:\n\n```bash\n# Example with curl\ncurl -u :your-password https://mail-tracker.YOUR-SUBDOMAIN.workers.dev/list\n```\n\nThe username is ignored (can be empty). Only the password matters.\n\n**Note:** The tracking pixel endpoint (`/t/:id`) is always open so emails can load the image.\n\n### Endpoints\n\n| Endpoint | Auth Required | Description |\n|----------|:-------------:|-------------|\n| `GET /` | ✓ | Web dashboard with all pixels |\n| `GET /new` | ✓ | Create a new tracker. Returns `{ id, pixel, html, stats }` |\n| `GET /new?to=email` | ✓ | Create tracker for a specific recipient |\n| `GET /t/:id` | ✗ | Tracking endpoint — serves 1x1 PNG and records the open |\n| `GET /s/:id` | ✓ | Stats for a tracker — returns `{ opens, events[], recipient, skipped, filteredEvents[], hasSenderProtection }` |\n| `GET /list` | ✓ | List all pixels — returns `[{ id, opens, skipped, recipient, lastOpen }]` |\n| `POST /self` | ✓ | Self-view signal — extension sends `{ ids: [...] }` to reclassify recent opens as self-views |\n| `GET /d/:id` | ✓ | Delete a tracker — returns `{ deleted: id }` |\n\n---\n\n## Project Structure\n\n```\nmail-tracker/\n├── src/\n│   ├── index.js           # Worker entry — router, API handlers, cron\n│   ├── shared.js          # Constants, helpers, auth, pixel serving\n│   ├── notifications.js   # Slack/Discord webhook dispatch\n│   └── views/\n│       ├── dashboard.js   # Main listing page (GET /)\n│       └── detail.js      # Individual tracker page (GET /s/:id)\n├── extension/\n│   ├── manifest.json      # Chrome extension manifest (v3)\n│   ├── popup.html         # Extension popup UI\n│   ├── popup.js           # Popup logic\n│   ├── background.js      # Service worker (polling \u0026 notifications)\n│   ├── gmail.js           # Content script (auto-inject + self-view detection)\n│   └── icons/             # Extension icons (16/48/128px)\n├── wrangler.toml          # Cloudflare Workers config (KV + cron trigger)\n├── CLAUDE.md              # AI assistant project guide\n├── package.json\n├── pnpm-lock.yaml\n└── .gitignore\n```\n\n## Pricing \u0026 Cost Breakdown\n\nThis project runs on Cloudflare's **free tier**. For most users, you'll never pay a cent.\n\n### Free Tier Limits\n\n| Resource | Free Limit | Resets |\n|----------|-----------|--------|\n| **Worker requests** | 100,000 / day | Daily (UTC midnight) |\n| **CPU time** | 10ms / request | Per request |\n| **KV reads** | 100,000 / day | Daily |\n| **KV writes** | 1,000 / day | Daily |\n| **KV deletes** | 1,000 / day | Daily |\n| **KV list operations** | 1,000 / day | Daily |\n| **KV storage** | 1 GB total | — |\n\n### What Our App Uses Per Action\n\n| Action | Worker Requests | KV Reads | KV Writes |\n|--------|:-:|:-:|:-:|\n| **Send email** (create tracker) | 1 | 0 | 1 |\n| **Recipient opens email** | 1 | 1 | 2 (tracker + webhook queue) |\n| **Self-view detected** | 1 | 1 | 1 |\n| **Cron processes webhooks** (every 1 min) | 1 | 1 | 0–1 |\n| **Extension polls /list** (every 60s) | 1 | N (one per tracker) | 0 |\n| **View tracker stats** | 1 | 1 | 0 |\n| **Delete tracker** | 1 | 0 | 0 (1 delete) |\n| **Load web dashboard** | 1 | N (one per tracker) | 0 |\n\n### Real-World Cost Estimates\n\n**Scenario 1: Personal use (free)**\n- Send ~20 tracked emails/day\n- ~50 opens/day\n- Cron trigger: ~1,440 requests/day (once per minute, 0 writes when idle)\n- **Total: ~1,510 requests/day, ~120 KV writes/day**\n- Well within free tier. **Cost: $0/month**\n\n**Scenario 2: Heavy personal use (free)**\n- Send ~100 tracked emails/day\n- ~500 opens/day\n- 200 pixels stored, extension polling reads ~200 keys per poll\n- **Total: ~290,000 KV reads/day, ~800 KV writes/day**\n- Still within free tier. **Cost: $0/month**\n\n**Scenario 3: Team / power user (paid plan needed)**\n- Send ~1,000+ tracked emails/day\n- ~5,000+ opens/day\n- Would exceed the 1,000 KV writes/day free limit\n- Paid plan: **$5/month base** includes 1M KV writes/month and 10M reads/month\n- That covers ~33,000 emails/day and ~330,000 opens/day\n- **Cost: $5/month** (covers almost any individual or small team)\n\n### Paid Plan Overage Rates (if you exceed included)\n\n| Resource | Included (Paid) | Overage Cost |\n|----------|-----------------|-------------|\n| Worker requests | 10M / month | +$0.30 / million |\n| KV reads | 10M / month | +$0.50 / million |\n| KV writes | 1M / month | +$5.00 / million |\n| KV deletes | 1M / month | +$5.00 / million |\n| KV list ops | 1M / month | +$5.00 / million |\n| KV storage | 1 GB | +$0.50 / GB-month |\n\n### Storage Estimate\n\nEach tracker uses ~0.5–2 KB of KV storage (depending on number of events stored, max 100 events per tracker).\n\n| Emails tracked | Approximate storage |\n|:-:|:-:|\n| 100 | ~100 KB |\n| 1,000 | ~1 MB |\n| 10,000 | ~10 MB |\n| 100,000 | ~100 MB |\n\nYou'd need to track **500,000+ trackers** to approach the 1 GB free storage limit.\n\n### TL;DR\n\n| Usage Level | Monthly Cost |\n|------------|:--:|\n| Personal (up to ~100 emails/day) | **Free** |\n| Heavy personal (up to ~1,000 emails/day) | **Free** (close to limit) |\n| Team / power user | **$5/month** |\n| Enterprise scale | **$5 + overages** |\n\n\u003e Source: [Cloudflare Workers Pricing](https://developers.cloudflare.com/workers/platform/pricing/) and [KV Pricing](https://developers.cloudflare.com/kv/platform/pricing/)\n\n---\n\n## Limitations\n\n- **Images disabled** — if the recipient's email client blocks images by default, the pixel won't load (common in corporate Outlook)\n- **Apple Mail Privacy Protection** (iOS 15+) — pre-fetches all images through Apple's proxy, so you see an open but with Apple's IP, not the recipient's real location\n- **Gmail image caching** — Gmail sometimes caches images after the first load, so subsequent opens from the same person may not trigger\n- **Extension required for self-open filtering** — self-view detection relies on the Chrome extension detecting the pixel in your Gmail DOM. If you open tracked emails outside Gmail (e.g. forwarded, in another client) without the extension, it may count as a real open\n- **Gmail plain text mode** — if you toggle \"Plain text mode\" in Gmail's compose menu (three dots → Plain text mode), all HTML is stripped and tracking won't work. This is **off by default** — Gmail always sends HTML, so even a simple \"hi\" email will include the tracking pixel. Just don't switch to plain text mode.\n- **Plain text emails (other clients)** — if you use a non-Gmail client that sends plain text only, tracking won't work since the `\u003cimg\u003e` tag gets stripped\n\n## License\n\n[AGPL-3.0](LICENSE)\n\nFree to use, share, modify, and contribute. If you modify and deploy it as a service, you must release your source code under the same license.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamrathreddy%2Fmail-tracker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamrathreddy%2Fmail-tracker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamrathreddy%2Fmail-tracker/lists"}