Advanced

Double Opt-in

Last updated July 7, 2026

Double opt-in is the practice of asking new sign-ups to confirm their email address by clicking a link in a confirmation email before they actually become a subscriber. It protects you against:

  • People mistyping their email address (“johnn@example.com” instead of “john@โ€ฆ”)
  • Bots filling forms with random addresses
  • Someone signing up someone else’s address as a prank

GDPR / PECR also strongly prefer it as evidence that consent was actually given by the person who owns the address.

Super Speedy Emails supports per-list double opt-in: you configure whether each list requires confirmation. Lists default to requiring confirmation.


Enabling double opt-in on a list

  1. Go to SSE Emails > Lists.
  2. Edit the list.
  3. Check Require email confirmation (double opt-in).
  4. Save.

After this, any new signup to that list lands in pending status. They do not appear in audience queries (campaign sends, newsletter digests, automations) until they confirm.

๐Ÿ’ก The default is on for new lists, because that’s the legally safer default. Turn it off only for operational lists where the signup itself is an explicit informed action (e.g. an internal staff distribution list).


What the user experience looks like

From the visitor’s perspective

  1. Visitor fills out a signup form on your site.
  2. They see a confirmation page: “Almost there! Please check your email for a confirmation link.”
  3. They open the confirmation email titled “Confirm your subscription to
    .
  4. They click the link. They land on a thank-you page: “Thanks โ€” your subscription is confirmed!”
  5. They’re now an active subscriber. They will receive sends to this list.

Behind the scenes

  1. Form submit โ†’ SSE_Subscribers::create() with status = pending, list membership inserted with status = pending.
  2. A confirmation token is generated and stored in sse_confirmation_tokens with a 7-day TTL.
  3. sse_send(category='transactional') sends the confirmation email โ€” never blocked by suppressions (transactional always sends, even to globally suppressed addresses, because we’re confirming the address itself works).
  4. Click on the link hits /wp-json/sse/v1/confirm?token=....
  5. Token consumed โ†’ subscriber status = active, confirmed_at = now. List membership status = subscribed.
  6. Optional redirect to a thank-you URL configured on the list.

Token TTL & expired confirmations

Tokens are valid for 7 days. After that, clicking the link shows an error: “This confirmation link has expired. Please subscribe again.”

The 7-day window is a compromise between:

  • Long enough that someone who saw the email on Monday morning can confirm Tuesday after the weekend (etc.)
  • Short enough that an old leaked link can’t be used to spuriously add an address as confirmed long after the original signup

Expired tokens are not automatically cleaned up โ€” they’re left in the table with a consumed_at status, since rows are tiny and the history is occasionally useful for support.


What happens if they don’t confirm

After 7 days the token expires. The subscriber row stays in pending status indefinitely. You can see them in SSE Emails > Subscribers by filtering for status = pending.

By default we do NOT send a reminder email. Sending an unsolicited reminder to an address that hasn’t yet confirmed they want emails is the kind of thing that creates spam complaints. If you want a “we still haven’t heard from you” reminder, build it as an automation (manual, opt-in per list).

๐Ÿ’ก If you migrated from MailPoet/MailerLite and saw some “unconfirmed” subscribers, they were imported as pending and no re-confirmation email was sent automatically. See Email Migration Guide for the reasoning.


Re-subscribing after declining

If a subscriber has previously unsubscribed, then re-signs up through a form:

  1. The form submit recognises the existing subscriber row.
  2. If the list requires confirmation, a new confirmation token is issued and emailed. Until they click, the list membership remains unsubscribed.
  3. Once they click, the list membership flips to subscribed. Their marketing_opt_in is also flipped back on if they’re re-subscribing to a marketing list.

This treats re-subscribe as “fresh consent” โ€” the previous unsubscribe is on file, the new consent is on file, and you have a clean audit trail.


What appears in the confirmation email

The email is a plain-text message with:

  • Subject: “Confirm your subscription”
  • Body: a one-line message + the confirmation link
  • Sender: configured “From” for the transactional category (see MailGun Setup)

The body is currently fixed; per-list custom confirmation copy is on the roadmap.

The confirmation page (where the link lands) is a minimal HTML page built into SSE. To customise it, override via the existing templates/ directory โ€” see Developer Reference.


Disabling on a list

You can turn off double opt-in for a specific list โ€” useful for operational lists where the signup itself is enough (e.g. an internal alerts list, or a list users join from inside their authenticated account):

  1. Edit the list.
  2. Uncheck Require email confirmation.
  3. Save.

Future signups land directly as active / subscribed. Existing pending subscribers are not retroactively confirmed โ€” they stay pending unless they click their existing confirmation link or the admin manually changes their status.


Audit / compliance

Every confirmation event is recorded:

  • sse_subscribers.confirmed_at โ€” timestamp of confirmation
  • sse_subscribers.source โ€” where the signup originated (form / migration_mailpoet / etc.)
  • sse_confirmation_tokens โ€” the token history with created_at / consumed_at
  • sse_subscriber_lists.subscribed_at โ€” when this specific list membership became active

Together that’s a complete record of “they consented to be on this list at this time via this source.” If a regulator ever asks, the evidence is on file.


Related

Leave a Reply

Your email address will not be published. Required fields are marked *

×
โ–ฒ
โ–ผ
1/1