HTTP endpoint called by the agentcr Cloudflare Worker (EmailRoutingAgent) to send outbound reply emails via Val Town's built-in email service.
Cloudflare Workers cannot send arbitrary outbound email without a verified sender domain. This val bridges that gap using Val Town's std/email.
The caller (Cloudflare Worker) authenticates by passing the shared secret in the JSON request body:
{ "secret": "<EMAIL_SECRET env var>", "to": "recipient@example.com", "subject": "Re: Your enquiry", "text": "Thank you for your message..." }
This val checks body.secret === process.env.EMAIL_SECRET. If they don't match → 401 Unauthorized.
Val Town (this val's environment variables):
EMAIL_SECRET=<your-chosen-secret>
Cloudflare — the worker reads EMAIL_INBOUND_SECRET and sends it as body.secret. The two vars must hold the same value:
npx wrangler secret put EMAIL_INBOUND_SECRET # paste the same value as EMAIL_SECRET above
Local dev (.dev.vars in project root):
EMAIL_INBOUND_SECRET=<same-value>
VALTOWN_SEND_URL=https://cookiemonster0922--<id>.web.val.run
POST <val-url>
Content-Type: application/json
{
"secret": string, // shared secret (required)
"to": string, // recipient address (required)
"subject": string, // email subject (required)
"text": string // plain-text body (required)
}
| Status | Meaning |
|---|---|
200 { ok: true } | Email sent successfully |
400 { ok: false, error: "..." } | Missing fields or invalid JSON |
401 Unauthorized | secret does not match EMAIL_SECRET env var |
405 Method Not Allowed | Non-POST request (OPTIONS allowed for CORS) |
500 { ok: false, error: "..." } | Val Town email API error |
| Symptom | Cause |
|---|---|
Worker logs send_reply_error: 401 | EMAIL_INBOUND_SECRET (Cloudflare) ≠ EMAIL_SECRET (this val), or one/both is unset |
Worker logs send_reply_error: 404 | VALTOWN_SEND_URL points to the wrong val URL |
| Variable | Required | Description |
|---|---|---|
EMAIL_SECRET | Yes | Shared secret — must match EMAIL_INBOUND_SECRET in Cloudflare |