Skip to content

JhaSourav07/postmarker

Repository files navigation

πŸ“¬ Postmarker

Anonymous, transient email threads. No sign-up. No tracking. No data retention.

GitHub Stars License Open Issues Pull Requests



What is Postmarker?

Postmarker lets anyone send a secure, anonymous email to any recipient and read replies β€” all without creating an account. When you compose a message, Postmarker:

  1. Generates a unique thread alias (e.g. you+xk3a9f@gmail.com)
  2. Dispatches your email anonymously via SMTP with custom X-PostMarker-Thread-ID headers
  3. Returns a single-use cryptographic token β€” your only key to the inbox
  4. Syncs replies via IMAP using header-based lookup (zero bandwidth waste)
  5. Deletes everything after 7 days β€” threads, messages, tokens

There is no user database. There are no cookies. There is nothing to leak.


Features

  • πŸ” Cryptographic token access β€” SHA-256 hashed, never stored in plaintext
  • πŸ“¨ Anonymous SMTP dispatch β€” custom X-PostMarker-Thread-ID header embedded in every email
  • πŸ“₯ Smart IMAP sync β€” 4-tier fallback strategy; marks emails \Seen immediately after ingestion
  • 🧹 Auto-expiry β€” MongoDB TTL-based cleanup, enforced by a daily Vercel Cron Job
  • 🚫 Zero tracking β€” no analytics, no user accounts, no persistent identity
  • ⚑ Edge-ready β€” Next.js 16 App Router, Turbopack dev server
  • 🎨 Premium UI β€” Framer Motion animations, Geist font, dark-mode first

Architecture

src/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ page.tsx                    # Landing page (compose form)
β”‚   β”œβ”€β”€ inbox/
β”‚   β”‚   β”œβ”€β”€ page.tsx                # /inbox token entry
β”‚   β”‚   └── [token]/page.tsx        # Thread inbox view (server component)
β”‚   └── api/
β”‚       β”œβ”€β”€ create-thread/route.ts  # POST β€” creates thread, sends email
β”‚       β”œβ”€β”€ inbox/route.ts          # GET  β€” IMAP sync + fetch messages
β”‚       └── cleanup/route.ts        # GET/POST β€” purge expired records
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ home/                       # Landing page sections
β”‚   β”‚   β”œβ”€β”€ Hero.tsx
β”‚   β”‚   β”œβ”€β”€ ComposerCard.tsx
β”‚   β”‚   β”œβ”€β”€ Features.tsx
β”‚   β”‚   β”œβ”€β”€ Workflow.tsx
β”‚   β”‚   └── SuccessModal.tsx
β”‚   β”œβ”€β”€ inbox/                      # Token access form
β”‚   β”‚   └── TokenAccessForm.tsx
β”‚   └── conversation/               # Thread inbox UI
β”‚       β”œβ”€β”€ InboxClientForm.tsx
β”‚       β”œβ”€β”€ InboxHeader.tsx
β”‚       β”œβ”€β”€ ThreadSidebar.tsx
β”‚       └── MessageViewer.tsx
β”œβ”€β”€ services/
β”‚   β”œβ”€β”€ thread.service.ts           # Thread creation + SMTP dispatch
β”‚   └── imap.service.ts             # IMAP sync with header lookup
β”œβ”€β”€ models/
β”‚   β”œβ”€β”€ Thread.ts                   # Mongoose thread schema
β”‚   └── Message.ts                  # Mongoose message schema
└── lib/
    β”œβ”€β”€ mongodb.ts                  # Connection pooling
    β”œβ”€β”€ email.ts                    # Nodemailer transporter
    β”œβ”€β”€ crypto.ts                   # Token generation + hashing
    └── validators.ts               # XSS sanitisation

Getting Started

Prerequisites

  • Node.js 18+
  • A MongoDB Atlas cluster (free tier works)
  • A Gmail account with:

1. Clone the repository

git clone https://github.com/JhaSourav07/postmarker.git
cd postmarker
npm install

2. Configure environment variables

Create a .env.local file at the project root:

# Database
MONGODB_URI=mongodb+srv://<user>:<password>@cluster0.xxxxx.mongodb.net/Postmarker?retryWrites=true&w=majority

# SMTP (outgoing email)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=you@gmail.com
SMTP_PASS=xxxx xxxx xxxx xxxx   # Gmail App Password (no trailing spaces!)
SMTP_FROM=you@gmail.com

# IMAP (incoming email sync)
IMAP_HOST=imap.gmail.com
IMAP_PORT=993
IMAP_USER=you@gmail.com
IMAP_PASS=xxxx xxxx xxxx xxxx   # Same App Password

# Cron security (generate with: openssl rand -hex 32)
CRON_SECRET=

3. Start the development server

npm run dev

Open http://localhost:3000.


Deployment (Vercel)

  1. Push to GitHub
  2. Import the repo at vercel.com/new
  3. Add all environment variables in Settings β†’ Environment Variables
  4. The vercel.json in this repo configures a daily cron job at midnight UTC to purge expired data

MongoDB Atlas: Allow all IPs (0.0.0.0/0) or Vercel's IP ranges under Network Access.


How the IMAP Sync Works

When a recipient replies to a Postmarker email, their email client preserves the custom X-PostMarker-Thread-ID header (set on the original outbound message). The sync pipeline uses a 4-tier strategy:

Priority Method Speed
1 HEADER X-PostMarker-Thread-ID: <threadId> ⚑ Instant
2 HEADER X-Thread-ID: <threadId> ⚑ Instant
3 SUBJECT contains <threadId> πŸ”Ά Fast
4 Scan last 50 UNSEEN emails by envelope πŸ”΄ Last resort

Once a message is saved to MongoDB, it is immediately marked \Seen on the IMAP server. Future syncs skip it at the server-side search level β€” zero re-download, zero re-parse.


Contributing

See CONTRIBUTING.md for guidelines.


Security

See SECURITY.md for how to report vulnerabilities.


Code of Conduct

This project follows the Contributor Covenant Code of Conduct.


License

MIT Β© Sourav Jha

About

A secure middleman for your inbox. Send emails wearing a cryptographic mask, and Postmarker securely routes the replies back to your private workspace.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors