Skip to main content

Tool for mutt to reply outlook html mail with markdown power

Project description

muttlook

MIT License CI 65 tests Python 3.8+ NeoMutt Notmuch 0.40 Pandoc

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

6. Neovim Telescope live search (nvim-mail)

Search, preview, reply, and triage mail directly from Neovim via telescope:

-- <leader>sm opens live notmuch search (via nm-livesearch)
require('telescope').load_extension('nvim_mail')
Key Action Muttlook role
Ctrl+d/u Scroll preview --action tui renders preview
Ctrl+o View in browser --action view (CID images resolved)
Ctrl+r Reply in nvim buffer Marker added for --action draft on send
Ctrl+l Full styled preview split nm-html-extract--action tui
Ctrl+t GTD tag
Enter Open in neomutt

Preview uses nm-html-extractmuttlook --action tui for styled rendering. Reply creates a draft with muttlook marker — on send (,m), --action draft joins the thread with full HTML history.

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.2.tar.gz (63.1 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.2-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: muttlook-0.1.2.tar.gz
  • Upload date:
  • Size: 63.1 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.2.tar.gz
Algorithm Hash digest
SHA256 b407104d6a9b0e2338734e007b329c38ea5a2bcddd55885155bbf3c22ba2771b
MD5 7b0ae8f80aac1aed57b83e97cc04a48e
BLAKE2b-256 6bdd434051f4595518bb0c7fb3cdde1c70a080fde7cf09c466361a1aed904853

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: muttlook-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 18.0 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 74f3476a5a2db563870c8d78e48221580cf445bc639b87ac2de774a448bc5660
MD5 048bd090879e794c8900e79cb0fd0fa5
BLAKE2b-256 3c77d4513ca92670a72a523deab0bc686c05f8d68fd46cb6dc51f9449ffe8deb

See more details on using hashes here.

Provenance

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