Publish hermes-skills-email via gitea-publish skill
This commit is contained in:
@@ -0,0 +1,304 @@
|
|||||||
|
---
|
||||||
|
name: himalaya
|
||||||
|
description: "Himalaya CLI: IMAP/SMTP email from terminal."
|
||||||
|
version: 1.1.0
|
||||||
|
author: community
|
||||||
|
license: MIT
|
||||||
|
platforms: [linux, macos, windows]
|
||||||
|
metadata:
|
||||||
|
hermes:
|
||||||
|
tags: [Email, IMAP, SMTP, CLI, Communication]
|
||||||
|
homepage: https://github.com/pimalaya/himalaya
|
||||||
|
prerequisites:
|
||||||
|
commands: [himalaya]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Himalaya Email CLI
|
||||||
|
|
||||||
|
Himalaya is a CLI email client that lets you manage emails from the terminal using IMAP, SMTP, Notmuch, or Sendmail backends.
|
||||||
|
|
||||||
|
This skill is separate from the Hermes Email gateway adapter. The gateway
|
||||||
|
adapter lets people email the agent and uses Hermes' built-in IMAP/SMTP
|
||||||
|
adapter; this skill lets the agent operate a mailbox from terminal tools and
|
||||||
|
requires the external `himalaya` CLI.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- `references/configuration.md` (config file setup + IMAP/SMTP authentication)
|
||||||
|
- `references/message-composition.md` (MML syntax for composing emails)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. Himalaya CLI installed (`himalaya --version` to verify)
|
||||||
|
2. A configuration file at `~/.config/himalaya/config.toml`
|
||||||
|
3. IMAP/SMTP credentials configured (password stored securely)
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pre-built binary (Linux/macOS — recommended)
|
||||||
|
curl -sSL https://raw.githubusercontent.com/pimalaya/himalaya/master/install.sh | PREFIX=~/.local sh
|
||||||
|
|
||||||
|
# macOS via Homebrew
|
||||||
|
brew install himalaya
|
||||||
|
|
||||||
|
# Or via cargo (any platform with Rust)
|
||||||
|
cargo install himalaya --locked
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration Setup
|
||||||
|
|
||||||
|
Run the interactive wizard to set up an account:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya account configure
|
||||||
|
```
|
||||||
|
|
||||||
|
Or create `~/.config/himalaya/config.toml` manually:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.personal]
|
||||||
|
email = "you@example.com"
|
||||||
|
display-name = "Your Name"
|
||||||
|
default = true
|
||||||
|
|
||||||
|
backend.type = "imap"
|
||||||
|
backend.host = "imap.example.com"
|
||||||
|
backend.port = 993
|
||||||
|
backend.encryption.type = "tls"
|
||||||
|
backend.login = "you@example.com"
|
||||||
|
backend.auth.type = "password"
|
||||||
|
backend.auth.cmd = "pass show email/imap" # or use keyring
|
||||||
|
|
||||||
|
message.send.backend.type = "smtp"
|
||||||
|
message.send.backend.host = "smtp.example.com"
|
||||||
|
message.send.backend.port = 587
|
||||||
|
message.send.backend.encryption.type = "start-tls"
|
||||||
|
message.send.backend.login = "you@example.com"
|
||||||
|
message.send.backend.auth.type = "password"
|
||||||
|
message.send.backend.auth.cmd = "pass show email/smtp"
|
||||||
|
|
||||||
|
# Folder aliases (himalaya v1.2.0+ syntax). Required whenever the
|
||||||
|
# server's folder names don't match himalaya's canonical names
|
||||||
|
# (inbox/sent/drafts/trash). Gmail is the common case — see
|
||||||
|
# `references/configuration.md` for the `[Gmail]/Sent Mail` mapping.
|
||||||
|
folder.aliases.inbox = "INBOX"
|
||||||
|
folder.aliases.sent = "Sent"
|
||||||
|
folder.aliases.drafts = "Drafts"
|
||||||
|
folder.aliases.trash = "Trash"
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Heads up on the alias syntax.** Pre-v1.2.0 docs used a
|
||||||
|
> `[accounts.NAME.folder.alias]` sub-section (singular `alias`).
|
||||||
|
> v1.2.0 silently ignores that form — TOML parses fine, but the
|
||||||
|
> alias resolver never reads it, so every lookup falls through to
|
||||||
|
> the canonical name. On Gmail this means save-to-Sent fails *after*
|
||||||
|
> SMTP delivery succeeds, and `himalaya message send` exits non-zero.
|
||||||
|
> Any caller (agent, script, user) that retries on that exit code
|
||||||
|
> will re-run the entire send — including SMTP — producing duplicate
|
||||||
|
> emails to recipients. Always use `folder.aliases.X` (plural, dotted
|
||||||
|
> keys, directly under `[accounts.NAME]`).
|
||||||
|
|
||||||
|
## Hermes Integration Notes
|
||||||
|
|
||||||
|
- **Reading, listing, searching, moving, deleting** all work directly through the terminal tool
|
||||||
|
- **Composing/replying/forwarding** — piped input (`cat << EOF | himalaya template send`) is recommended for reliability. Interactive `$EDITOR` mode works with `pty=true` + background + process tool, but requires knowing the editor and its commands
|
||||||
|
- Use `--output json` for structured output that's easier to parse programmatically
|
||||||
|
- The `himalaya account configure` wizard requires interactive input — use PTY mode: `terminal(command="himalaya account configure", pty=true)`
|
||||||
|
|
||||||
|
## Common Operations
|
||||||
|
|
||||||
|
### List Folders
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya folder list
|
||||||
|
```
|
||||||
|
|
||||||
|
### List Emails
|
||||||
|
|
||||||
|
List emails in INBOX (default):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya envelope list
|
||||||
|
```
|
||||||
|
|
||||||
|
List emails in a specific folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya envelope list --folder "Sent"
|
||||||
|
```
|
||||||
|
|
||||||
|
List with pagination:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya envelope list --page 1 --page-size 20
|
||||||
|
```
|
||||||
|
|
||||||
|
### Search Emails
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya envelope list from john@example.com subject meeting
|
||||||
|
```
|
||||||
|
|
||||||
|
### Read an Email
|
||||||
|
|
||||||
|
Read email by ID (shows plain text):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message read 42
|
||||||
|
```
|
||||||
|
|
||||||
|
Export raw MIME:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message export 42 --full
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reply to an Email
|
||||||
|
|
||||||
|
To reply non-interactively from Hermes, read the original message, compose a reply, and pipe it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get the reply template, edit it, and send
|
||||||
|
himalaya template reply 42 | sed 's/^$/\nYour reply text here\n/' | himalaya template send
|
||||||
|
```
|
||||||
|
|
||||||
|
Or build the reply manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat << 'EOF' | himalaya template send
|
||||||
|
From: you@example.com
|
||||||
|
To: sender@example.com
|
||||||
|
Subject: Re: Original Subject
|
||||||
|
In-Reply-To: <original-message-id>
|
||||||
|
|
||||||
|
Your reply here.
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Reply-all (interactive — needs $EDITOR, use template approach above instead):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message reply 42 --all
|
||||||
|
```
|
||||||
|
|
||||||
|
### Forward an Email
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Get forward template and pipe with modifications
|
||||||
|
himalaya template forward 42 | sed 's/^To:.*/To: newrecipient@example.com/' | himalaya template send
|
||||||
|
```
|
||||||
|
|
||||||
|
### Write a New Email
|
||||||
|
|
||||||
|
**Non-interactive (use this from Hermes)** — pipe the message via stdin:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat << 'EOF' | himalaya template send
|
||||||
|
From: you@example.com
|
||||||
|
To: recipient@example.com
|
||||||
|
Subject: Test Message
|
||||||
|
|
||||||
|
Hello from Himalaya!
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Or with headers flag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message write -H "To:recipient@example.com" -H "Subject:Test" "Message body here"
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: `himalaya message write` without piped input opens `$EDITOR`. This works with `pty=true` + background mode, but piping is simpler and more reliable.
|
||||||
|
|
||||||
|
### Move/Copy Emails
|
||||||
|
|
||||||
|
Move to folder (target folder comes first, then the message ID):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message move "Archive" 42
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy to folder (target folder comes first, then the message ID):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message copy "Important" 42
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete an Email
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message delete 42
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manage Flags
|
||||||
|
|
||||||
|
Add flag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya flag add 42 --flag seen
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove flag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya flag remove 42 --flag seen
|
||||||
|
```
|
||||||
|
|
||||||
|
## Multiple Accounts
|
||||||
|
|
||||||
|
List accounts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya account list
|
||||||
|
```
|
||||||
|
|
||||||
|
Use a specific account:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya --account work envelope list
|
||||||
|
```
|
||||||
|
|
||||||
|
## Attachments
|
||||||
|
|
||||||
|
Save attachments from a message:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya attachment download 42
|
||||||
|
```
|
||||||
|
|
||||||
|
Save to specific directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya attachment download 42 --downloads-dir ~/Downloads
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output Formats
|
||||||
|
|
||||||
|
Most commands support `--output` for structured output:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya envelope list --output json
|
||||||
|
himalaya envelope list --output plain
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
Enable debug logging:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
RUST_LOG=debug himalaya envelope list
|
||||||
|
```
|
||||||
|
|
||||||
|
Full trace with backtrace:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
RUST_LOG=trace RUST_BACKTRACE=1 himalaya envelope list
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- Use `himalaya --help` or `himalaya <command> --help` for detailed usage.
|
||||||
|
- Message IDs are relative to the current folder; re-list after folder changes.
|
||||||
|
- For composing rich emails with attachments, use MML syntax (see `references/message-composition.md`).
|
||||||
|
- Store passwords securely using `pass`, system keyring, or a command that outputs the password.
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
# Himalaya Configuration Reference
|
||||||
|
|
||||||
|
Configuration file location: `~/.config/himalaya/config.toml`
|
||||||
|
|
||||||
|
## Minimal IMAP + SMTP Setup
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.default]
|
||||||
|
email = "user@example.com"
|
||||||
|
display-name = "Your Name"
|
||||||
|
default = true
|
||||||
|
|
||||||
|
# IMAP backend for reading emails
|
||||||
|
backend.type = "imap"
|
||||||
|
backend.host = "imap.example.com"
|
||||||
|
backend.port = 993
|
||||||
|
backend.encryption.type = "tls"
|
||||||
|
backend.login = "user@example.com"
|
||||||
|
backend.auth.type = "password"
|
||||||
|
backend.auth.raw = "your-password"
|
||||||
|
|
||||||
|
# SMTP backend for sending emails
|
||||||
|
message.send.backend.type = "smtp"
|
||||||
|
message.send.backend.host = "smtp.example.com"
|
||||||
|
message.send.backend.port = 587
|
||||||
|
message.send.backend.encryption.type = "start-tls"
|
||||||
|
message.send.backend.login = "user@example.com"
|
||||||
|
message.send.backend.auth.type = "password"
|
||||||
|
message.send.backend.auth.raw = "your-password"
|
||||||
|
|
||||||
|
# Folder aliases — required whenever server folder names differ
|
||||||
|
# from himalaya's canonical names. See "Folder Aliases" below.
|
||||||
|
folder.aliases.inbox = "INBOX"
|
||||||
|
folder.aliases.sent = "Sent"
|
||||||
|
folder.aliases.drafts = "Drafts"
|
||||||
|
folder.aliases.trash = "Trash"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Password Options
|
||||||
|
|
||||||
|
### Raw password (testing only, not recommended)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
backend.auth.raw = "your-password"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Password from command (recommended)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
backend.auth.cmd = "pass show email/imap"
|
||||||
|
# backend.auth.cmd = "security find-generic-password -a user@example.com -s imap -w"
|
||||||
|
```
|
||||||
|
|
||||||
|
### System keyring (requires keyring feature)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
backend.auth.keyring = "imap-example"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run `himalaya account configure <account>` to store the password.
|
||||||
|
|
||||||
|
## Gmail Configuration
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.gmail]
|
||||||
|
email = "you@gmail.com"
|
||||||
|
display-name = "Your Name"
|
||||||
|
default = true
|
||||||
|
|
||||||
|
backend.type = "imap"
|
||||||
|
backend.host = "imap.gmail.com"
|
||||||
|
backend.port = 993
|
||||||
|
backend.encryption.type = "tls"
|
||||||
|
backend.login = "you@gmail.com"
|
||||||
|
backend.auth.type = "password"
|
||||||
|
backend.auth.cmd = "pass show google/app-password"
|
||||||
|
|
||||||
|
message.send.backend.type = "smtp"
|
||||||
|
message.send.backend.host = "smtp.gmail.com"
|
||||||
|
message.send.backend.port = 587
|
||||||
|
message.send.backend.encryption.type = "start-tls"
|
||||||
|
message.send.backend.login = "you@gmail.com"
|
||||||
|
message.send.backend.auth.type = "password"
|
||||||
|
message.send.backend.auth.cmd = "pass show google/app-password"
|
||||||
|
|
||||||
|
# Gmail folder mapping. Without these, save-to-Sent fails after
|
||||||
|
# SMTP delivery succeeds (Gmail's Sent folder is `[Gmail]/Sent Mail`,
|
||||||
|
# not `Sent`), and `himalaya message send` exits non-zero. Any
|
||||||
|
# caller that retries on that error will re-run SMTP — duplicate
|
||||||
|
# emails to recipients. Always include this block for Gmail.
|
||||||
|
folder.aliases.inbox = "INBOX"
|
||||||
|
folder.aliases.sent = "[Gmail]/Sent Mail"
|
||||||
|
folder.aliases.drafts = "[Gmail]/Drafts"
|
||||||
|
folder.aliases.trash = "[Gmail]/Trash"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Gmail requires an App Password if 2FA is enabled.
|
||||||
|
|
||||||
|
## iCloud Configuration
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.icloud]
|
||||||
|
email = "you@icloud.com"
|
||||||
|
display-name = "Your Name"
|
||||||
|
|
||||||
|
backend.type = "imap"
|
||||||
|
backend.host = "imap.mail.me.com"
|
||||||
|
backend.port = 993
|
||||||
|
backend.encryption.type = "tls"
|
||||||
|
backend.login = "you@icloud.com"
|
||||||
|
backend.auth.type = "password"
|
||||||
|
backend.auth.cmd = "pass show icloud/app-password"
|
||||||
|
|
||||||
|
message.send.backend.type = "smtp"
|
||||||
|
message.send.backend.host = "smtp.mail.me.com"
|
||||||
|
message.send.backend.port = 587
|
||||||
|
message.send.backend.encryption.type = "start-tls"
|
||||||
|
message.send.backend.login = "you@icloud.com"
|
||||||
|
message.send.backend.auth.type = "password"
|
||||||
|
message.send.backend.auth.cmd = "pass show icloud/app-password"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Generate an app-specific password at appleid.apple.com
|
||||||
|
|
||||||
|
## Folder Aliases
|
||||||
|
|
||||||
|
Map himalaya's canonical folder names (`inbox`, `sent`, `drafts`,
|
||||||
|
`trash`) to whatever the server actually calls them. Use the
|
||||||
|
v1.2.0 `folder.aliases.X` syntax (plural, dotted keys, directly
|
||||||
|
under `[accounts.NAME]`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.default]
|
||||||
|
# ... other account config ...
|
||||||
|
|
||||||
|
folder.aliases.inbox = "INBOX"
|
||||||
|
folder.aliases.sent = "Sent"
|
||||||
|
folder.aliases.drafts = "Drafts"
|
||||||
|
folder.aliases.trash = "Trash"
|
||||||
|
```
|
||||||
|
|
||||||
|
The equivalent TOML sub-section form also works in v1.2.0:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.default.folder.aliases]
|
||||||
|
inbox = "INBOX"
|
||||||
|
sent = "Sent"
|
||||||
|
drafts = "Drafts"
|
||||||
|
trash = "Trash"
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Don't use the singular `alias` form.** Pre-v1.2.0 docs showed
|
||||||
|
> `[accounts.NAME.folder.alias]` (singular). v1.2.0 silently
|
||||||
|
> ignores that sub-section — TOML parses without error, but the
|
||||||
|
> alias resolver never reads it. Every lookup then falls through
|
||||||
|
> to the canonical name. On Gmail (where `sent` is actually
|
||||||
|
> `[Gmail]/Sent Mail`) this means save-to-Sent fails *after* SMTP
|
||||||
|
> delivery succeeds, and `himalaya message send` exits non-zero.
|
||||||
|
> Any caller (agent, script, user) that retries on that error
|
||||||
|
> code will re-run the send — including SMTP — producing duplicate
|
||||||
|
> emails to recipients. Always use `folder.aliases.X` (plural).
|
||||||
|
|
||||||
|
## Multiple Accounts
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.personal]
|
||||||
|
email = "personal@example.com"
|
||||||
|
default = true
|
||||||
|
# ... backend config ...
|
||||||
|
|
||||||
|
[accounts.work]
|
||||||
|
email = "work@company.com"
|
||||||
|
# ... backend config ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Switch accounts with `--account`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya --account work envelope list
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notmuch Backend (local mail)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.local]
|
||||||
|
email = "user@example.com"
|
||||||
|
|
||||||
|
backend.type = "notmuch"
|
||||||
|
backend.db-path = "~/.mail/.notmuch"
|
||||||
|
```
|
||||||
|
|
||||||
|
## OAuth2 Authentication (for providers that support it)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
backend.auth.type = "oauth2"
|
||||||
|
backend.auth.client-id = "your-client-id"
|
||||||
|
backend.auth.client-secret.cmd = "pass show oauth/client-secret"
|
||||||
|
backend.auth.access-token.cmd = "pass show oauth/access-token"
|
||||||
|
backend.auth.refresh-token.cmd = "pass show oauth/refresh-token"
|
||||||
|
backend.auth.auth-url = "https://provider.com/oauth/authorize"
|
||||||
|
backend.auth.token-url = "https://provider.com/oauth/token"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Additional Options
|
||||||
|
|
||||||
|
### Signature
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.default]
|
||||||
|
signature = "Best regards,\nYour Name"
|
||||||
|
signature-delim = "-- \n"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Downloads directory
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.default]
|
||||||
|
downloads-dir = "~/Downloads/himalaya"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Editor for composing
|
||||||
|
|
||||||
|
Set via environment variable:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export EDITOR="vim"
|
||||||
|
```
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
# Message Composition with MML (MIME Meta Language)
|
||||||
|
|
||||||
|
Himalaya uses MML for composing emails. MML is a simple XML-based syntax that compiles to MIME messages.
|
||||||
|
|
||||||
|
## Basic Message Structure
|
||||||
|
|
||||||
|
An email message is a list of **headers** followed by a **body**, separated by a blank line:
|
||||||
|
|
||||||
|
```
|
||||||
|
From: sender@example.com
|
||||||
|
To: recipient@example.com
|
||||||
|
Subject: Hello World
|
||||||
|
|
||||||
|
This is the message body.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Headers
|
||||||
|
|
||||||
|
Common headers:
|
||||||
|
|
||||||
|
- `From`: Sender address
|
||||||
|
- `To`: Primary recipient(s)
|
||||||
|
- `Cc`: Carbon copy recipients
|
||||||
|
- `Bcc`: Blind carbon copy recipients
|
||||||
|
- `Subject`: Message subject
|
||||||
|
- `Reply-To`: Address for replies (if different from From)
|
||||||
|
- `In-Reply-To`: Message ID being replied to
|
||||||
|
|
||||||
|
### Address Formats
|
||||||
|
|
||||||
|
```
|
||||||
|
To: user@example.com
|
||||||
|
To: John Doe <john@example.com>
|
||||||
|
To: "John Doe" <john@example.com>
|
||||||
|
To: user1@example.com, user2@example.com, "Jane" <jane@example.com>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Plain Text Body
|
||||||
|
|
||||||
|
Simple plain text email:
|
||||||
|
|
||||||
|
```
|
||||||
|
From: alice@localhost
|
||||||
|
To: bob@localhost
|
||||||
|
Subject: Plain Text Example
|
||||||
|
|
||||||
|
Hello, this is a plain text email.
|
||||||
|
No special formatting needed.
|
||||||
|
|
||||||
|
Best,
|
||||||
|
Alice
|
||||||
|
```
|
||||||
|
|
||||||
|
## MML for Rich Emails
|
||||||
|
|
||||||
|
### Multipart Messages
|
||||||
|
|
||||||
|
Alternative text/html parts:
|
||||||
|
|
||||||
|
```
|
||||||
|
From: alice@localhost
|
||||||
|
To: bob@localhost
|
||||||
|
Subject: Multipart Example
|
||||||
|
|
||||||
|
<#multipart type=alternative>
|
||||||
|
This is the plain text version.
|
||||||
|
<#part type=text/html>
|
||||||
|
<html><body><h1>This is the HTML version</h1></body></html>
|
||||||
|
<#/multipart>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Attachments
|
||||||
|
|
||||||
|
Attach a file:
|
||||||
|
|
||||||
|
```
|
||||||
|
From: alice@localhost
|
||||||
|
To: bob@localhost
|
||||||
|
Subject: With Attachment
|
||||||
|
|
||||||
|
Here is the document you requested.
|
||||||
|
|
||||||
|
<#part filename=/path/to/document.pdf><#/part>
|
||||||
|
```
|
||||||
|
|
||||||
|
Attachment with custom name:
|
||||||
|
|
||||||
|
```
|
||||||
|
<#part filename=/path/to/file.pdf name=report.pdf><#/part>
|
||||||
|
```
|
||||||
|
|
||||||
|
Multiple attachments:
|
||||||
|
|
||||||
|
```
|
||||||
|
<#part filename=/path/to/doc1.pdf><#/part>
|
||||||
|
<#part filename=/path/to/doc2.pdf><#/part>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inline Images
|
||||||
|
|
||||||
|
Embed an image inline:
|
||||||
|
|
||||||
|
```
|
||||||
|
From: alice@localhost
|
||||||
|
To: bob@localhost
|
||||||
|
Subject: Inline Image
|
||||||
|
|
||||||
|
<#multipart type=related>
|
||||||
|
<#part type=text/html>
|
||||||
|
<html><body>
|
||||||
|
<p>Check out this image:</p>
|
||||||
|
<img src="cid:image1">
|
||||||
|
</body></html>
|
||||||
|
<#part disposition=inline id=image1 filename=/path/to/image.png><#/part>
|
||||||
|
<#/multipart>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Mixed Content (Text + Attachments)
|
||||||
|
|
||||||
|
```
|
||||||
|
From: alice@localhost
|
||||||
|
To: bob@localhost
|
||||||
|
Subject: Mixed Content
|
||||||
|
|
||||||
|
<#multipart type=mixed>
|
||||||
|
<#part type=text/plain>
|
||||||
|
Please find the attached files.
|
||||||
|
|
||||||
|
Best,
|
||||||
|
Alice
|
||||||
|
<#part filename=/path/to/file1.pdf><#/part>
|
||||||
|
<#part filename=/path/to/file2.zip><#/part>
|
||||||
|
<#/multipart>
|
||||||
|
```
|
||||||
|
|
||||||
|
## MML Tag Reference
|
||||||
|
|
||||||
|
### `<#multipart>`
|
||||||
|
|
||||||
|
Groups multiple parts together.
|
||||||
|
|
||||||
|
- `type=alternative`: Different representations of same content
|
||||||
|
- `type=mixed`: Independent parts (text + attachments)
|
||||||
|
- `type=related`: Parts that reference each other (HTML + images)
|
||||||
|
|
||||||
|
### `<#part>`
|
||||||
|
|
||||||
|
Defines a message part.
|
||||||
|
|
||||||
|
- `type=<mime-type>`: Content type (e.g., `text/html`, `application/pdf`)
|
||||||
|
- `filename=<path>`: File to attach
|
||||||
|
- `name=<name>`: Display name for attachment
|
||||||
|
- `disposition=inline`: Display inline instead of as attachment
|
||||||
|
- `id=<cid>`: Content ID for referencing in HTML
|
||||||
|
|
||||||
|
## Composing from CLI
|
||||||
|
|
||||||
|
### Interactive compose
|
||||||
|
|
||||||
|
Opens your `$EDITOR`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message write
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reply (opens editor with quoted message)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message reply 42
|
||||||
|
himalaya message reply 42 --all # reply-all
|
||||||
|
```
|
||||||
|
|
||||||
|
### Forward
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message forward 42
|
||||||
|
```
|
||||||
|
|
||||||
|
### Send from stdin
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat message.txt | himalaya template send
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prefill headers from CLI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message write \
|
||||||
|
-H "To:recipient@example.com" \
|
||||||
|
-H "Subject:Quick Message" \
|
||||||
|
"Message body here"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- The editor opens with a template; fill in headers and body.
|
||||||
|
- Save and exit the editor to send; exit without saving to cancel.
|
||||||
|
- MML parts are compiled to proper MIME when sending.
|
||||||
|
- Use `himalaya message export --full` to inspect the raw MIME structure of received emails.
|
||||||
Reference in New Issue
Block a user