Skip to main content

Tool for mutt to reply outlook html mail with markdown power

Project description

Muttlook

A unified Python tool for reading, replying, and composing HTML emails in mutt/neomutt. Handles Outlook/OWA emails with Markdown composition, terminal rendering, and browser viewing.

Features

  • TUI rendering — styled terminal output via html2text --colour with Tokyo Night Storm ANSI colors (bold→purple, headers→blue, forwarded headers→dim gray, Teams boilerplate stripped)
  • Browser viewing — full HTML with inline CID images resolved, opens in default browser
  • Markdown reply/compose — write in markdown, send as HTML preserving Outlook thread formatting
  • Obsidian-style extensions: callouts (> [!note]), task checkboxes ([/] [-] [>]), strikethrough, definition lists, fenced code, tables
  • Inline image CID handling for both replies and new messages
  • Reply detection via In-Reply-To with References header fallback
  • Graceful fallback to new message mode when notmuch can't find the original
  • Built-in email trimming (mutt-trim)
  • Notmuch integration for message lookup

Installation

# From GitHub
uv tool install "muttlook @ git+https://github.com/monkeyxite/muttlook.git" --force

# From local clone
uv tool install -e . --force

Dependencies

Python (auto-installed)

click, mail-parser (>=3.9.3), mail-parser-reply, markdown (>=3.1.1), pymdown-extensions (>=10.0), rich (>=13.0), shortuuid

System

  • html2text — Rust crate (cargo install html2text-cli) for TUI rendering (--colour mode)
  • Pandoc — HTML template processing for new messages
  • Notmuch — finding original messages by Message-ID
  • Neomutt — MUA integration

Actions

Action Input Output Use case
--action tui <file> Raw HTML file Styled ANSI text to stdout Neomutt mailcap pager, nm-html-extract
--action tui (stdin) Full RFC822 email Styled ANSI text to stdout Pipe from notmuch show
--action tui-rich Raw HTML file or RFC822 Rich-styled ANSI text Experimental alternative renderer
--action view (stdin) Full RFC822 email Opens HTML in browser ,w macro, nms Ctrl+O
--action draft (stdin) Email draft from neomutt HTML file + mutt_cmd ,m macro, nms Ctrl+R
--action clean Removes temp files Send hook cleanup

Use Cases

1. Neomutt pager (auto_view HTML)

Mailcap entry — renders HTML emails inline in the neomutt pager:

text/html; muttlook --action tui %s; nametemplate=%s.html; copiousoutput;

2. nm-search (nms) fzf preview

nm-html-extract extracts the HTML part via notmuch and pipes to muttlook:

fzf --preview → nm-html-extract → notmuch show --part=N → muttlook --action tui <file>

3. nm-search inline shortcuts

Ctrl+O → muttlook --action view   (browser)
Ctrl+R → muttlook --action draft  (reply via neomutt)
Ctrl+F → notmuch tag              (GTD: archive/action/waiting/defer/done)

4. Neomutt compose macros

Reply to Outlook email with markdown:

macro compose ,m "<first-entry>\
<pipe-entry>notmuch new 2>/dev/null; muttlook --action draft<enter>\
<enter-command>set compose_confirm_detach_first=no<enter>\
<enter-command>source ~/.cache/muttlook/mutt_cmd<enter>\
<enter-command>set compose_confirm_detach_first=yes<enter>" "reply with md→html"

View HTML in browser with inline images:

macro pager,attach ,w "<pipe-message>muttlook --action view<enter>" "view HTML in browser"

5. Markdown in replies

# Summary

- Action item 1
- Action item 2

| Name | Task |
|------|------|
| Alice | Review |

> [!note] Reminder
> Meeting moved to Friday

- [x] Done
- [ ] Pending
- [/] In progress
- [-] Cancelled
- [>] Deferred

~~cancelled item~~

Term
:   Definition

TUI Rendering Pipeline

Input HTML
  → Charset auto-detect (from <meta> tag)
  → Outlook MsoNormal paragraph merge
  → html2text --colour (Rust binary, 120 cols)
  → ANSI color remap:
      bold yellow (38;5;11) → purple (35)
      # headers → bold blue (1;34) / cyan (1;36)
      forwarded headers (From/Sent/To/Cc) → dim gray (90)
      Original/Forwarded separators → dim gray (90)
  → Teams/Zoom boilerplate strip
  → Blank line collapse
  → stdout

Colors use standard ANSI 16 codes, mapped through kitty's Tokyo Night Storm theme.

How Draft Works

  1. mail-parser-reply separates your reply from quoted content
  2. Obsidian callouts (> [!type]) → styled HTML divs
  3. Obsidian checkboxes ([/] → ◐, [-] → ―, [>] → ▷)
  4. Markdown → HTML via pymdown-extensions (tables, tasklist, tilde, fenced_code, def_list)
  5. Reply detection: In-Reply-ToReferences (last entry) → new message fallback
  6. Original message fetched via notmuch search --output=files
  7. Inline images → CID attachments (multipart/related)
  8. HTML reply embedded into original email's HTML structure
  9. mutt_cmd generated for neomutt to attach HTML as MIME alternative

Development

uv tool install -e . --force    # Install editable
ruff check src/                  # Lint
ruff format src/                 # Format
uv run --with pytest pytest tests/ -v  # Test (27 tests)

Credits

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

muttlook-0.1.0.tar.gz (16.9 kB view details)

Uploaded Source

Built Distribution

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

muttlook-0.1.0-py3-none-any.whl (14.1 kB view details)

Uploaded Python 3

File details

Details for the file muttlook-0.1.0.tar.gz.

File metadata

  • Download URL: muttlook-0.1.0.tar.gz
  • Upload date:
  • Size: 16.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for muttlook-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4c479d9fe86e80dedc2a253a5343161a22d92eb0721c7c5874aba3ee0b23b6c1
MD5 91b6fa54d245f9a091e50df086f0d1b7
BLAKE2b-256 e111d4343597a7c7b86fa194d34f2ffe567570670eebc62693e9f38bd0e1d63c

See more details on using hashes here.

Provenance

The following attestation bundles were made for muttlook-0.1.0.tar.gz:

Publisher: ci.yml on monkeyxite/muttlook

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

File details

Details for the file muttlook-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: muttlook-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for muttlook-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bace2af826621997681108e017ce2cdbc8576d810fb517d30ded0a81e93e86ff
MD5 45fb0dfb65b8386d4f63ada142b7ec9c
BLAKE2b-256 4e49938960ad5ba0e205d1f7cdf484b45b5ff897043768f921895be7c8b43dbd

See more details on using hashes here.

Provenance

The following attestation bundles were made for muttlook-0.1.0-py3-none-any.whl:

Publisher: ci.yml on monkeyxite/muttlook

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