Files
hermes-skills/skills/email/email-workflows/references/shonuff-inbox-monitoring.md
T

2.6 KiB

Sho'Nuff Inbox Monitoring

Goal: Monitor shonuff@germainebrown.com for incoming replies/emails, extract content, and notify Germaine via Telegram.

Architecture

Two-layer system:

  1. Collector script (shonuff-inbox-collect.py, no_agent=True) — runs every 15m, checks for UNSEEN messages from non-trusted senders, outputs JSON with: from, subject, date, body_preview (first 500 chars), uid. Silent when nothing new. Marks messages as Seen after processing.

  2. LLM cron job — takes the collector's JSON output, summarizes each message in 2-3 sentences for Germaine: who sent it, what it's about, whether action is needed. Responds with SILENT when nothing new.

Script location

/root/.hermes/scripts/shonuff-inbox-collect.py

Trusted senders (skipped, not reported)

TRUSTED = ["g@germainebrown.com"]

The collector skips messages FROM these addresses entirely — no output, no summary. All other senders are reported.

Known limitations

  • Apple Mail replies are HTML-only — they often send with no text/plain alternative. The get_text_body() function strips HTML tags to extract plain text, but this can miss content that's rendered only through CSS or loaded images.
  • Body preview is truncated at 500 chars — the LLM summary may need more context for long messages. The preview in the JSON output is an excerpt, not the full body.

Body extraction

def get_text_body(msg):
    body = ""
    if msg.is_multipart():
        for part in msg.walk():
            ct = part.get_content_type()
            if ct == "text/plain":
                payload = part.get_payload(decode=True)
                if payload:
                    body += payload.decode("utf-8", errors="replace")
    else:
        payload = msg.get_payload(decode=True)
        if payload:
            body = payload.decode("utf-8", errors="replace")
    body = re.sub(r'\s+', ' ', body).strip()
    return body[:2000]

The fallback path (HTML-only) is handled by extracting text/html parts and stripping tags manually.

Cron config

  • Schedule: every 15m
  • no_agent=True on the collector
  • LLM cron reads output via context_from job ID
  • If nothing changed from last run, the LLM responds SILENT and the user sees nothing

Setup checklist

  • IMAP credentials in .env (SHONUFF_EMAIL, SHONUFF_EMAIL_PASS)
  • Collector script at ~/scripts/shonuff-inbox-collect.py
  • no_agent=True cron at 15m
  • LLM cron reading collector's output
  • Trusted senders configured
  • Base64 image for signature stored at ~/references/shonuff-image-b64.txt