Skip to main content
Suppressions prevent emails from being sent to addresses that have bounced, complained, or requested removal. Managing suppressions properly is critical for maintaining good deliverability.

Why Suppressions Matter

Sending to invalid or unwilling recipients damages your sender reputation:
  • Hard bounces: Permanent delivery failures (email address doesn’t exist, domain invalid, recipient rejected)
  • Soft bounces: Temporary delivery failures (mailbox full, server temporarily unavailable)
  • Complaints: Recipients who mark your email as spam
  • Unsubscribes: Users who opted out
Email providers track these signals. Too many bounces or complaints can land your emails in spam folders or get your domain blocklisted.

Automatic Suppressions

Ark automatically adds email addresses to your suppression list to protect your sender reputation:
EventActionReason in API
Hard bounceImmediately suppressed on first occurrencehard fail
Soft bounce exhaustedSuppressed after 18 failed retry attempts (~48 hours)too many soft fails
Spam complaintImmediately suppressedcomplaint
Unsubscribe clickImmediately suppressedunsubscribe
Hard bounces trigger immediate suppression. Unlike some email providers that wait for multiple failures, Ark adds recipients to the suppression list on the very first hard bounce. This aggressive approach protects your sender reputation by preventing repeated delivery attempts to invalid addresses.

Viewing Suppressions

List All Suppressions

from ark import Ark

client = Ark()

suppressions = client.suppressions.list()

for s in suppressions.data:
    print(f"{s.email}: {s.reason} (added {s.created_at})")

print(f"Total suppressed: {len(suppressions.data)}")

Filter by Reason

# View only bounces
bounces = client.suppressions.list(reason="hard_bounce")

# View only complaints
complaints = client.suppressions.list(reason="complaint")

Check Specific Email

Before sending, check if an email is suppressed:
import ark

def is_email_suppressed(email):
    try:
        suppression = client.suppressions.retrieve(email)
        return True, suppression.data.reason
    except ark.NotFoundError:
        return False, None

# Usage
suppressed, reason = is_email_suppressed("[email protected]")
if suppressed:
    print(f"Email is suppressed: {reason}")
else:
    # Safe to send
    client.emails.send(...)

Manual Suppression

Add emails manually (e.g., user requested removal):
client.suppressions.create(
    email="[email protected]",
    reason="user_requested"
)

Bulk Add Suppressions

result = client.suppressions.bulk_create(
    suppressions=[
        {"email": "[email protected]", "reason": "hard_bounce"},
        {"email": "[email protected]", "reason": "complaint"},
    ]
)

print(f"Added {result.data.created_count} suppressions")

Removing Suppressions

Use caution. Removing a suppression for a hard-bounced email will likely result in another bounce, harming your reputation.
Only remove suppressions when:
  • The email was incorrectly added
  • A user confirms their email is now valid
  • You’ve verified the issue is resolved
client.suppressions.delete("[email protected]")
print("Removed from suppression list")

Sync with Your Database

Use webhooks to keep your database in sync:
app.post('/webhooks/ark', async (req, res) => {
  const event = req.body;

  switch (event.type) {
    case 'MessageBounced':
      await db.users.update({
        where: { email: event.data.to },
        data: {
          emailValid: false,
          emailInvalidReason: 'bounce',
          bounceType: event.data.bounceType,
        },
      });
      break;

    case 'MessageComplained':
      await db.users.update({
        where: { email: event.data.to },
        data: {
          emailValid: false,
          emailInvalidReason: 'complaint',
          optedOut: true,
        },
      });
      break;
  }

  res.status(200).send('OK');
});

Understanding Bounce Types

Bounces indicate that an email could not be delivered. Understanding the difference between bounce types is crucial for managing your email program effectively.

Hard Bounces (Permanent Failures)

A hard bounce is a permanent delivery failure. The email will never be deliverable to this address. Common causes:
  • Email address doesn’t exist (user unknown, mailbox not found)
  • Domain doesn’t exist or has no mail servers
  • Recipient server permanently rejected the message
  • Email address was disabled or deleted
Ark’s behavior: Immediately adds the recipient to the suppression list on the first hard bounce. No retries are attempted. SMTP codes: Typically 5xx errors (500-599)
{
  "status": "HardFail",
  "details": "550 5.1.1 The email account that you tried to reach does not exist",
  "suppression_added": true,
  "suppression_reason": "hard fail"
}

Soft Bounces (Temporary Failures)

A soft bounce is a temporary delivery failure. The email might be deliverable if retried later. Common causes:
  • Mailbox full (quota exceeded)
  • Server temporarily unavailable
  • Message too large
  • Connection timeout
  • Greylisting (intentional delay by receiving server)
Ark’s behavior:
  1. Retries delivery with exponential backoff
  2. Makes up to 18 retry attempts over approximately 48 hours
  3. If all retries fail, converts to hard fail and adds to suppression list
SMTP codes: Typically 4xx errors (400-499)
{
  "status": "SoftFail",
  "details": "452 4.2.2 Mailbox full",
  "retry_after": "2024-01-15T10:05:00Z",
  "attempts": 3,
  "max_attempts": 18
}

Bounce vs Hard Fail

TermMeaningAutomatic Suppression
HardFailPermanent delivery failure at send time (SMTP 5xx)Yes - reason hard fail
BouncedNDR received after initial acceptanceNo - handle via webhook
SoftFailTemporary failure (SMTP 4xx), will retryNo - retries up to 18 times
Important distinction: Only HardFail status triggers automatic suppression. The Bounced status (from NDR messages) does NOT automatically add to the suppression list. You should handle the MessageBounced webhook and manually suppress via the API if desired.

Suppression Expiration

Suppressions automatically expire after 30 days by default. This allows addresses to become deliverable again if the underlying issue was resolved (e.g., the user recreated their account). You can specify a custom retention period when adding suppressions manually:
# Suppress for 90 days
client.suppressions.create(
    email="[email protected]",
    reason="hard_bounce",
    days=90
)

# Suppress for 365 days
client.suppressions.create(
    email="[email protected]",
    reason="complaint",
    days=365
)

Best Practices

Especially for older email lists, check each address before sending. This prevents wasted API calls and maintains clean metrics.
Hard bounces are permanent failures. Removing them from the suppression list will just cause another bounce, harming your reputation. Only remove if you’ve verified the address is now valid.
If someone marks your email as spam, they don’t want to hear from you. Keep them suppressed and update your application’s user preferences.
Use webhooks to keep your user database updated. Mark email addresses as invalid when they bounce so you don’t need to query suppressions on every send.
Don’t wait for bounces. Periodically remove subscribers who haven’t engaged in 6+ months, and use double opt-in to verify new addresses.
Keep your bounce rate below 2%. Higher rates indicate list quality issues and will harm deliverability.

API Reference

View suppression API documentation