Operations

Bounces, complaints & suppressions

Send to a bad address → you get a bounce. Recipient hits "Report spam" → you get a complaint. SendBolt parses both, classifies them into actionable buckets, and auto-suppresses the address so you don't shoot yourself in the foot by re-sending.

Bounce categories (W132-G)

Every bounce is classified into one of 8 categories. The category decides whether we permanently suppress the address or just defer the next attempt.

CategoryWhat it meansDefault action
no_such_user5.1.1: mailbox doesn't existPermanent suppression
mailbox_full5.2.2: quota exceededRetry after 24h
policy_block5.7.x: spam policy, blocklist, no PTRPause campaign if >3%
auth_failure5.7.8: SPF/DKIM/DMARC failedInvestigate immediately
dns_failure5.4.x: recipient's MX unreachableRetry with backoff
tls_failureTLS / SSL handshake errorRetry; investigate if persistent
rate_limit4.4.x / 4.7.x / 4.2.1: too fastBackoff; reduce send rate
unknownFallthrough — couldn't classifySuppress conservatively

See your tenant's 30-day breakdown at GET /api/v1/admin/tenants/{id}/bounce-categories. If 80% of your bounces are policy_block, your content is being filtered — see DNS troubleshooting.

Complaint handling

Gmail postmaster, Outlook FBL (Feedback Loop), Yahoo, and AOL all forward "Report spam" clicks to SendBolt as ARF-formatted reports. Every complaint:

  • Adds the complaining address to the suppression list (permanent)
  • Counts toward your tenant's rolling complaint rate

If your tenant exceeds 0.1% complaint rate over 50+ sends, SendBolt auto-pauses outbound for 24h. Recovery is automatic once the rate drops below 0.05% sustained.

Suppression list

The suppression list is the union of:

  • Hard-bounced addresses (no_such_user)
  • Complainers
  • Unsubscribers (one-click unsubscribe)
  • Manual additions (operator entered an address via the UI)
  • Bulk-imported from CSV (W127-G)
  • Domain-scoped entries (e.g. @badcorp.com blocks every recipient at that domain)

Anytime you call /transactional/send, the gate checks suppression FIRST. If hit, the response is {status: "skipped_suppressed"} and the send is dropped silently — no charge, no event, no bounce.

Your code's job

  1. Honour skipped_suppressed — when the API returns that status, mark the user as email_undeliverable = true in your DB. Don't retry.
  2. Don't maintain a parallel suppression list — you'll double-bookkeep and de-sync. Trust SendBolt's gate.
  3. Show "unsubscribed" in your in-app settings — if a user asks why they stopped getting emails, point them at the in-app preferences page where they can re-subscribe (which removes the address from suppression).
  4. Don't re-engage hard-bounced addresses — sending "we miss you" to no_such_user@example.com is the fastest way to tank reputation.

Bulk import (cleaning a known-dirty list)

If you import a list and already know N addresses are bad, dump them into suppression first via CSV import. Stops your warmup curve from being torpedoed by predictable bounces. See /dashboard/suppressions → Import CSV.

Monitoring