Gareth Wilson Gareth Wilson

Guide to SMTP2GO Webhooks: Features and Best Practices

Published


SMTP2GO webhooks tell your application what happens to the email and SMS you send through SMTP2GO. An email is delivered, opened or clicked, bounces, is marked as spam, or a recipient unsubscribes, and SMTP2GO calls your endpoint, so you can update contact records, suppress bad addresses and track engagement as it happens.

This guide covers how SMTP2GO webhooks are set up, the events and parameters they send, how to authenticate them with the Authorization header, how retries work, and the practices that keep a receiver reliable.

What are SMTP2GO webhooks?

An SMTP2GO webhook is an HTTP POST to your URL for each email or SMS event you select. You decide which senders it applies to (SMTP users, API keys or authenticated IPs), which events it reports, and whether the body is JSON or Form encoded.

SMTP2GO doesn't sign webhooks. Each webhook can have an optional Authorization header of type bearer or basic, which SMTP2GO sends with every request. SMTP2GO's overview also mentions other ways to protect the URL: credentials embedded in the URL, a password query parameter, a hard-to-guess path, or checking that requests come from the addresses behind webhooks.smtp2go.com. The Authorization header is the cleanest of these, and the one Hookdeck checks.

SMTP2GO webhook features

FeatureDetails
ConfigurationSMTP2GO App, Settings > Webhooks > Manage Webhooks, or the API
Limit1 webhook on the free plan, up to 10 on paid plans
ScopeSelected SMTP users, API keys or authenticated IPs
MethodPOST
Body formatJSON or form-encoded, chosen per webhook. The API defaults to form
Event fieldevent
AuthenticationOptional Authorization header, bearer or basic
Signature and timestamp headerNone
Timeout10 seconds, measured until response headers arrive
RetriesUp to 35 times over 48 hours
Failed notificationsViewable, retryable and cancellable in the App
Custom email headersCan be added to the event data
Source IPsNo fixed list. SMTP2GO suggests the A record of webhooks.smtp2go.com

Events and parameters

Email eventMeaning
processedReceived by SMTP2GO and being processed for delivery
deliveredThe recipient server accepted it with a 250 response
openOpened. Can fire on each open
clickA tracked link was clicked. Can fire on each click
bounceBounced. The bounce parameter says hard or soft
spamMarked as spam. The address is added to your suppressions
unsubscribeUnsubscribed through the unsubscribe footer. The address is added to your suppressions
resubscribeResubscribed, or removed from the suppressions page
rejectRejected: a suppressed address, an unverified sender, or a sandboxed sender

SMS events cover messages that are sending, submitted, delivered, failed or rejected, plus recipient opt-outs. The event values SMTP2GO documents for SMS are sms_sending, sms_submitted, sms_delivered, sms_failed and sms_rejected.

