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.1.tar.gz (18.6 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.1-py3-none-any.whl (14.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: muttlook-0.1.1.tar.gz
  • Upload date:
  • Size: 18.6 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.1.tar.gz
Algorithm Hash digest
SHA256 de92d8c2a3a03490f308d1c15782db59965c614b0b736ef2117ebdf7b3071548
MD5 c5008fb7cb2f9f07360a6a2707066a2f
BLAKE2b-256 fafccbc5227edcd13627339a93c07461766bd277cd70d5a10c78d77f85321c3a

See more details on using hashes here.

Provenance

The following attestation bundles were made for muttlook-0.1.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: muttlook-0.1.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c792e412a2d4eb9d4d163dbc904b22bb84bea954831e26ec01096f5a62317284
MD5 b2376d687c1b4e60bd844e0bbdc72913
BLAKE2b-256 de53665a31bb858f23d7cf3f71ea050df7cdad10218f9024acf25ae48d7deb14

See more details on using hashes here.

Provenance

The following attestation bundles were made for muttlook-0.1.1-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