Skip to content

Powered by Grav CMS + Helios Theme

SMTP2GO

This page is for a store sending through SMTP2GO that wants delivered, bounced and complained figures on its campaign screens. Read Delivery reports and providers first for what a provider webhook is and what the store does with each event.

Before you begin

  • An SMTP2GO account with a verified sender. Since 11 April 2025 SMTP2GO requires every message to come from a verified sender domain or a verified sender address.
  • An API key beginning api-.
  • The grav-plugin-email-smtp2go plugin at 1.1.2 or later, with the Grav Email plugin at 5.2.0 or later on PHP 8.1 or later.
  • The Email plugin's Mail Engine set to SMTP2GO.

Warning

SMTP2GO's free plan allows one webhook for the whole account. Paid plans allow up to ten.

That is an account-wide limit, not a per-domain one, so on a free plan there is only ever one webhook to have. If something else already uses it, another site of yours, or another tool, pressing Set up takes it over and that other thing stops receiving events. Nothing warns you, at either end.

Check Settings → Webhooks before you press the button, and put the old address back when you are finished if you were only testing.

What the API key must be allowed to do

In SMTP2GO, go to Sending → API Keys, open the key, and tick these three on its Permissions tab.

Permission Needed for Endpoints it covers
Emails Sending on the API transport only. Not needed on the SMTP transport. /email/send and the rest of the send group
Webhooks The Set up in SMTP2GO button: reading what is already registered, and creating the webhook. /webhook/view, /webhook/add
Sender Domains Optional. Lets the Health tab read your DKIM selector and custom return path off the account. /domain/view

Leave Statistics, Activity, Suppressions, Templates, SMTP Users and API Keys unticked. Nothing here uses them.

Important

A key missing a permission answers 400, not 403, with SMTP2GO's own sentence in the body. The Set up button prints that sentence and names the permissions it needs.

Fill API Key in even on the SMTP transport. The Set up button and the domain lookup use it.

Configure the transport

The transport is a Grav plugin, so its own settings live in the Grav admin's plugin list. The webhook that reports deliveries back is set up from the Providers card in the KahunaCart admin, in the next section.

  1. 1

    In the Grav admin's plugin list, open Email SMTP2GO and set Transport to API (faster) or SMTP.

  2. 2

    Paste your API key into API Key.

    It begins api-. On the SMTP transport you also need Username, Password, Port and TLS. SMTP users are created in SMTP2GO under Sending → SMTP Users.

  3. 3

    Open Email in the same plugin list and set Mail Engine to SMTP2GO.

Field Default What it does
enabled on The plugin's own switch.
transport api api posts to api.smtp2go.com; smtp connects to mail.smtp2go.com.
api_key empty Sends on the API transport, and sets up delivery reports and reads the domain's DNS on either transport.
username empty SMTP transport only.
password empty SMTP transport only.
port 2525 2525, 587, 25, 8025 or 465.
tls off Implicit TLS. On for 465, off for the others.

There is no verification key field. SMTP2GO does not sign its webhooks; see What protects the address.

Important

SMTP2GO's API transport dropped List-Unsubscribe until version 1.0.1 of this plugin. If Gmail draws no unsubscribe button beside your name, check the version the Health tab reports.

Set the webhook up in one click

  1. 1

    Check Settings → Webhooks in SMTP2GO for a webhook you already have.

    On a free plan there is room for one. If something else is using it, read the warning above before going further.

  2. 2

    Go to KahunaCart → Add-ons → Newsletters → Settings → Providers and click Generate a secret on the SMTP2GO card.

  3. 3

    Click Set up in SMTP2GO.

The button reads your existing webhooks first, then creates one with four things set:

  • the webhook address, with your secret in it;
  • the six events below;
  • the output type set to JSON, because the store cannot read SMTP2GO's default form encoding;
  • X-Grav-Send-Id in the header list, because SMTP2GO only echoes a header named on the webhook itself.

Pressing it twice adds nothing. Nothing is ever deleted.

Do it by hand instead

  1. 1

    In SMTP2GO, go to Settings → Webhooks → Manage Webhooks and click Add Webhook.

  2. 2

    Paste the webhook address from the Providers card into URL, and under Users select the SMTP users, API keys or authenticated IPs this webhook should fire for.

  3. 3

    Set Output type to JSON.

    This one matters more than it looks. Leave it on form encoded and SMTP2GO's dashboard shows a healthy webhook while the store cannot read a word of it.

  4. 4

    Under Email events to include, tick Delivered, Bounce, Spam, Open, Click and Reject.

  5. 5

    In Email headers, add X-Grav-Send-Id, then click Save changes.

    The box takes several entries, separated by pressing Tab. SMTP2GO is the only provider that echoes a header back, and it only echoes one that is named here.

Warning

Leaving Output type on Form encoded fails silently. SMTP2GO's dashboard shows a healthy webhook, the store cannot read the body, and nothing says why.

If you set an Authorization header on the webhook, put the whole value, including the word Bearer or Basic, into providers.smtp2go.auth_header in user/config/plugins/kahunacart-newsletters.yaml. The store checks it in constant time alongside the path secret.

What each event means