Email events carry a flat set of parameters, including event, time, sendtime, sender, from, rcpt, recipients, subject, email_id, id (the webhook's unique ID), message-id, auth (the SMTP user, the first 16 characters of the API key, or the IP that sent the email), and, for opens and clicks, user-agent, client, client-device, client-os and geoip-* fields. SMS events carry fields such as message_id, destination_number, source_number, status_code and received_timestamp.

Some names contain hyphens (message-id, read-secs, geoip-country), so read them with bracket notation rather than attribute access.

Inspect SMTP2GO webhooks as they arrive. Use a Hookdeck Inspect URL as the webhook URL and click Test this webhook to see the exact headers and body for your output type, with no account or setup required.

Setting up SMTP2GO webhooks

Generate a long random token first, for example with openssl rand -hex 32.

  1. In the SMTP2GO App, go to Settings > Webhooks > Manage Webhooks and click Add Webhook.
  2. Enter your HTTPS endpoint as the URL.
  3. In Authorization header, choose bearer and enter your token.
  4. Under Users, select the SMTP users, API keys or authenticated IPs the webhook applies to.
  5. Choose the Output type: JSON or Form encoded.
  6. Select the email events and SMS events to include, and any custom email headers you want reported.
  7. Click Save changes, then Test this webhook.

Through the API, webhook/add takes the same settings, with auth_header_type (bearer or basic) and auth_header_value (a custom token, or base64(user:pass) for basic). Set output_format to json explicitly if you want JSON, since the API defaults to form.

With Hookdeck. SMTP2GO is a supported source in Hookdeck. Its setup note reads: "Set an Authorization header on the SMTP2GO webhook and paste the full value, including the "Bearer " or "Basic " prefix." Create a source with the SMTP2GO type and use its URL as the webhook URL. In Authorization Header, paste the whole header value, for example Bearer your-long-random-token. SMTP2GO's docs don't print the outgoing header, so check the first test delivery in Hookdeck and make sure the value matches what arrives. The source accepts POST only, which is what SMTP2GO sends. A request with a missing or wrong value still gets a 200 from Hookdeck, but Hookdeck marks it as failed verification and doesn't deliver it to your service.

For local development, hookdeck listen 3000 smtp2go --path /webhooks/smtp2go gives you a public URL that forwards to your machine.

Securing SMTP2GO webhooks

Compare the whole Authorization header with the value you expect, prefix included, in constant time. Then parse the body as JSON or form data, depending on its content type.

const crypto = require('crypto');
const express = require('express');

// The full value, e.g. "Bearer your-long-random-token".
const EXPECTED = process.env.SMTP2GO_AUTHORIZATION;

function safeEqual(received, expected) {
  const a = Buffer.from(received, 'utf8');
  const b = Buffer.from(expected, 'utf8');
  // timingSafeEqual throws on unequal lengths, so check first.
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

function parseBody(req) {
  const text = req.body.toString('utf8');
  if ((req.get('content-type') || '').includes('application/json')) {
    return JSON.parse(text);
  }
  return Object.fromEntries(new URLSearchParams(text)); // Form encoded
}

const app = express();

app.post('/webhooks/smtp2go', express.raw({ type: '*/*' }), (req, res) => {
  const received = req.get('authorization');
  if (!EXPECTED || typeof received !== 'string' || !safeEqual(received, EXPECTED)) {
    return res.sendStatus(401);
  }

  let event;
  try {
    event = parseBody(req);
  } catch {
    return res.sendStatus(400);
  }

  if (event.event === 'bounce' && event.bounce === 'hard') {
    // Suppress event.rcpt in your own system.
  }

  res.sendStatus(200);
});

The same check in Python:

import hmac
import os

EXPECTED = os.environ.get("SMTP2GO_AUTHORIZATION", "")  # e.g. "Bearer your-token"


def verify_smtp2go_request(headers) -> bool:
    if not EXPECTED:
        return False  # never accept when unconfigured
    received = headers.get("Authorization")
    if not received:
        return False
    # Compare bytes: compare_digest raises TypeError on a non-ASCII str.
    return hmac.compare_digest(received.encode("utf-8"), EXPECTED.encode("utf-8"))

A static Authorization value authenticates the sender, not the body, so a modified payload still passes, and nothing stops a captured request from being replayed. Use HTTPS and a long random token. Avoid the URL-based options from SMTP2GO's overview where you can: credentials in a URL or query string end up in access logs.

Make SMTP2GO webhooks production-ready. Hookdeck Event Gateway checks the Authorization header, answers within SMTP2GO's 10-second timeout, and absorbs bursts of open and click events before they reach your service.

SMTP2GO webhook limitations and pain points

Opens and clicks come in bursts

The Problem: A large campaign produces a flood of open and click events that can overload a small receiver.

Why It Happens: Each open and each click can trigger its own event, and SMTP2GO sends them as they happen.

Workarounds:

  • Only subscribe to engagement events if you use them.
  • Queue events in the handler and process them at a steady rate.

How Hookdeck Can Help: Hookdeck accepts the burst and delivers to your service at a max delivery rate you set.

Two body formats

The Problem: A handler written for JSON fails on form-encoded bodies, or the other way round.

Why It Happens: The output type is a per-webhook setting, and the API defaults to form encoding even though the App lets you pick JSON.

Workarounds:

  • Set the output type explicitly and parse by Content-Type, as in the example above.

How Hookdeck Can Help: Hookdeck shows each request's content type and body, so you can confirm the format before you deploy a parser.

The outgoing header isn't documented

The Problem: The value you compare against may not match what SMTP2GO sends.

Why It Happens: SMTP2GO documents the bearer and basic options and the API fields, but not the exact header string it builds from them.

Workarounds:

  • Capture a test delivery and copy the Authorization value exactly.
  • Prefer bearer over basic, so you're comparing one random token rather than an encoded username and password.

How Hookdeck Can Help: Hookdeck keeps failed-verification requests with their headers, so you can compare the received value with the one on the source.

Long retries, then cancellation

The Problem: A broken handler gets the same events again for two days.

Why It Happens: SMTP2GO retries up to 35 times over 48 hours: 5 times in the first 30 minutes, hourly for 24 hours, every 6 hours for the next 24, every 12 hours for the next 24, and once more after that.

Workarounds:

  • Make handlers idempotent so repeats do no harm.
  • Use Settings > Webhooks > Failed Notifications to retry or cancel failed attempts after a fix.

How Hookdeck Can Help: Hookdeck acknowledges SMTP2GO straight away, so its retry schedule doesn't run, and you retry delivery to your service on your own terms.

Best practices

Deduplicate on id

SMTP2GO describes id as the unique ID for the webhook. Store it and skip repeats, since retries resend the same event. See our guide to webhook idempotency.

Act on hard bounces and spam complaints

bounce with hard, spam and unsubscribe mean you should stop mailing that address. SMTP2GO already suppresses spam and unsubscribe addresses on its side; mirror them in your own list so other senders respect them too.

Report custom headers you need for correlation

Add a custom email header, such as your own message or campaign ID, and select it in the webhook's email headers. It comes back with each event, so you can match events to your records.

Acknowledge fast and process asynchronously

SMTP2GO times out after 10 seconds without response headers. Return 200 once the header checks out and the body is queued. See why to process webhooks asynchronously.

Conclusion

SMTP2GO webhooks report email and SMS events as JSON or form-encoded POST requests, with an optional bearer or basic Authorization header and no signature. Set a bearer token, compare the full header in constant time, parse by content type, deduplicate on id, and answer within 10 seconds so you aren't relying on 48 hours of retries.

Hookdeck Event Gateway checks the header, absorbs engagement bursts, and retries and replays delivery to your service.

Get started with Hookdeck for free and handle SMTP2GO webhooks reliably in minutes.


Gareth Wilson

Gareth Wilson

Product Marketing

Multi-time founding marketer, Gareth is PMM at Hookdeck and author of the newsletter, Community Inc.