mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
287 lines
7 KiB
Markdown
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`
|