Publish himalaya via gitea-publish skill
This commit is contained in:
@@ -0,0 +1,295 @@
|
|||||||
|
---
|
||||||
|
name: himalaya
|
||||||
|
description: "CLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language)."
|
||||||
|
homepage: https://github.com/pimalaya/himalaya
|
||||||
|
metadata:
|
||||||
|
builtin_skill_version: "1.3"
|
||||||
|
qwenpaw:
|
||||||
|
emoji: "📧"
|
||||||
|
requires:
|
||||||
|
bins:
|
||||||
|
- himalaya
|
||||||
|
install:
|
||||||
|
- id: brew
|
||||||
|
kind: brew
|
||||||
|
formula: himalaya
|
||||||
|
bins:
|
||||||
|
- himalaya
|
||||||
|
label: "Install Himalaya (brew)"
|
||||||
|
---
|
||||||
|
# Himalaya Email CLI
|
||||||
|
|
||||||
|
Himalaya is a CLI email client that lets you manage emails from the terminal using IMAP, SMTP, Notmuch, or Sendmail backends.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- `references/configuration.md` (config file setup + IMAP/SMTP authentication)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. **Himalaya CLI** - the `himalaya` binary must already be on `PATH`. Check with `himalaya --version`.
|
||||||
|
- **Recommended: v1.2.0 or newer.** Older releases can fail against some IMAP servers; v1.2.0+ includes related fixes.
|
||||||
|
2. A configuration file at `~/.config/himalaya/config.toml`
|
||||||
|
3. IMAP/SMTP credentials configured (password stored securely)
|
||||||
|
|
||||||
|
## Configuration Setup
|
||||||
|
|
||||||
|
Run the interactive wizard to set up an account (replace `default` with
|
||||||
|
any name you want, e.g. `gmail`, `work`):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya account configure default
|
||||||
|
```
|
||||||
|
|
||||||
|
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"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are using 163 mail account, add `backend.extensions.id.send-after-auth = true` in the config file to ensure proper functionality.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
```
|
||||||
|
|
||||||
|
If meet with error, try:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya envelope list -f INBOX -s 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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
|
||||||
|
```
|
||||||
|
|
||||||
|
### Send / Compose Emails
|
||||||
|
|
||||||
|
**Recommended approach:** Use `template write | template send` pipeline for simple emails.
|
||||||
|
|
||||||
|
**Send a simple email:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export EDITOR=cat
|
||||||
|
himalaya template write \
|
||||||
|
-H "To: recipient@example.com" \
|
||||||
|
-H "Subject: Email Subject" \
|
||||||
|
"Email body content" | himalaya template send
|
||||||
|
```
|
||||||
|
|
||||||
|
**Send with multiple headers:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export EDITOR=cat
|
||||||
|
himalaya template write \
|
||||||
|
-H "To: recipient@example.com" \
|
||||||
|
-H "Cc: cc@example.com" \
|
||||||
|
-H "Subject: Email Subject" \
|
||||||
|
"Email body content" | himalaya template send
|
||||||
|
```
|
||||||
|
|
||||||
|
**Send with attachments (using Python):**
|
||||||
|
|
||||||
|
For emails with attachments, use Python's `smtplib` and `email.mime` modules:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import smtplib
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.base import MIMEBase
|
||||||
|
from email import encoders
|
||||||
|
|
||||||
|
msg = MIMEMultipart()
|
||||||
|
msg['From'] = 'sender@163.com'
|
||||||
|
msg['To'] = 'recipient@example.com'
|
||||||
|
msg['Subject'] = 'Email with attachment'
|
||||||
|
|
||||||
|
msg.attach(MIMEText('Email body', 'plain'))
|
||||||
|
|
||||||
|
# Add attachment
|
||||||
|
with open('/path/to/file.pdf', 'rb') as f:
|
||||||
|
part = MIMEBase('application', 'octet-stream')
|
||||||
|
part.set_payload(f.read())
|
||||||
|
encoders.encode_base64(part)
|
||||||
|
part.add_header('Content-Disposition', 'attachment; filename="file.pdf"')
|
||||||
|
msg.attach(part)
|
||||||
|
|
||||||
|
server = smtplib.SMTP_SSL('smtp.163.com', 465)
|
||||||
|
server.login('sender@163.com', 'password')
|
||||||
|
server.send_message(msg)
|
||||||
|
server.quit()
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ MML attachment limitations:** The `template send` command with MML format may fail with "cannot parse MML message: empty body" when using multipart/attachments. This is a known issue in himalaya v1.1.0. Use Python approach for attachments.
|
||||||
|
|
||||||
|
**⚠️ Avoid `message write` for automation:** The `himalaya message write` command requires interactive TUI selection (Edit/Discard/Quit) and will hang in non-interactive environments.
|
||||||
|
|
||||||
|
**⚠️ `message send` limitations:** Direct `himalaya message send <raw_email>` may fail with "cannot send message without a recipient" due to header parsing issues. Use `template send` instead.
|
||||||
|
|
||||||
|
**Configuration requirement:** Ensure `message.send.save-to-folder` is set in config.toml to avoid "Folder not exist" errors:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.163]
|
||||||
|
# ... other config ...
|
||||||
|
message.send.save-to-folder = "Sent"
|
||||||
|
```
|
||||||
|
|
||||||
|
For 163 mail accounts, create the Sent folder first if it doesn't exist:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya folder create Sent
|
||||||
|
```
|
||||||
|
|
||||||
|
### Move/Copy Emails
|
||||||
|
|
||||||
|
Move to folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message move 42 "Archive"
|
||||||
|
```
|
||||||
|
|
||||||
|
Copy to folder:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
himalaya message copy 42 "Important"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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 --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.
|
||||||
|
- **For automation:** Always use `template write | template send` pipeline with `export EDITOR=cat`.
|
||||||
|
- **163 Mail users:** Set `backend.extensions.id.send-after-auth = true` and `message.send.save-to-folder = "Sent"` in config.
|
||||||
|
- **Folder names:** Use English folder names (e.g., "Sent" instead of "已发送") for better compatibility.
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
# 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"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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"
|
||||||
|
```
|
||||||
|
|
||||||
|
**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 custom folder names:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[accounts.default.folder.alias]
|
||||||
|
inbox = "INBOX"
|
||||||
|
sent = "Sent"
|
||||||
|
drafts = "Drafts"
|
||||||
|
trash = "Trash"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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"
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user