name: cloudflare-email-delivery description: Deliver Hermes AI Topics reports via Cloudflare Email Service. Setup, cron config, and troubleshooting for email channel. version: 1.0.0
Cloudflare Email Report Delivery
Add email as a delivery channel for Hermes AI Topics hot-posts reports, using Cloudflare Email Service (REST API).
Architecture
Slack cron (5e91a0b47c32)
└── generates Japanese hot-posts report → Slack channel
└── output saved to ~/.hermes/cron/output/5e91a0b47c32/
└── (15min offset) Email relay (new cron job)
└── no_agent script reads latest Slack output
└── sends HTML email via Cloudflare Email Service
Mirrors Discord relay pattern but uses Cloudflare Email API instead of Discord webhook.
Prerequisites (User Action Required)
Before the cron job can work, the user must:
- Enable Cloudflare Workers Paid plan ($5/mo) on the kusari.cc Cloudflare account
- Onboard sender domain in Cloudflare Dashboard:
- Email → Email Sending → Onboard Domain
- Add a subdomain like
report.kusari.cc(isolates reputation from main domain) - Cloudflare auto-adds SPF/DKIM/DMARC + cf-bounce MX records
- Create API token at https://dash.cloudflare.com/profile/api-tokens → Create Token → Custom:
- Permissions:
Email Sending — Write - Account Resources: Include the target account
- Permissions:
- Set environment variables in
~/.hermes/.env:CF_ACCOUNT_ID=<your-cloudflare-account-id> CF_EMAIL_API_TOKEN=<token-with-email_sending_write> CF_EMAIL_FROM=Hermes Agent <hermes@report.kusari.cc> CF_EMAIL_TO=<recipient-email> CF_EMAIL_SUBJECT_PREFIX=[Hermes Report]
Setup (Agent Actions)
After user provides env vars:
Test with dry run:
python3 ~/ai-topics/scripts/cloudflare_email.py --subject "Test" --text "Hello from Hermes" --dry-runSend test email:
python3 ~/ai-topics/scripts/cloudflare_email.py --subject "Hermes Test" --text "This is a test email from Hermes Agent via Cloudflare Email Service."Test relay script:
python3 ~/.hermes/scripts/email_report_relay.pyCreate cron job (see below)
Cron Job Configuration
cronjob(
action="create",
name="ai-topics-email-hot-posts",
schedule="45 0,4,8,12,16,20",
script="email_report_relay.py",
no_agent=True,
deliver="local", # or specific email/platform target
)
- Schedule: 15 min after Slack job (mirrors Discord offset)
- no_agent=True: Zero token cost — the script IS the job
- Script behavior: If Slack output exists and is < 6h old → extracts response → emails it. If no output or stale → exits 0 silently (no delivery).
Files
| File | Location | Purpose |
|---|---|---|
| Core module | ~/ai-topics/scripts/cloudflare_email.py |
send_email_via_cloudflare() function + CLI |
| Core module (cron copy) | ~/.hermes/scripts/cloudflare_email.py |
Copy for cron execution |
| Relay script | ~/.hermes/scripts/email_report_relay.py |
Reads Slack output → emails via Cloudflare |
Email Format
The relay generates a clean HTML email:
- Header: Report timestamp + "Generated by Hermes Agent" attribution
- Body: Markdown converted to HTML (headers, tables, bold, italic, links, code blocks)
- Footer: Link to ai-topics repo + sent-via attribution
Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
CF_ACCOUNT_ID not set |
Env vars not loaded | Check ~/.hermes/.env has all 4 CF_EMAIL_* vars |
HTTP 403 |
Token missing email_sending:write scope |
Recreate token with correct permission |
HTTP 400 |
Domain not onboarded | Onboard sender domain in Cloudflare Dashboard |
No Slack output files found |
Slack job hasn't run yet | Run Slack job manually first: cronjob(action='run', job_id='5e91a0b47c32') |
Latest output is Xh old — skipping |
Slack job failed earlier | Check Slack cron status, re-run if needed |
permanent_bounces for all recipients |
Recipient email not valid / blocked | Check recipient address, check Cloudflare suppression list |
Pricing
- Workers Paid: $5/mo
- Emails: 3,000 free/mo, $0.35/1,000 after
- At 6 reports/day (~180/mo), the free tier covers all usage indefinitely
Related
- Wiki: [[concepts/cloudflare-email-sending]] — API reference, pricing comparison
- Wiki: [[entities/levelsio]] — Pieter Levels' original price comparison + migration prompt
- Raw: [[wiki/raw/articles/2026-05-10_levelsio_cloudflare-email-migration-prompt]]
- Skill:
wiki-ingestion-pipelines— Hot-posts reporting pipeline (Slack + Discord sections) - Skill:
cron-job-management— Cron job lifecycle management