Skip to main content

Zero-config email interceptor for Python ASGI apps

Project description

Mailview

Mailview

Capture outgoing emails during development and view them in a browser UI mounted inside your app.

No Docker. No SMTP server. No external services. Just one line of middleware.
Inspired by Ruby's letter_opener.

CI CodeQL PyPI Python Coverage License

Installation

pip install mailview

Quick Start

from fastapi import FastAPI
from mailview import MailviewMiddleware

app = FastAPI()
app.add_middleware(MailviewMiddleware)

That's it. Visit /_mail in your browser to see captured emails.

Features

  • Zero config - add middleware, visit /_mail, done
  • Persistent storage - emails survive dev server restarts (SQLite in temp dir)
  • Full email support - HTML, plaintext, multipart, attachments
  • Sandboxed preview - HTML emails render in an iframe without CSS bleed
  • Dev-only by default - refuses to activate in production environments
  • Self-contained - no external assets, works fully offline

How It Works

Mailview provides drop-in email backends that intercept outgoing emails instead of sending them:

# FastAPI-Mail
from mailview.backend import MailviewBackend
from fastapi_mail import FastMail, ConnectionConfig

config = ConnectionConfig(
    MAIL_BACKEND=MailviewBackend,
    # ... other config
)

# Or with any SMTP-based library, point it at Mailview's capture backend

Captured emails are stored in SQLite at /tmp/mailview/mailview.db and served through the /_mail UI.

Browser UI

Navigate to /_mail to see:

  • Inbox - list of captured emails with sender, recipients, subject, timestamp
  • HTML preview - rendered email in a sandboxed iframe
  • Plaintext - raw text version
  • Source - raw email headers and body
  • Attachments - download any attached files

Clear all emails with the delete button or DELETE /_mail/api/emails.

Screenshots

Source Tab Source Tab

Headers Table Headers Table

Text Tab Text Tab

Copy Button Copy Button

Configuration

Mailview works with zero configuration, but you can customise if needed:

app.add_middleware(
    MailviewMiddleware,
    mount_path="/_mail",        # Change the UI path (default: /_mail)
    db_path="/custom/path.db",  # Custom SQLite location (default: /tmp/mailview/mailview.db)
    enabled=True,               # Force enable/disable (default: auto-detect dev environment)
)

Production Safety

Mailview will not activate unless it detects a development environment. It checks for:

  • DEBUG=true or DEBUG=1 environment variable
  • MAILVIEW_ENABLED=true to explicitly enable
  • Framework-specific debug flags (FastAPI's debug=True, etc.)

To be extra safe, don't include mailview in your production dependencies.

Network Binding Warning

Mailview has no authentication. If your dev server binds to 0.0.0.0 (all interfaces) instead of 127.0.0.1 (localhost only), anyone on your local network can access /_mail and view captured emails.

For local development, prefer:

uvicorn app:app --host 127.0.0.1 --port 8000

Framework Support

Framework Status
FastAPI ✅ Supported
Starlette ✅ Supported
Django 🔜 Planned
Flask 🔜 Planned

Requirements

  • Python: 3.11+
  • Starlette: 0.40.0+
  • FastAPI: 0.115.5+ (if using FastAPI)

API Endpoints

The UI is powered by a simple JSON API:

Method Path Description
GET /_mail/api/emails List all captured emails
GET /_mail/api/emails/{id} Get a single email
GET /_mail/api/emails/{id}/html Get HTML body
GET /_mail/api/emails/{id}/attachments/{filename} Download attachment
DELETE /_mail/api/emails Clear all emails
DELETE /_mail/api/emails/{id} Delete a single email

Development

git clone https://github.com/swmcc/mailview.git
cd mailview
make local.install
make local.check

See CONTRIBUTING.md for full development workflow.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mailview-0.1.1.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mailview-0.1.1-py3-none-any.whl (24.3 kB view details)

Uploaded Python 3

File details

Details for the file mailview-0.1.1.tar.gz.

File metadata

  • Download URL: mailview-0.1.1.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mailview-0.1.1.tar.gz
Algorithm Hash digest
SHA256 39620727780fdca9231aaa69937ea809cfb2da37a3ceeb33c9e614efb84c45f5
MD5 169a7de1be6c024c99c65e228113f87f
BLAKE2b-256 2865c717db73262b78cb0fa00eb02cbfe05e86f357f972d022401ab77a8a7ad4

See more details on using hashes here.

Provenance

The following attestation bundles were made for mailview-0.1.1.tar.gz:

Publisher: release.yml on swmcc/mailview

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mailview-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: mailview-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 24.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mailview-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e15f6e9edc590b5aed430f1d94ffcbeb9fe67f8e781a7fa7cb6720e2dff4ec46
MD5 2e4e3429decfad9afdcd9935e780b2ee
BLAKE2b-256 18cd7c9a9e056985ce6c1b6117a2924231f4d058f219c65ff1cc11422ad78afa

See more details on using hashes here.

Provenance

The following attestation bundles were made for mailview-0.1.1-py3-none-any.whl:

Publisher: release.yml on swmcc/mailview

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page