Skip to content

jcgurango/meremail

Repository files navigation

Meremail

A minimalist, self-hosted email API + client with a robust rules engine. Built with Hono, Vue 3, and SQLite. Connect it to your SMTP/IMAP, and it'll handle everything else. PWA for mobile. Read more about what it is and why it exists here.

Features

Rules Engine

Automatically organize incoming emails with powerful filtering rules:

  • Flexible Conditions: Match on sender, subject, content, recipients, attachments, or custom headers
  • Condition Groups: Combine conditions with AND/OR logic, including nested groups
  • Multiple Actions: Move to folder, delete, mark as read, add to Reply Later, or Set Aside
  • Contact Lists: Match senders against a list of email addresses
  • Header Matching: Filter on any email header (e.g., X-Spam-Score, List-Unsubscribe)
  • Preview: Test your rule against recent emails before saving
  • Retroactive Application: Apply rules to existing emails with progress tracking

Folder-Based Organization

Emails are organized into folders:

  • System Folders: Inbox, Junk, Trash (with 30-day retention)
  • Custom Folders: Create your own folders for organization
  • IMAP Sync: Folders sync with your IMAP server

Reply Later Queue

Mark threads you need to respond to. They're collected in one place, sorted by when you added them (oldest first), so nothing falls through the cracks.

Set Aside

Temporarily set threads aside to focus on what matters now. They're sorted by when you set them aside (newest first) for easy retrieval.

Full-Text Search

Search across all emails, contacts, and attachments.

Rich Email Composer

  • WYSIWYG editor with formatting
  • Inline images and file attachments
  • Reply, reply-all, and forward
  • Draft auto-save

Offline Support

Progressive Web App with offline capabilities:

  • Read cached emails without an internet connection
  • Compose drafts offline (synced when back online)
  • Folder and contact metadata cached for offline navigation

Privacy Features

  • External images proxied by default to prevent tracking
  • Self-hosted - your data stays on your server
  • Raw EML backup during import

Tech Stack

  • Frontend: Vue 3, Vite, TipTap editor, PWA
  • Backend: Hono (Node.js), Drizzle ORM
  • Database: SQLite (via better-sqlite3)
  • Email: IMAP for receiving, SMTP for sending

Setup

Prerequisites

  • Node.js 20+
  • pnpm

Installation

# Clone the repository
git clone https://github.com/yourusername/meremail.git
cd meremail

# Install dependencies
pnpm install

# Copy environment template
cp .env.example .env

# Edit .env with your email server details
# (see Configuration below)

# Run database migrations
pnpm db:migrate

# Import existing emails from IMAP
pnpm mail:import

# Start development server
pnpm dev

The app will be available at http://localhost:5173 (frontend) with API at http://localhost:3000.

Production

# Build all packages
pnpm build

# Start production server (serves API + static files)
pnpm start

In production, the server serves both the API and the built frontend on port 3000.

Docker

You can just pull the jcgurango/meremail:latest image from dockerhub.

Configuration

Edit .env with your settings:

# SMTP (for sending)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=you@example.com
SMTP_PASS=your-password
SMTP_SECURE=false

# IMAP (for receiving/importing)
IMAP_HOST=imap.example.com
IMAP_PORT=993
IMAP_USER=you@example.com
IMAP_PASS=your-password
IMAP_SECURE=true

# Your identity (auto-created on first import)
DEFAULT_SENDER_NAME=Your Name
DEFAULT_SENDER_EMAIL=you@example.com

# Image proxy for privacy (set empty to disable)
IMAGE_PROXY_URL=https://images.weserv.nl/?url={url}

# Attachment uploads
MAX_ATTACHMENT_SIZE=20971520

# EML backup during IMAP import (default: enabled)
EML_BACKUP_ENABLED=true

# Authentication
AUTH_USERNAME=admin
AUTH_PASSWORD=changeme
AUTH_COOKIE_SECRET=change-this-to-a-random-string

CLI Commands

IMAP Import

# Import all folders from IMAP
pnpm mail:import

# Import specific folders only
pnpm mail:import --folders=inbox,sent

During import:

  • Emails are deduplicated by Message-ID
  • Contacts are auto-created from senders and recipients
  • Threads are constructed from References/In-Reply-To headers
  • Emails are assigned to folders based on IMAP source (INBOX, Junk, etc.)
  • Raw EML files are backed up with IMAP metadata (folder, flags, UID)
  • Rules are evaluated and applied to incoming emails

EML File Import

Import emails from local .eml files:

# Import all .eml files from a folder (recursive)
pnpm mail:eml-import ~/backups/emails

# Import sent emails
pnpm mail:eml-import ~/backups/sent --sent

# Import spam/junk
pnpm mail:eml-import ~/backups/spam --junk

# Mark imported emails as read
pnpm mail:eml-import ~/backups/archive --read

# Preview without importing
pnpm mail:eml-import ~/backups/emails --dry-run

# Non-recursive (single folder only)
pnpm mail:eml-import ~/backups/emails --no-recursive

Demo Mode

Try out Meremail without connecting to a real email server:

# Reset database and load demo data
pnpm reset && pnpm mail:demo

# Start the app
pnpm dev

The demo data includes:

  • Conversation threads with back-and-forth replies
  • Newsletters and marketing emails
  • Receipts and confirmations
  • Unread messages and verification codes

This only works on an empty database.

Other Commands

# List available IMAP folders
pnpm mail:folders

# Generate new migration after schema changes
pnpm db:generate

# Run pending migrations
pnpm db:migrate

# Reset database (deletes all data!)
pnpm reset

Data Storage

All data is stored in ./data/:

data/
├── meremail.db      # SQLite database
├── uploads/         # Uploaded attachments
├── attachments/     # Downloaded IMAP attachments
└── eml-backup/      # Raw EML backups (organized by folder)
    ├── INBOX/
    ├── Sent/
    └── ...

Development

# Start dev servers (frontend + backend with hot reload)
pnpm dev

# Build all packages
pnpm build

# Run only the server
pnpm -F @meremail/server dev

# Run only the frontend
pnpm -F @meremail/web dev

# Type check the frontend
pnpm -F @meremail/web build

Architecture

This is a pnpm monorepo with three packages:

packages/
├── shared/        # Database, types, services, config
│   └── src/
│       ├── db/           # Drizzle schema and migrations
│       ├── types/        # Shared TypeScript types
│       ├── services/     # Business logic (IMAP, import, etc.)
│       └── config.ts     # Environment configuration
│
├── server/        # Hono API server
│   └── src/
│       ├── routes/       # API endpoints
│       ├── utils/        # Server utilities
│       ├── cli/          # CLI commands
│       └── index.ts      # Server entry point
│
└── web/           # Vue 3 SPA (Vite + PWA)
    └── src/
        ├── pages/        # Route pages
        ├── components/   # Vue components
        ├── composables/  # Vue composables (including offline sync)
        └── utils/        # Client utilities (API, IndexedDB sync)

Key Concepts

  • Folders organize threads (Inbox, Junk, Trash, plus custom folders)
  • Threads group related emails by References/In-Reply-To headers
  • Emails have readAt timestamp (null = unread) for read tracking
  • Contacts are a simple address book of senders and recipients
  • Rules filter incoming emails with conditions and actions (first match wins)
  • Trash holds deleted items for 30 days before permanent deletion
  • Offline Sync caches folders, threads, emails, and contacts to IndexedDB for PWA support

License

MIT

About

Hey.com inspired mail server + client

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages