<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>MailBox Ultra changelog</title>
    <link>https://mpjhorner.github.io/changelog/</link>
    <description>Releases of MailBox Ultra. Latest: v2.0.0.</description>
    <language>en</language>
    <lastBuildDate>Wed, 29 Apr 2026 14:51:55 GMT</lastBuildDate>
    <item>
      <title>v2.0.0</title>
      <link>https://mpjhorner.github.io/changelog/#v2.0.0</link>
      <guid isPermaLink="true">https://mpjhorner.github.io/changelog/#v2.0.0</guid>
      <pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[<p><strong>BREAKING CHANGE.</strong> MailBox Ultra is now a native macOS application — no CLI binary, no browser UI, no HTTP server. The 0.x line was a Rust CLI that bound an SMTP listener and an embedded vanilla-JS web UI on a separate port; everything was driven by <code>--flags</code>. 2.0 is a real <code>.app</code> bundle you drop into <code>/Applications</code>.</p>
<h3 id="whats-new"><a class="anchor" href="#whats-new" aria-label="Anchor">#</a>What&#39;s new</h3>
<ul>
<li><strong>Ships as <code>MailBoxUltra.app</code> inside a <code>.dmg</code>.</strong> Drag into <code>/Applications</code>, right-click → Open on first launch (one-time Gatekeeper prompt). Universal binary; runs natively on Intel and Apple Silicon.</li>
<li><strong>Native Preferences window</strong> (<code>⌘,</code> or the gear button) replaces every <code>--flag</code>: SMTP port, bind address, hostname, max message size, AUTH PLAIN/LOGIN, ring-buffer size, upstream relay URL, NDJSON log file, theme. Atomic JSON persistence in <code>~/Library/Application Support/com.mpjhorner.MailBoxUltra/settings.json</code>. <strong>Apply</strong> restarts only the servers whose settings changed; captured messages survive across an SMTP restart.</li>
<li><strong>HTML email rendered by the system <code>WKWebView</code></strong> — the same engine Mail.app uses — embedded inside the app window. JavaScript is disabled, link clicks intercepted and shelled to the default browser, captured email HTML sandboxed.</li>
<li><strong>Faithful responsive preview.</strong> The HTML tab&#39;s Desktop / iPad / Mobile buttons resize the WKWebView frame <em>and</em> swap the User-Agent (iOS Mail / iPad Mail), so <code>@media (max-width: …)</code> rules and any UA-gated CSS branch the way they would on a real phone.</li>
<li><strong>Inbox sidebar</strong> designed for glanceability: two-line rows with the From address (strong, ellipsis) and Subject (dim, ellipsis), relative timestamps (&quot;now / 2m ago / 1h ago / 3d ago&quot;) right-aligned, attachment marker (📎N) on row 2 when applicable. Hover lifts to a soft accent bar; selection gets the full accent left edge.</li>
<li><strong>Theme</strong> built around an explicit four-step surface hierarchy (<code>BG → BG_ELEV → BG_ELEV2 → BG_SOFT</code>) with helper functions for body/muted/dim text and surface levels. Settings dialog uses heading-with-underline sections (no nested cards), primary buttons fill with the brand accent, focus rings are clean 1px borders.</li>
<li><strong>Native menus and shortcuts:</strong> <code>⌘,</code> Preferences · <code>⌘Q</code> Quit · <code>j</code> / <code>k</code> / <code>↓</code> / <code>↑</code> next / prev message · <code>g</code> / <code>G</code> newest / oldest · <code>/</code> focus search · <code>1</code>-<code>6</code> switch detail tab · <code>p</code> pause / resume · <code>d</code> delete · <code>⇧⌘X</code> clear all · <code>t</code> toggle theme · <code>?</code> shortcuts cheat sheet · <code>Esc</code> close dialog / blur search.</li>
<li><strong>Detail tabs:</strong> HTML (rendered) · Text · Headers (sortable) · Attachments (Save…) · Source (RFC 822 with syntax highlighting) · Release (resend any captured message to a target SMTP URL).</li>
<li><strong>Hand-drawn icon</strong> that pops on the macOS dock; source SVG in <code>icon/icon.svg</code>, baked into <code>AppIcon.icns</code> via <code>make icon</code>.</li>
<li><strong><code>scripts/simulate.py</code></strong> ships ~30 ready-to-fire scenarios across work tooling (Linear, GitHub, Figma, Google Docs, Slack-shaped notifications), transactional (Stripe payment, Apple App Store receipt, Google Calendar reminder), newsletters (Substack), and ecommerce (a fictional bikini brand &quot;MARÉ&quot; with six perfectly-curated responsive templates: welcome, drop, order, cart, sale, lookbook). Default firing order is interleaved to look like a plausible day&#39;s inbox. Stdlib-only Python; no <code>pip install</code> needed.</li>
</ul>
<h3 id="whats-removed"><a class="anchor" href="#whats-removed" aria-label="Anchor">#</a>What&#39;s removed</h3>
<ul>
<li><strong>No CLI binary, no <code>--flags</code></strong> — every option is a Preferences field. <code>mailbox-ultra</code> is the .app&#39;s executable, not something you run from a terminal.</li>
<li><strong>No web UI, no HTTP API, no SSE stream.</strong> The axum/tower/rust-embed stack is gone. Anything that scraped <code>/api/messages</code> or watched the <code>/events</code> SSE stream needs to switch to the <a href="https://mpjhorner.github.io/MailboxUltra/logging/" rel="noopener noreferrer">NDJSON log file</a> — same data, line-buffered, tail-friendly.</li>
<li><strong>No more <code>--update</code> self-update.</strong> Updates come from the GitHub releases page; download the new <code>.dmg</code>, drag the new <code>.app</code> into <code>/Applications</code>.</li>
<li><strong>macOS only.</strong> Linux and Windows builds are not produced. WKWebView is macOS-only and we don&#39;t want a degraded preview on other platforms.</li>
</ul>
<h3 id="migrating-from-0x"><a class="anchor" href="#migrating-from-0x" aria-label="Anchor">#</a>Migrating from 0.x</h3>
<p>The SMTP port stays at <code>1025</code> by default, so anything pointing at <code>127.0.0.1:1025</code> keeps working without changes. Old <code>--flag</code> workflows map to Preferences fields one-to-one; open <code>⌘,</code>, set the field, click Apply. If you were piping <code>--json</code> (NDJSON to stdout) into a tail, switch to Preferences → Logging and tick &quot;Append every captured message as NDJSON to a log file&quot; — same schema.</p>
]]></description>
    </item>
    <item>
      <title>v0.2.0</title>
      <link>https://mpjhorner.github.io/changelog/#v0.2.0</link>
      <guid isPermaLink="true">https://mpjhorner.github.io/changelog/#v0.2.0</guid>
      <pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[<ul>
<li>HTML preview now has Desktop / iPad / Mobile size buttons so you can see how a captured email reflows at different widths. Selection is remembered across messages.</li>
<li>HTML preview iframe fills the full height of the detail pane.</li>
<li>Fixed: clicking a message in the list sometimes left the detail pane on the placeholder instead of showing the email.</li>
</ul>
]]></description>
    </item>
    <item>
      <title>v0.1.0</title>
      <link>https://mpjhorner.github.io/changelog/#v0.1.0</link>
      <guid isPermaLink="true">https://mpjhorner.github.io/changelog/#v0.1.0</guid>
      <pubDate>Tue, 28 Apr 2026 00:00:00 GMT</pubDate>
      <description><![CDATA[<p>Initial release. Bind a port and catch every email your app tries to send. No real delivery, no setup. SMTP server, MIME parser, live web UI, JSON API, NDJSON log file, optional upstream relay.</p>
]]></description>
    </item>
  </channel>
</rss>
