Postilio docs

Suppressions and test mode

The suppression list

Every project has a list of addresses Postilio no longer sends to. Mail to them would bounce again or be marked as spam again, and that hurts the delivery of all your other mail.

An address gets on the list:

ReasonHow
hard_bounceby itself, when a receiving server refuses it for good (a 5xx answer) because the mailbox or domain does not exist or is no longer in use. A block for spam or policy reasons (5.7.x) does not count: that is about reputation, not about the address.
complaintby itself, when the recipient marks a message as spam
manualwhen you add it, in the portal or with the API

Test messages never put an address on the list. Addresses are compared without regard to case.

Sending to a suppressed address

Postilio accepts the message but does not send it. The 202 answer lists the address in suppressed, and its message gets the status suppressed with an event that says why. An address that gets on the list after a message to it was accepted, but before it was sent, is not sent to either.

Manage the list

With the suppressions:manage scope:

curl "https://api.postilio.eu/v1/suppressions?reason=hard_bounce&limit=20" \
  -H "Authorization: Bearer $POSTILIO_KEY"

GET /v1/suppressions lists the newest first. Filter with q (part of an address) and reason; for the next page pass the answer's next as before.

Add an address by hand with POST /v1/suppressions; it gets the reason manual. An address that is on the list already answers 409 with {"error": "address_already_suppressed"}.

curl https://api.postilio.eu/v1/suppressions \
  -H "Authorization: Bearer $POSTILIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "address": "former.customer@example.org" }'

Remove one with DELETE /v1/suppressions/{id}, and Postilio sends to it again. A complaint is only removed with a reason of 10 to 500 characters, which Postilio keeps; without one the answer is 422 with {"error": "reason_required"}. Remove a complaint only when the recipient asked for your mail again.

curl -X DELETE https://api.postilio.eu/v1/suppressions/$SUPPRESSION_ID \
  -H "Authorization: Bearer $POSTILIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "The customer subscribed again on 5 October." }'

Test mode

A message sent with a test key (pk_test_…) goes through every check a live one does (the sender's domain, the key's restrictions, the suppression list) and is stored, but it is never sent. Instead it gets simulated events at once. The recipient decides the outcome:

RecipientOutcome
delivered@simulator.postilio.eudelivered
bounced@simulator.postilio.eubounced: 550 5.1.1, the mailbox does not exist
deferred@simulator.postilio.eudeferred: 451 4.7.1, greylisted
complained@simulator.postilio.eudelivered, then complained
suppressed@simulator.postilio.eusuppressed, as if the address were on the suppression list
any other addressdelivered

A tag after a plus keeps test runs apart and changes nothing: bounced+run-42@simulator.postilio.eu bounces too.

Test messages:

Use a test key in your own tests and in CI. Switching to live is swapping the key.