Skip to content

Postmark error 406: you tried to send to a recipient that has been marked as inactive

A 406 means Postmark deactivated the address after a hard bounce, complaint or manual block. Do not retry it. Surface it, and reactivate only on the owner's request.

Postmark2 min readships at docs/solutions/postmark/inactive-recipient-406.md

Tags: postmark · errors · suppression · bounces · inactive-recipient

A user says "I never got my sign-in link". Your logs show:

422 Unprocessable Entity
ErrorCode: 406
Message: You tried to send to recipient(s) that have been marked as inactive.

What it means

Postmark keeps a suppression list per message stream. An address lands on it after:

  • a hard bounce (the mailbox does not exist),
  • a spam complaint (the person clicked "report spam"),
  • a manual suppression (you, support, or an unsubscribe on a broadcast stream).

After that, Postmark refuses every send to that address on that stream. It does this to protect your reputation. The message was never sent.

What not to do

  • Do not retry. It is a 422. It fails the same way every time.
  • Do not reactivate it to make the error go away. A dead mailbox bounces again. A complainer complains again, and complaints cost more than bounces.
  • Do not switch streams to get around it. Sending a login link on the broadcast stream "because it's not blocked there" puts transactional mail on marketing infrastructure with an unsubscribe footer.

What to do

  1. Turn it into a clear domain error. The Node SDK throws Errors.InactiveRecipientsError for this case. Catch it at the send boundary and throw your own EmailSuppressedError(address).
  2. Show the user something useful. "We can't deliver email to this address. Check it, or use a different one." Not "something went wrong".
  3. Find out why. Search the address in Postmark (Suppressions tab on the stream), or query the API:
const { Suppressions } = await client.getSuppressions("outbound", { emailAddress });
// [{ EmailAddress, SuppressionReason: "HardBounce" | "SpamComplaint" | "ManualSuppression", Origin, CreatedAt }]
  1. Reactivate only on request. If the owner fixed their mailbox and asks, delete the suppression:
await client.deleteSuppressions("outbound", { Suppressions: [{ EmailAddress: emailAddress }] });

SpamComplaint suppressions cannot be deleted through the API. The person reported you, so they have to write to you (or to Postmark support) to undo it.

Refuse before you call

A 406 costs an API round trip and happens after you rendered the email. Keep a local copy of the list, filled by the Bounce, SpamComplaint and SubscriptionChange webhooks, and check it first. Treat the local list as a fast path, not the authority:

  • If the local check fails (database down), let the send through. Postmark still refuses with a 406.
  • If Postmark reactivates an address (a SubscriptionChange with SuppressSending: false), remove it locally too.

Checklist

  • [ ] InactiveRecipientsError is mapped to a domain error, not reported as a crash.
  • [ ] No retry on any 422.
  • [ ] Users see an actionable message.
  • [ ] Reactivation is a support action on request, never automatic.