Skip to content

Daily email report of slowdowns and dropouts - #2

Merged
MSabacreationslab merged 3 commits into
mainfrom
feature/email-reports
Sep 26, 2026
Merged

MSabacreationslab merged 3 commits into
mainfrom
feature/email-reports

Conversation

@MSabacreationslab

Copy link
Copy Markdown
Owner

What

A daily email report of every slowdown and dropout, with its reason, the game that was running, and who was busy on the network at the time.

  • Dashboard card: fields for who gets it (comma-separated), the sending account, and an app password; a daily on/off switch; Save, Send report now and Preview report.
  • When it sends: once a day when HogWatch starts, or at 8 AM if it's already running. Each daily report covers the time since the previous one (7 days at most). A failed send is logged and retried an hour later.
  • Sending: through the user's own SMTP account (Gmail by default), always over TLS (STARTTLS on 587, TLS from the start on 465). If Gmail rejects the login, the error explains app passwords.
  • Password storage: encrypted with Windows DPAPI in data/email.json (gitignored), so only that Windows account can read it. The API never returns it; it only reports whether one is saved.
  • CLI: python -m hogwatch send-report [--hours N] [--preview]
  • Fix: eero's "Unassigned" profile no longer shows up as a device owner.

Security

The dashboard holds email settings now, so it's locked down further:

  • It only answers requests whose Host is 127.0.0.1:<port> or localhost:<port>. This blocks DNS-rebinding pages from reading the API.
  • Every POST needs the X-HogWatch: 1 header, which cross-site pages can't send without a CORS preflight (never approved). A random web page can't change the recipient or trigger emails.
  • Device names are HTML-escaped in the email.

Testing

  • 20 new tests in tests/test_report.py: DPAPI storage, the password never appearing in API responses, Host and header enforcement, HTML escaping, report counts and advice, SMTP flows (smtplib mocked), and daily scheduling. 51/51 pass locally.
  • Manual run against a demo server: a bad address shows a clear error, Save persists, Send without a password refuses, and the preview renders.
  • No real email was sent. The first real send needs the owner's app password.

Note: this repo's CI workflow is added in #1. This PR won't have its test check until #1 is merged and main is merged into this branch.

🤖 Generated with Claude Code

MSabacreationslab and others added 3 commits September 24, 2026 23:42
Devices outside any eero profile report the profile name 'Unassigned', which
showed up in explanations as if it were a person.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Dashboard card: recipients, sending account, app password, daily on/off,
  Send report now, and Preview report.
- Sent once a day at startup (or 8 AM if already running) through the user's
  own SMTP account, TLS only. The password is DPAPI-encrypted and never
  returned by the API.
- send-report CLI (with --preview).
- Dashboard server now only answers Host 127.0.0.1/localhost (blocks DNS
  rebinding), and every POST needs the X-HogWatch header.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MSabacreationslab
MSabacreationslab merged commit 6afe4b6 into main Sep 26, 2026
1 check passed
@MSabacreationslab
MSabacreationslab deleted the feature/email-reports branch September 26, 2026 04:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant