Files
hermes-skills/skills/email/email-workflows/scripts/shonuff-inbox-collect.py
T

97 lines
3.4 KiB
Python

#!/usr/bin/env python3
"""Check shonuff@germainebrown.com inbox. Outputs JSON for LLM summary.
Silent if nothing new. Skips trusted senders (Germaine, mailer-daemon).
"""
import imaplib, email, json, os, hashlib
from email.utils import parsedate_to_datetime
HOST = "mail.germainebrown.com"
PORT = 993
USER = "shonuff@germainebrown.com"
PW = "Catches.bullets1985"
SEEN_FILE = "/root/.hermes/scripts/.shonuff-processed.json"
TRUSTED = ["g@germainebrown.com"]
def load_seen():
if os.path.exists(SEEN_FILE):
return set(json.load(open(SEEN_FILE)))
return set()
def save_seen(seen):
json.dump(list(seen), open(SEEN_FILE, "w"))
def safe_str(val):
if val is None: return ""
if isinstance(val, str): return val
try: return str(val)
except: return ""
def get_text_body(msg):
body = ""
# Try text/plain first
if msg.is_multipart():
for part in msg.walk():
if part.get_content_type() == "text/plain":
payload = part.get_payload(decode=True)
if payload:
body += payload.decode("utf-8", errors="replace")
# Fallback: extract text from text/html if no plain text found
if not body.strip():
for part in msg.walk():
if part.get_content_type() == "text/html":
payload = part.get_payload(decode=True)
if payload:
import html
text = payload.decode("utf-8", errors="replace")
text = re.sub(r'<[^>]+>', ' ', text)
text = html.unescape(text)
body = text
break
else:
payload = msg.get_payload(decode=True)
if payload:
ct = msg.get_content_type()
text = payload.decode("utf-8", errors="replace")
if ct == "text/html":
text = re.sub(r'<[^>]+>', ' ', text)
import html
text = html.unescape(text)
body = text
import re
body = re.sub(r'\s+', ' ', body).strip()
return body[:500]
def main():
seen = load_seen()
new_msgs = []
try:
conn = imaplib.IMAP4_SSL(HOST, PORT)
conn.login(USER, PW)
conn.select("INBOX")
status, data = conn.search(None, "UNSEEN")
if status == "OK" and data[0]:
for num in data[0].split():
status, msg_data = conn.fetch(num, "(RFC822)")
if status != "OK": continue
raw = email.message_from_bytes(msg_data[0][1])
sender = safe_str(raw.get("From", "")).strip()
subj = safe_str(raw.get("Subject", "(no subject)"))
mid = safe_str(raw.get("Message-ID", str(num)))
date = safe_str(raw.get("Date", ""))
if any(t.lower() in sender.lower() for t in TRUSTED): continue
h = hashlib.md5(mid.encode()).hexdigest()
if h in seen: continue
seen.add(h)
new_msgs.append({"from": sender, "subject": subj, "date": date, "body_preview": get_text_body(raw)[:500], "uid": num.decode()})
conn.store(num, "+FLAGS", "\\Seen")
conn.logout()
save_seen(seen)
except Exception as e:
print(json.dumps({"error": str(e)}))
return
if new_msgs:
print(json.dumps({"messages": new_msgs}, indent=2))
if __name__ == "__main__":
main()