Unsubscribe and suppression
How recipients opt out of campaign email, what SendSets does when they do, and how the suppression list works.
Every campaign email gives its recipient a way to stop hearing from you, and every opt-out is honoured automatically across the whole workspace. This page covers the three mechanisms, the suppression list behind them, and the settings that shape what a recipient sees.
What a recipient sees
SendSets appends an opt-out to every campaign email, after the signature. There are three modes, set for the workspace under Settings > Sending > Unsubscribe and overridable per campaign under Preferences:
| Mode | What is appended | Default |
|---|---|---|
| Reply to opt out | A plain sentence such as "If this isn't relevant, just reply and let me know and I won't email you again." | Yes |
| Unsubscribe link | A sentence with a real link, for example "Not the right person, or not interested? Unsubscribe" | |
| Nothing | No opt-out in the body |
The wording of the sentence and of the link text is yours to change.
Where it appears
The opt-out line goes last: after the body, after any hand-placed content, and after the mailbox signature.
In an email laid out in HTML, last means inside the email, not under it. A designed message is a column of content centred on the page, and an opt-out appended after that column renders against the left edge of the window, on the page background, with none of the styling the rest of the message carries. SendSets places the line inside the container the email was built in, so it picks up the same width, padding and alignment as the copy above it. A message built as a stack of full-width rows (what a drag-and-drop builder exports) has no single container to sit in, so the line is centred on the same width as the rows instead. The same applies to the mailbox signature.
An email written in the visual composer has no layout of its own, and the line is simply appended to the end of it.
Reply to opt out is the default because it reads as a personal email, which is what cold outreach is. A formal unsubscribe link and footer are the strongest signal a mailbox provider has that a message is bulk marketing, and several deliverability teams report worse placement for cold email that carries one. A reply that asks to stop is detected and honoured automatically (see below), so the plain sentence is a real mechanism, not a courtesy. CAN-SPAM, CASL and the Australian Spam Act all accept a reply as the opt-out method.
Unsubscribe link is the right choice when your list skews toward consumers, when your legal team asks for a link, or when your volume is high enough that provider bulk-sender rules apply. The link is unique to the recipient and campaign, opaque so it cannot be guessed or altered, and valid for a year after the send. Clicking it opens a plain confirmation page with one button. Nothing happens until the button is pressed, because link scanners and preview fetchers follow every link in an email. The page then offers a way back for anyone who unsubscribed by mistake.
The address is short on purpose: https://t.yourdomain.com/unsubscribe/Xk3mP9qR2tLwAb7dEfGhIj. It matters because the plain-text half of an email has nowhere to hide a URL, so this is the one address a recipient can end up reading in full, and a long one there looks like a tracking parameter rather than a way out. Every step of a sequence reuses the same address for the same recipient, so an old email in someone's archive opens the same page as the latest one.
The token carries 128 bits from a cryptographic random source, which is more than a random UUID holds and shorter than one, so it cannot be guessed or walked. It names nobody: there is no contact id, campaign id or address in it, and the page it opens says nothing about who the recipient is or who sent the mail. Opening the link changes nothing on its own, because link scanners and mail-security gateways fetch every URL in a message; only pressing the button does.
Which address the link points at
A mailbox or campaign with a verified custom tracking domain serves its unsubscribe link there, so a recipient reads https://t.yourdomain.com/unsubscribe/... rather than an address on the platform. The campaign's own domain wins over the mailbox's, and only a verified one is used. The page itself is the same page, named after you: it carries no logo, no product name and no scripts, because the email came from your mailbox and not from a platform.
Without a custom domain the link stays on the instance's own API address. Either way it is the sender's infrastructure, not a third party's, and the recipient's opt-out reaches the same suppression list.
Unsubscribe links travel with a workspace export, in the Campaigns group, so moving to another instance does not break a link someone is still holding. Keep serving the tracking domain they were minted on, or they arrive at a host that no longer answers.
You can also place the link inside your own copy instead of the footer: insert the Unsubscribe link variable from the variable menu, or type {{.UnsubscribeLink}}.
Dropped into your copy on its own, the variable becomes a real link in the HTML message, labelled with the same Link text the footer uses ("Unsubscribe" by default). The recipient reads a word, not the address. To choose the wording yourself, select the text first and then pick Unsubscribe link from the variable menu, or press the link button and use the Unsubscribe shortcut next to the address field: the selected text becomes the link and SendSets fills in the address at send time.
Two things follow from that. The plain-text alternative of the message has nowhere to hide a URL, so it carries the address in full when you place the variable on its own, and only your wording when you wrap your own link around it. And click tracking never rewrites the link either way, so an opt-out is never counted as a click.
Plain-text campaigns
A campaign with Plain text only switched on ships no HTML at all, so there is nothing for a link to hide inside: link mode and a hand-placed variable both print the address in the copy. It is short enough to sit on one line and it names the sender's own domain, but it is still a URL in a message that is meant to read as one person writing to another. The composer says so while you are writing and the launch check says it again before you start.
The answer there is the header. It is not visible copy, it works the same on a plain-text send, and it is what Gmail and Yahoo actually look for. Leave Unsubscribe header on, leave the opt-out line as the reply sentence, and the recipient gets a one-click control in their mail client plus a human sentence in the message.
The List-Unsubscribe header
Independently of the body, each campaign can attach the List-Unsubscribe and List-Unsubscribe-Post headers (RFC 8058). Mail clients that recognise them show their own Unsubscribe control next to the sender's name, and pressing it opts the recipient out with no page at all. The toggle is Preferences > Unsubscribe header, on by default.
Two things to know. Gmail only shows its button for mail it already classes as bulk, so a one-to-one style cold email from a Workspace mailbox usually does not get one. And Google and Yahoo require the header only above roughly five thousand messages a day to their consumer inboxes, which no mailbox at SendSets's default limits approaches. The header costs nothing and is worth leaving on; it is not a substitute for the opt-out line.
Replies that ask to stop
SendSets reads every reply to a campaign email. One that asks to stop, in wording such as "unsubscribe", "remove me", "stop emailing me", "opt out" or "do not contact", puts the sender on the suppression list immediately. Only the new text of the reply is read: the quoted history below it carries your own opt-out wording and is ignored. Phrases match on whole words, so "stop by our booth" does not opt anyone out.
A reply that says "not interested" is classed as negative and can stop the sequence, but it does not suppress the contact. Someone who says no today may be a fit next year; someone who says stop is asking not to be contacted at all.
Turn this off with Settings > Sending > Honour replies that ask to stop if you would rather handle such replies by hand. Leaving it off with the reply-to-opt-out line in place means promising an opt-out you then honour manually.
The suppression list
Contacts > Suppression list is every address and domain that no campaign in the workspace will email, however it got there:
| Source | How it got there |
|---|---|
| Unsubscribed | Clicked the link, pressed the mail client's button, or replied asking to stop |
| Spam complaint | The recipient's provider sent a complaint report for a message you sent |
| Bounced | A permanent delivery failure for the address |
| Added by hand | Someone on the team added it |
| Imported | Pasted in as part of a list |
The list is workspace-wide. An entry stops the address in every campaign, in new campaigns created later, and in the unibox composer, which refuses to send to it. Import a list containing a suppressed address and the contact is created but never mailed. The launch check counts suppressed leads out of a campaign's deliverable total, so what the campaign says it will send is what it sends.
Adding entries. Press Add and paste addresses or domains, one per line or as a column from a spreadsheet. A bare domain (acme.com or @acme.com) suppresses every address at it, which is the usual way to keep customers, partners and your own company out of outreach. An optional reason is kept with each entry.
Removing entries. Each entry has a Remove action, and a suppressed contact's drawer shows the same. Removing an entry the recipient made themselves, by unsubscribing, complaining or bouncing, is confirmed with a stronger warning and recorded in the audit log with who lifted it and why the address was listed. Removing an address also restores the contact's Subscribed flag, so the two never disagree.
Contacts and the Subscribed flag. The contact's own Subscribed toggle is a second gate: a contact switched off is skipped by every campaign even with no suppression entry. An opt-out sets both, so a contact who unsubscribed reads as unsubscribed everywhere.
Suppression entries travel with a workspace export, so a workspace moved to another instance does not re-mail people who already opted out.
Webhooks and the API
An opt-out fires the campaign.unsubscribed webhook with a source of one_click (the mail client's button), link (the link in the email), reply (a reply asking to stop) or action (a sequence's Unsubscribe step).
The suppression list is available over the API as GET /suppressions, POST /suppressions and DELETE /suppressions/:id. See deliverability and ops.
Self-hosting
Unsubscribe links are served by the API process on the origin in API_PUBLIC_URL, so that variable must be set to an address recipients can reach. Leaving it unset does not disable the link: the backend falls back to its own listen address, API_HOST, whose default wildcard bind resolves to http://localhost:8080. Every opt-out in every campaign email then points at an address only the backend's own machine can open.
A link minted today is a row in the database, so it survives a secret rotation and travels with a workspace export. Links minted before short tickets existed carry the whole claim inside the token, signed under AUTH_SECRET: those are still honoured, and rotating that secret invalidates the ones still in inboxes.
Nothing in a campaign email points at sendsets.com. The opt-out address, the tracking pixel and every wrapped link are built from your own API_PUBLIC_URL and TRACKING_DOMAIN, and a workspace on your instance that verifies its own tracking domain gets the opt-out on that domain instead. A workspace's verified domain is a CNAME to your TRACKING_DOMAIN, so the tracking service serves the unsubscribe routes as well as the pixel and click tickets: an install running core only has no tracking service, keeps TRACKING_DOMAIN unset, and serves every opt-out from the API address.
One-click (List-Unsubscribe-Post) is attached only when the link is https. An instance reachable over plain HTTP still sends the plain List-Unsubscribe header, because a provider POSTing an opt-out to an http address either refuses it or sends the token in the clear.