SMTP2GO event Becomes Notes
delivered delivered
bounce with bounce: hard hard bounce The address is suppressed and the subscriber is set to bounced.
bounce with anything else soft bounce Three in thirty days are treated as a hard one.
spam complaint The address is suppressed and the subscriber is unsubscribed. SMTP2GO sends no message with it, so the reason reads "marked as spam".
open open Stamped where the store's own pixel has not already.
click click The same.
reject refused message or refused address Decided from the reason. See below.
processed, unsubscribe, resubscribe skipped with a note Answered 200 and logged.

unsubscribe is not acted on. SMTP2GO reports it when somebody uses SMTP2GO's own unsubscribe link, and the store carries its own List-Unsubscribe.

What a reject means

SMTP2GO sends a reject when it refuses to send at all. Its documentation gives three causes: the address has previously hard bounced, complained or unsubscribed; the sender is not verified; or the SMTP user, API key or authenticated IP is set to Sandboxed.

The first is a refused address: the store suppresses it and marks the subscriber bounced. The other two are a refused message: the send is marked bounced and the subscriber is left as they were.

The store reads the event's message to decide. A message naming an unverified sender is the message. One naming the suppression list, a previous bounce, a complaint or an unsubscribe is the address. Anything else is read as the message, because one more refused message costs less than losing a subscriber.

Note

SMTP2GO releases a hard-bounced address from its own reject list after seven days. A suppression this store wrote from an SMTP2GO reject may outlive SMTP2GO's own.

Provider quirks

SMTP2GO only echoes a header you registered on the webhook. Subject and Message-id come back by default; anything else has to be named in the webhook's Email headers box. The Set up button does that for you. If you rename the send header, press Set up again.

On the API transport, the Message-ID you see back is SMTP2GO's, not yours. So on that transport the send header is the correlation that works. On the SMTP transport the whole message goes over the wire and your Message-ID survives.

Nothing is signed. SMTP2GO publishes no signature scheme for its webhooks. The path secret, and the optional Authorization header, protect the address.

SMTP2GO retries a failed post. Up to 35 times over 48 hours, with a ten-second timeout on each attempt.

One event per request. The payload is flat, with no envelope and no batching.

What protects the address

The webhook address carries thirty-six random bytes minted by Generate a secret. A wrong secret answers 404 rather than 401, so a scanner cannot tell a wrong secret from a provider you do not use. SMTP2GO also offers an Authorization header on the webhook and publishes an A record at webhooks.smtp2go.com for allowlisting its own delivery addresses.

DNS for the Health tab

SMTP2GO verifies a sender domain with three CNAMEs, and hands you all three during setup.

Type Host Value What it is for
CNAME em<id>.yourdomain.com return.smtp2go.net The custom return path. This is the envelope sender, which aligns SPF on your domain.
CNAME s<id>._domainkey.yourdomain.com dkim.smtp2go.net The DKIM selector. A CNAME lets SMTP2GO rotate the key without you touching DNS.
CNAME link.yourdomain.com track.smtp2go.net Click and open tracking on your own hostname.

<id> is an SMTP2GO-assigned number for that domain. It is the same number in the em and s records.

Important

Do not add an SPF include: for SMTP2GO. The return-path CNAME above covers SPF, and SMTP2GO's own documentation says not to change your existing SPF record. The Health tab's SPF check follows the return path.

If you need -all at the end of your own SPF record, SMTP2GO gives return-alt.smtp2go.net as the return-path value instead.

DMARC is yours to add. SMTP2GO does not publish it for you. See Health.

With the Sender Domains permission on the key, the Health tab reads the selector and the return path off your account. Without it, put the part before ._domainkey into deliverability.dkim_selector on KahunaCart → Add-ons → Newsletters → Settings → Health.

Checking it actually works

Important

The numbers on a campaign screen are not evidence that SMTP2GO is reporting anything. Opens and clicks are stamped by the store's own tracking pixel and click redirect, and those run whether or not a single webhook has ever arrived. A campaign can read delivered, opened and clicked with the provider silent the whole time.

The signal to trust is the Providers card. If it says nothing has been received, nothing has, whatever the campaign screens show.

Send a one-recipient campaign to an address you can read, open it, press a link, then look at the SMTP2GO card. That is the only check that tells a working webhook apart from a well-drawn screen.

Troubleshooting

Symptom Cause
The webhook looks healthy in SMTP2GO and nothing arrives Output type is on Form encoded. Set it to JSON.
"the body was not a JSON object" The same, or something else is posting to that address.
The Set up button says SMTP2GO refused it, mentioning a permission The key is missing Webhooks. Tick it under Sending → API Keys.
"There is no SMTP2GO API key to set the webhook up with" Paste the key into the Email SMTP2GO plugin first. It is the same key the store sends with.
"SMTP2GO already has a webhook at this address, so nothing was added" You pressed the button twice. Not an error.
Events arrive but nothing joins to a campaign The send header is not on the webhook's header list. Press Set up again, or add X-Grav-Send-Id by hand.
401 from the webhook providers.smtp2go.auth_header is set and does not match what SMTP2GO is sending.
404 from the webhook The path secret does not match. Generate a new one and re-register.
No unsubscribe button in Gmail The API transport before plugin version 1.0.1 dropped List-Unsubscribe.
535 incorrect authentication data Wrong SMTP user credentials.
The Set up button refuses on a free plan The free plan allows one webhook, and you already have one.