ZapBounce and Mailgun

Mailgun sells an email validation product alongside its sending, which tells you how much the bounces matter to them.

Its suppression behavior is the operational fact worth planning around: bounced addresses go onto a list and subsequent sends to them are dropped.

Dropped sends look identical to successful ones

When Mailgun drops a message because the address is suppressed, your API call still returns successfully. The drop is recorded in the events log rather than in the response.

So an application that checks the API response sees a send. Only a process reading the events feed knows the difference, and most applications do not.

For a transactional stream that is a real reliability problem: password resets and receipts that silently do not arrive.

How the data moves

  1. Verify at capture, before an address enters the sending stream

    The first bounce is what creates the suppression, and it is avoidable.

  2. Consume the events webhook as well as the API response

    Delivered, bounced and dropped are events. The API response only tells you the request was accepted.

  3. Cross-check the suppression list periodically

    Export it, verify it, and review addresses that come back valid.

  4. Use separate domains for marketing and transactional

    Mailgun suppressions are per domain, so separation contains the damage.

Setting it up

  1. Verify addresses at capture before they reach the sending stream.
  2. Register the Mailgun events webhook and record delivered, bounced and dropped events.
  3. Alert on a dropped event for any transactional message, because that is a silent failure.
  4. Export the suppression list monthly and verify it as a batch.
  5. Review and remove suppressions for addresses that verify as valid.
  6. Separate marketing and transactional onto different Mailgun domains.

Mailgun: common questions

Why did my send succeed but not arrive?

Almost certainly a suppression drop. The API accepted the request and the events log records it as dropped.

Mailgun sells validation. Why use this?

Compare them on the same sample and look at the unresolved count. That difference is what you are choosing between.

Should transactional have its own domain?

Yes. Suppressions are per domain, and a marketing list problem should not silence password resets.

The password reset that returned 200

Say a customer signed up in March with a work address, and one receipt bounced in April while their IT team was migrating mail. Mailgun added the address to the bounces list for your domain. In June the customer asks for a password reset. Your app calls the messages API, gets a 200 with a queued message id, and logs a success. Nothing arrives.

The events feed shows what happened: a failed event with severity permanent and the reason suppress-bounce, which Mailgun's help pages describe as "Not delivering to previously bounced address". Your app never reads that feed, so the customer tries three more times and then writes to support.

Fixing it takes one API call, a DELETE on /v3/yourdomain.com/bounces/ followed by the address. Finding it is the hard part, and that's the argument for alerting on that reason for any transactional message.

Auditing the bounces list without emptying it

You can pull the whole list with a GET on /v3/yourdomain.com/bounces, which pages through every suppressed address along with the original error and the date it was added. Export it monthly and run the addresses as a batch.

Read the results against the age of each entry. An address that bounced last week and verifies as invalid is correctly suppressed, so leave it. One that bounced eight months ago with a mailbox-full or temporary error and now verifies as valid is a candidate for removal, since the original problem has probably passed. Catch-all and unknown results tell you nothing new, so those stay suppressed.

Don't clear the list in bulk. Mailgun suppresses bounced addresses to protect the reputation of the domain you send from, and wiping the list means re-sending to every dead mailbox at once. Remove entries one at a time, and only where a fresh valid result and a real reason (an active customer, a pending reset) both exist. Complaints and unsubscribes sit in separate lists, and a verdict is never a reason to take anyone off those.

Check a Mailgun export today

100 free checks a month, no card. Unknown results and duplicates are never billed.