Matrix: M30M33
Open in panel — /app/queues
Sending

Bounce Classification

PostMTA classifies every delivery failure as either a hard bounce (permanent) or a soft bounce (temporary). Classification drives suppression decisions, retry scheduling, and alerting thresholds.

Overview

A bounce occurs when a receiving mail server rejects a message during the SMTP delivery attempt. PostMTA intercepts the SMTP response code and maps it to an internal bounce classification before deciding whether to retry.

Sending to known-hard-bounce addresses carries significant deliverability risk. Repeated hard bounces cause your sending domain's reputation to degrade with major mailbox providers. PostMTA suppresses hard bounces automatically after the first occurrence.

Hard Bounces

Hard bounces indicate a permanent delivery failure. PostMTA immediately suppresses the recipient address and stops all future delivery attempts to that address.

SMTP codes that trigger hard bounce

SMTP CodeEnhanced CodeMeaning
5505.1.1User unknown — mailbox does not exist.
5505.1.2Host unknown — destination domain does not exist.
5505.1.6Recipient address has been permanently deleted or disabled.
5505.1.7Invalid sender address format.
5505.1.8Bad sender domain (e.g., unresolvable domain in MAIL FROM).
5535.1.2Mailbox name not allowed (malformed address).
5545.3.0Message too large for recipient (permanent refusal).
5505.7.1Message rejected by receiving server policy (e.g., blocklist).

SMTP response examples

550 5.1.1 User unknown <alice@nonexistent-domain.example.com>
550 5.1.2 Host unknown
550 5.7.1 Message rejected due to policy

Immediate suppression

Upon hard bounce detection, PostMTA:

  1. Adds the recipient address to the workspace suppression list with reason hard_bounce.
  2. Stops all queued delivery attempts to that address.
  3. Fires a message.bounced webhook event.
  4. Increments the workspace hard bounce rate counter.

Soft Bounces

Soft bounces indicate a temporary failure. PostMTA retries the message according to the retry schedule until either the message is delivered or all retry attempts are exhausted.

SMTP codes that trigger soft bounce

SMTP CodeEnhanced CodeMeaningRetryable
4504.1.1Recipient mailbox temporarily unavailable.Yes
4504.1.2Host temporarily unreachable.Yes
4504.2.0Mailbox temporarily full.Yes
4504.3.0Mail system full or out of disk space.Yes
4514.4.1Server busy; try again later.Yes
4514.3.2Server overload — too many connections.Yes
4214.4.2Connection timed out.Yes
4214.4.7Server greeting timeout.Yes

SMTP response examples

450 4.2.0 Mailbox temporarily full for <alice@example.com>
451 4.4.1 Server busy; try again later
421 4.4.2 Connection timed out

Retry Schedule

Soft bounce retry attempts follow an exponential back-off schedule. After all retry attempts are exhausted, the message is marked assoft_bounced and the recipient is evaluated for dampening.

Retry attempt schedule

AttemptDelay after previous failureCumulative timeTotal attempts
15 minutes5 minutesInitial delivery
230 minutes35 minutesRetry 1
32 hours2h 35mRetry 2
48 hours10h 35mRetry 3
524 hours34h 35mRetry 4
6 (final)~34h 35m totalLast attempt

After attempt 6 fails, the message is classified as soft_bounced. The recipient is placed on dampening hold (see below) and the workspace soft bounce counter is incremented.

Enterprise plans can customize the retry schedule. Contact support to configure longer intervals or additional retry attempts for high-touch campaigns.

Bounce Classification Algorithm

PostMTA applies the following decision tree on every SMTP delivery response:

1. Parse SMTP enhanced status code (e.g., 5.1.1, 4.4.1)
2. Map enhanced code to bounce class:
     - Class H1 (hard bounce): enhanced code category 5.1.x, 5.2.x, 5.3.x, 5.7.x
     - Class S1 (soft bounce): enhanced code category 4.1.x, 4.2.x, 4.3.x, 4.4.x, 4.5.x
     - Class E1 (error): unclassifiable — treat as soft bounce, retry once after 5 min
3. If hard bounce:
     a. Suppress recipient immediately.
     b. Fire webhook event "message.bounced".
     c. Stop processing.
4. If soft bounce:
     a. Increment retry counter for this message.
     b. If retry_count < max_retries: re-queue with back-off delay.
     c. If retry_count >= max_retries: mark soft_bounced, apply dampening.
5. If SMTP session error (connection dropped, TLS failure):
     a. Treat as soft bounce.
     b. Retry on next scheduling run (up to 3 session-level retries).

Dampening Controls

Dampening temporarily or permanently suppresses a recipient after excessive soft bounce failures. PostMTA applies dampening at two levels: per-recipient and per-domain.

Per-recipient dampening

After a soft_bounced final state, PostMTA places the recipient on dampening hold for 4 hours by default. During the hold period, all messages to that address are suppressed without triggering a webhook. After the hold expires, PostMTA attempts one delivery. If it fails again, the hold extends to 24 hours, then 7 days.

Per-domain dampening

If more than 10% of messages to a given destination domain produce soft bounces within a 15-minute window, PostMTA applies domain-level dampening for that domain. During domain dampening:

Global dampening controls

Workspace administrators can configure global dampening thresholds and hold durations in the dashboard under Settings → Dampening:

SettingDefaultDescription
Initial dampening hold4 hoursFirst soft bounce hold duration.
Extended hold24 hoursHold after second soft bounce.
Final hold7 daysHold after third consecutive soft bounce.
Domain dampening threshold10%Domain soft bounce rate triggering domain dampening.
Domain dampening duration30 minutesHow long domain dampening lasts.

Bounce Webhook Events

Configure webhook subscriptions for bounce events to build your own suppression list management, alerting, or analytics pipeline.

message.bounced — hard bounce

{
  "event": "message.bounced",
  "timestamp": "2026-07-18T12:10:00Z",
  "data": {
    "message_id": "msg_01HX5K9P7N3M4Q6R8T2V4W6Y8",
    "from": "hello@mail.example.com",
    "to": "alice@nonexistent.example.com",
    "bounce_class": "hard",
    "smtp_code": "550",
    "smtp_enhanced_code": "5.1.1",
    "bounce_reason": "User unknown",
    "suppressed": true
  }
}

message.soft_bounced — final soft bounce

{
  "event": "message.soft_bounced",
  "timestamp": "2026-07-18T22:00:00Z",
  "data": {
    "message_id": "msg_01HX5K9P7N3M4Q6R8T2V4W6Y8",
    "from": "hello@mail.example.com",
    "to": "alice@example.com",
    "bounce_class": "soft",
    "smtp_code": "450",
    "smtp_enhanced_code": "4.2.0",
    "bounce_reason": "Mailbox temporarily full",
    "retry_count": 6,
    "dampening_until": "2026-07-19T02:00:00Z",
    "suppressed": false
  }
}

Bounce Rate Alerting

PostMTA monitors your workspace's bounce rate and fires alerts when thresholds are exceeded. These appear in the dashboard and can be forwarded via webhook or email.

AlertThresholdAction
High hard bounce rate> 3% hard bounces in 1 hourDashboard warning banner + webhook event workspace.high_bounce_rate
Critical hard bounce rate> 8% hard bounces in 1 hourAutomatic sending pause until acknowledged; support notified
Domain dampening activeDomain threshold exceededWebhook event domain.dampened

Next Steps