Mailglass

Mail you can see through.

CIHex.pmHexDocsLicense

Pre-release. v0.1 is in active development (Phase 7 of 7). The installation and quickstart below describe the target API for v0.1 and will ship as tested against published Hex tarballs when Phase 7 (Installer + CI/CD + Docs) completes. Track progress in .planning/ROADMAP.md.

Mailglass is a batteries-included transactional email framework for Phoenix. It composes on top of Swoosh and ships the framework layer Swoosh deliberately leaves out: HEEx-native components with Outlook MSO/VML fallbacks, a LiveView preview/admin dashboard, normalized webhook events, an append-only event ledger with Postgres trigger immutability, multi-tenant routing, suppression lists, and — at v0.5 — RFC 8058 List-Unsubscribe with signed tokens and mix mail.doctor deliverability checks.

It is shipped as three sibling packages: mailglass (core), mailglass_admin (mountable LiveView dashboard), and mailglass_inbound (inbound routing; v0.5+). It is for senior Phoenix teams building production transactional email — welcome flows, password resets, magic links, receipts, notifications — who today rebuild the same 40% of framework plumbing on every project.

Requirements

Installation

Add mailglass to your dependencies:

# mix.exs
def deps do
  [
    {:mailglass, "~> 0.1"},
    {:mailglass_admin, "~> 0.1", only: [:dev]}
  ]
end

Fetch deps, run the installer, and migrate:

mix deps.get
mix mailglass.install
mix ecto.migrate

The installer generates: a MyApp.Mailing context, the three-table migration (mailglass_deliveries, mailglass_events, mailglass_suppressions plus the immutability trigger), router mounts for the dev preview and webhook plug, a default mailable and layout, an Oban worker stub (when Oban is installed), and a config/runtime.exs configuration block.

Quickstart

Run the full onboarding path first:

mix deps.get
mix mailglass.install
mix ecto.migrate
mix verify.phase_07

Define a mailable:

defmodule MyApp.UserMailer do
  use Mailglass.Mailable, stream: :transactional

  def welcome(user) do
    Mailglass.Message.new()
    |> Mailglass.Message.to(user.email)
    |> Mailglass.Message.subject("Welcome to MyApp")
    |> Mailglass.Message.render(MyApp.Mailing.Templates, :welcome, user: user)
  end
end

Send it — synchronously, asynchronously (via Oban when available), or in a batch:

MyApp.UserMailer.welcome(user) |> Mailglass.deliver()
MyApp.UserMailer.welcome(user) |> Mailglass.deliver_later()
Mailglass.deliver_many(Enum.map(users, &MyApp.UserMailer.welcome/1))

Preview mailables in dev at http://localhost:4000/dev/mail — sidebar of discovered mailables, device width and dark-mode toggles, HTML/Text/Raw/Headers tabs, live-editable assigns.

Feature highlights

Packages

Package Status What it is
mailglass v0.1 in development Core library: mailables, rendering, delivery pipeline, event ledger, webhook ingest, tenancy.
mailglass_admin v0.1 (dev-preview only) Mountable LiveView preview in dev. Prod-mountable sent-mail inbox + event timeline + suppression UI arrive in v0.5.
mailglass_inbound v0.5+ Inbound routing (Action Mailbox equivalent): recipient/subject/header matchers, ingress plugs per provider, storage adapters, Oban routing.

Roadmap

Full trajectory in .planning/ROADMAP.md and .planning/PROJECT.md.

Documentation

Phase 7 ships the full guide suite on HexDocs: Getting Started, Authoring Mailables, Components, Preview, Multi-Tenancy, Telemetry, Testing, and Migration from Swoosh.

Contributing

Mailglass is developed in public. Contributor conventions, decision log, and phase-by-phase roadmap live in CLAUDE.md and .planning/PROJECT.md; a dedicated CONTRIBUTING.md lands in Phase 7.

Reproduce the default CI gate locally:

mix verify.phase_02
mix verify.cold_start
mix compile --no-optional-deps --warnings-as-errors

License

MIT. The LICENSE file ships with Phase 7; the license is already declared in mix.exs and applies across all sibling packages.