Agent skill
SMTP2GO Webhooks Skill
Receive and authenticate SMTP2GO email and SMS webhooks. Use when setting up an SMTP2GO webhook endpoint, checking the Authorization header (Bearer or Basic), debugging 401s, parsing JSON or form-encoded payloads, or handling events like delivered, bounce, open, click, spam and sms_failed.
Install this skill
npx skills add hookdeck/webhook-skills --skill smtp2go-webhooks
SMTP2GO (email and SMS delivery) sends an HTTP or HTTPS POST to your URL whenever an email or SMS event happens in your account. Payloads are not signed: there is no HMAC, signature header or timestamp. The only built-in credential is an optional Authorization header you configure on the webhook.
When to Use This Skill
- How do I receive SMTP2GO webhooks?
- How do I authenticate SMTP2GO webhooks? (Does SMTP2GO sign them? No: shared
Authorizationheader only) - Why does my SMTP2GO webhook endpoint return 401?
- How do I parse SMTP2GO's JSON or form-encoded webhook body?
- How do I handle
delivered,bounce,open,click,spam,unsubscribeorsms_failedevents?
Verification (core)
Set an Authorization header on the SMTP2GO webhook and paste the full value, including the "Bearer " or "Basic " prefix.
The docs don't print the exact outgoing header (the API's auth_header_type is bearer or basic; auth_header_value is "either base64(user:pass) or a custom token"). Capture one delivery and set SMTP2GO_AUTHORIZATION to exactly what arrives in Authorization (expected Bearer <token> or Basic <base64>). Compare the whole header value; don't strip, parse or base64-decode the prefix.
const crypto = require('crypto');
// Hash both sides: equal-length buffers, so timingSafeEqual never throws.
function safeEqual(a, b) {
const ha = crypto.createHash('sha256').update(String(a)).digest();
const hb = crypto.createHash('sha256').update(String(b)).digest();
return crypto.timingSafeEqual(ha, hb);
}
function verifySmtp2goRequest(headers, expected = process.env.SMTP2GO_AUTHORIZATION) {
if (!expected) return false; // never accept when unconfigured
const received = headers['authorization']; // full value, e.g. "Bearer abc123"
return Boolean(received) && safeEqual(received, expected);
}
Return 401 on a missing or mismatched header, 400 for a body you can't parse, 200 once handled. Read the body raw (express.raw({ type: '*/*' })) and parse it only after the check. Python and Next.js equivalents are in references/verification.md.
A static shared credential authenticates the sender, not the body, and gives no replay protection (no signature, no timestamp). Use HTTPS, rotate the credential if it leaks, and dedupe on the webhook
id.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Request Body
SMTP2GO sends a POST (not a GET) with a data output type of JSON or Form encoded, chosen in the webhook's settings. Parse application/json and application/x-www-form-urlencoded. Parameters are flat; dispatch on event.
Event Types
| Kind | event values |
|---|---|
processed, delivered, open, click, bounce, spam, unsubscribe, resubscribe, reject | |
| SMS | sms_sending, sms_submitted, sms_delivered, sms_failed, sms_rejected |
Common fields: event, time, sendtime, sender, rcpt, email_id, message-id, id (unique webhook id). Bounces add bounce (hard or soft), host and message. SMS events use destination_number, message_id, status_code, received_timestamp. See references/overview.md.
Retries
Failures retry for up to 48 hours (a maximum of 35 attempts), and the timeout is 10 seconds with no response headers. Respond fast with 200, and make handlers idempotent.
Environment Variables
SMTP2GO_AUTHORIZATION=Bearer your-token # full Authorization header value, prefix included
Local Development
npx hookdeck-cli listen 3000 smtp2go --path /webhooks/smtp2go
No account required. Use the printed URL as the SMTP2GO webhook URL.
Resources
- references/overview.md - Events, parameters, retries
- references/setup.md - Creating the webhook in the app or API, the Authorization header
- references/verification.md - Header check in Node, Python and Next.js, gotchas
- examples/ - Runnable Express, Next.js and FastAPI handlers with tests