hermes-agent/optional-skills/email/mail-auto-draft/SKILL.md
2026-03-28 02:23:40 +01:00

287 lines
7 KiB
Markdown

---
name: mail-auto-draft
description: Build and deploy a Himalaya-based inbound email auto-reply workflow with self-reply protection, Reply-To aware recipient selection, and systemd user timers.
version: 1.0.0
author: jozrftamson
license: MIT
metadata:
hermes:
tags: [email, himalaya, imap, smtp, automation, systemd, gmail]
category: email
prerequisites:
commands: [himalaya, python3, systemctl]
---
# Mail Auto-Draft with Himalaya
Build a practical local inbound email automation workflow that:
- reads new mail from INBOX via Himalaya
- classifies simple inbound requests
- automatically replies only to safe standard cases
- avoids self-reply loops
- runs continuously via systemd user timers
This skill is intentionally optional. It is highly useful for users who want mailbox automation, but it depends on local mail account setup, machine-specific deployment choices, and provider-specific operational details.
## When to Use
Use this skill when the user wants to automate replies to inbound email on their own mailbox, especially on Ubuntu/Linux with Himalaya.
Typical requests:
- "Automatically answer simple incoming emails"
- "Set up a local email auto-responder with Gmail and Himalaya"
- "Keep it running in the background every minute"
- "Make it safe enough for production"
This skill is for user-owned mailboxes, not agent-owned inboxes like AgentMail.
## Quick Reference
Typical flow:
1. configure Himalaya for the mailbox
2. create or adapt `process_inbox.py` and `config.yaml`
3. test in draft mode
4. enable auto-send only for safe whitelisted categories
5. run continuously with a `systemd --user` timer
## Requirements
1. Himalaya CLI installed
2. Python 3 with `pyyaml` and `requests`
3. A working IMAP/SMTP account in `~/.config/himalaya/config.toml`
4. A local project directory containing:
- `process_inbox.py`
- `config.yaml`
- `prompts/system_prompt.txt`
- `prompts/user_prompt.txt`
## Recommended Project Files
Minimum structure:
- `process_inbox.py`
- `config.yaml`
- `config.example.yaml`
- `README.md`
- `SCHNELLSTART_AND_INSTALLATION.md`
- `deploy/systemd/mail-auto-draft.service`
- `deploy/systemd/mail-auto-draft.timer`
- `prompts/`
Local runtime dirs:
- `drafts/`
- `logs/`
- `data/`
- `runtime/`
## Safe Defaults
For production, prefer:
- `require_unseen: true`
- `require_new_in_inbox: true`
- `require_whitelist: true`
- `require_high_confidence: true`
- `confidence_threshold` around `70` to `85`
- `forbid_sensitive_categories` includes:
- `sensibel`
- `individuell`
- `unklar`
- `ignorieren`
## Critical Safety Rules
### 1. Always define own addresses
In `config.yaml`:
```yaml
own_addresses:
- your-address@example.com
```
This prevents self-reply loops when your own replies appear in INBOX.
### 2. Prefer Reply-To over From
When selecting the reply recipient:
1. use `Reply-To` if present
2. otherwise use `From`
3. if the generated reply template has empty `To:`, backfill it before sending
### 3. Ignore own-sender mail
Any inbound mail whose sender matches `own_addresses` should be ignored with a reason like `self_sender`.
### 4. Do not auto-send uncertain categories
Keep these as draft-only or blocked:
- `sensibel`
- `individuell`
- `unklar`
- `ignorieren`
### 5. Treat Gmail Sent append failures carefully
On Gmail, SMTP may succeed while Himalaya still exits non-zero because append to Sent fails.
If stderr includes both:
- `cannot add IMAP message`
- `Folder doesn't exist`
then treat it as likely sent and avoid duplicate resend.
## Himalaya Config Notes
For Gmail, use an app password, not the normal password.
Recommended pattern:
- keep the app password out of the project repo
- store it in a local secret file such as:
`~/.config/mail-auto-draft/secrets.env`
Example local secret file:
```bash
GMAIL_APP_PASSWORD='YOUR_APP_PASSWORD'
```
Example auth command in `~/.config/himalaya/config.toml`:
```toml
backend.auth.cmd = "sh -lc '. /home/USER/.config/mail-auto-draft/secrets.env && printf %s \"$GMAIL_APP_PASSWORD\"'"
message.send.backend.auth.cmd = "sh -lc '. /home/USER/.config/mail-auto-draft/secrets.env && printf %s \"$GMAIL_APP_PASSWORD\"'"
```
## Continuous Background Processing
Prefer a `systemd --user` oneshot service plus timer over an infinite Python loop.
Example service template:
```ini
[Unit]
Description=Process inbox and auto-reply via Himalaya
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
WorkingDirectory=__PROJECT_DIR__
ExecStart=/usr/bin/flock -n __PROJECT_DIR__/runtime/process_inbox.lock /usr/bin/python3 __PROJECT_DIR__/process_inbox.py --limit 5
```
Example timer template:
```ini
[Unit]
Description=Run mail auto-draft every minute
[Timer]
OnBootSec=2min
OnUnitActiveSec=60s
Persistent=true
Unit=mail-auto-draft.service
[Install]
WantedBy=timers.target
```
## Procedure
### 1. Verify dependencies
```bash
himalaya --version
python3 -c "import yaml, requests"
python3 -m py_compile process_inbox.py
```
### 2. Test in draft mode first
```bash
python3 process_inbox.py --mode draft --limit 5
```
Review:
- generated drafts
- `logs/mail_actions.jsonl`
### 3. Switch to auto mode only after review
```bash
python3 process_inbox.py --mode auto --limit 1
```
### 4. Enable timer-based background processing
```bash
systemctl --user daemon-reload
systemctl --user enable --now mail-auto-draft.timer
systemctl --user start mail-auto-draft.service
```
## Useful Runtime Commands
Status:
```bash
systemctl --user status mail-auto-draft.timer --no-pager
systemctl --user status mail-auto-draft.service --no-pager
```
Logs:
```bash
journalctl --user -u mail-auto-draft.service -n 50 --no-pager
```
Manual run:
```bash
python3 process_inbox.py --limit 1
```
## Example Workflow
Example use case:
- a user wants automatic replies for simple inbound messages such as information requests, lightweight appointment requests, or simple acknowledgements
- Hermes helps configure Himalaya and the local processing script
- the workflow only auto-sends safe standard categories
- anything uncertain stays out of the auto-send path
## Troubleshooting
### It replies to itself repeatedly
Check:
- `own_addresses` is configured
- self-sender mail is ignored
- only new/unseen mail is processed
### Replies go to the wrong recipient
Check:
- recipient selection prefers `Reply-To`
- fallback uses `From`
- empty `To:` in reply templates is repaired before send
### It sends to newsletters or bulk mail
Tighten:
- subject keyword filters
- header ignore rules
- whitelist-only auto-send
- high confidence requirement
### Himalaya says send failed but recipient got the email
This is often the Gmail IMAP append issue after SMTP success.
Verify recipient delivery before resending.
## Verification
A successful setup should show:
- inbound external mail gets processed
- `chosen_reply_recipient` is logged correctly
- own mail is ignored with `self_sender`
- background timer runs every minute
- no repeated self-reply loops
## References
- `references/production-checklist.md`
- `references/setup-commands.md`