# Configure VERP to handle bouncing e-mails

**URL:** https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343
**Category:** Self-Hosting
**Tags:** email, how-to
**Created:** [June 6, 2016, 10:53pm UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343 "2016-06-06T22:53:31Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![Discourse](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/discourse/32/148734_2.png) [@Discourse](https://meta.discourse.org/u/Discourse)
#### Post date: [June 6, 2016, 10:53pm UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/1 "2016-06-06T22:53:32Z")

</div>

## Setting up bounces handling

Discourse uses the [Variable envelope return path (VERP)](https://en.wikipedia.org/wiki/Variable_envelope_return_path) technique to handle bouncing e-mails.

To enable VERP, set the “`reply by email address`” site setting with an email address template that uses the + sign. The default of

`replies+%{reply_key}@discourse.example.com`

… works fine. If you are using your own or your company’s email server, then, that’s it 🎉

Your discourse instance **must** be able to receive email sent to this address. This should work via POP, but we highly recommend [Direct-delivery incoming email for self-hosted sites](https://meta.discourse.org/t/straightforward-direct-delivery-incoming-mail/49487)

If, however, you are using a third party email service, you will need to enable VERP, or activate their **webhooks** as follows:

### MailGun

1. Log in to MailGun and go to [your dashboard](https://app.mailgun.com/app/dashboard); look in the left column for the **Sending** → **Webhooks** page.
2. Select the **Configuration** tab and copy the **HTTP signing key**
3. In _your Discourse site_, set the **Mailgun API key** site setting with your **HTTP signing key**
4. Back in Mailgun, click the **Add webhook** button (selecting **Domain-level** ) and set the **HTTP post URL** to `https://your.discourse/webhooks/mailgun`. Test this.
5. Select both `Permanent Failure` and `Temporary failure`, double check the Domain, and then Create Webhook.

### SendGrid

- Log in to SendGrid and go to [Mail Settings](https://app.sendgrid.com/settings/mail_settings)
- expand the **Event Webhook** setting and enable it if it isn’t already
- click **edit** to set the **HTTP POST URL** to `http://your.discourse/webhooks/sendgrid`
- make sure you selected the following 3 actions: `Dropped`, `Deferred` and `Bounced`
- save your changes by clicking the ✅

### MailJet

- Log in to MailJet and go to [event tracking](https://app.mailjet.com/account/triggers)
- check the **bounce** event
- set the **endpoint URL** to `http://your.discourse/webhooks/mailjet`
- check the ◻ in the **group events** column
- click the save button

### SparkPost

- Login to SparkPost and go to [your dashboard](https://app.sparkpost.com/dashboard).
- Select **Account** from left menu icons
- Select **Webhooks** from menu ( [SparkPost](https://app.sparkpost.com/account/webhooks) )
- Select New Webhook.
- Enter a friendly value for **Webhook Name** e.g. `Discourse Forum`
- Enter a **Target URL** as `http://your.discourse/webhooks/sparkpost`
- Select Add Webhook.

### Amazon Simple Email Service (AWS SES)

- On Discourse:
  - set `reply by email enabled` and `reply by email address` as per the top of OP
  - set `manual polling enabled`

- On AWS:
  - create an SNS Topic
  - create an SNS Subscription for the created Topic as HTTPS pointing to `https://your.discourse/webhooks/aws`
  - go to SES \> Verified Identities, select your site domain, and go to the Notifications tab. Edit your Feedback Notifications. Set the Bounce feedback and Complaint feedback to the SNS Topic you just created

### Postmark

- Login to Postmark and then select the _server_ that is used for sending Discourse emails
- Select the message stream associated with Discourse emails, typically _Default Transactional Stream_
- Click **Webhooks**
- Click **Add webhook**
- Enter **Webhook URL** as `http://your.discourse/webhooks/postmark`
- Under, _Which events should we send?_, check **Delivery** and **Spam complaint**
- Scroll down and click **Save webhook**

## Testing Bounces

To ensure that everything is working, do this:

1. Sign up for a new account on your site with an obviously incorrect email, of the form `bademail@obviously-invalid-domain.com` or `clearly.nobody.has.this.email.address@gmail.com`
2. Wait a while for the emails to fully bounce (check your provider’s logs, if you want – they will usually be shown under the “warn” or “error” log level)
3. Check `/admin/email/bounced` on your site to confirm that the bounce was picked up. Bear in mind this **may take up to 48 hours** depending on how many retries and the particular logic of your email provider.

## Configuring Bounces

Bounces handling can be customized using these site settings

- **soft bounce score** : points added to the user’s “bounce score” when we receive a **temporary** bounce from their email address
- **hard bounce score** : points added to the user’s “bounce score” when we receive a **permanent** (or unknown) bounce from their email address
- **reset bounce score after days** : number of days during which we must receive **no bounce** before we can reset the user’s “bounce score” back to 0
- **bounce score threshold** : score threshold at which point we will stop sending non urgent emails to the user

* * *

_Last Reviewed by @SaraDev on 2022-07-19T20:00:00Z_

> Last edited by @nathank 2026-03-18T23:42:58Z
> 
> > **Check document**
> >
> > Perform check on document:

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [April 29, 2024, 7:51pm UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/197 "2024-04-29T19:51:57Z")

</div>

If someone wants to test this out and confirm that it works, I’ll add it to the OP.

## Create Mailgun webhooks

```plaintext
for event_type in 'permanent_fail' 'temporary_fail'; do
curl -s --user 'api:'=mg_api_key= \
          https://api=mg_region=.mailgun.net/v3/domains/$discourse_hostname/webhooks \
          -F id="$event_type" \
          -F url="https://=discourse_hostname=/webhooks/mailgun"
done

```

---

<div class="post-metadata">

### Author: ![nathank](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nathank/32/290039_2.png) [@nathank](https://meta.discourse.org/u/nathank)
#### Post date: [May 6, 2024, 3:10am UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/198 "2024-05-06T03:10:51Z")

</div>

Updated the Mailgun section as things have changed a wee bit in their UI:

> [@zogstrip](#):
>
> ### MailGun
> 
> 1. Log in to MailGun and go to [your dashboard](https://app.mailgun.com/app/dashboard); look in the left column for the **Sending** → **Webhooks** page.
> 2. Make sure that the correct Domain is selected (top right on desktop)
> 3. In Discourse, set the `mailgun api key` site setting with your **HTTP webhook signing key**
> 4. Click the **Add webhook** button, set the “Event Type” menu to “Permanent Failure”, and set the URL to `https://your.discourse/webhooks/mailgun`
> 5. Repeat the **Add webhook** portion, choosing “Temporary Failure” as the “Event Type”
> - ❗ there is a “Test webhook” section which is useful for testing, but _doesn’t save_ - make sure you use the **Add webhook** button instead

---

<div class="post-metadata">

### Author: ![markersocial](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/markersocial/32/170136_2.png) [@markersocial](https://meta.discourse.org/u/markersocial)
#### Post date: [December 8, 2024, 9:28am UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/199 "2024-12-08T09:28:54Z")

</div>

Is there a simple way to handle email complaints automatically currently using VERP? For the case of users who do not unsubscribe but just mark the email as spam. It’s quite critical to stop emailing people who complain.

---

<div class="post-metadata">

### Author: ![Jagster](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/jagster/32/192154_2.png) [@Jagster](https://meta.discourse.org/u/Jagster)
#### Post date: [December 14, 2024, 1:54pm UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/200 "2024-12-14T13:54:58Z")

</div>

~~Just kind of FYI to everyone with low level skills: SES part is badly outdated, I reckon.~~

Just don’t choose FIFO even it is suggested 🤦‍♂️

---

<div class="post-metadata">

### Author: ![Abdelrahman\_MoHamed](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/abdelrahman_mohamed/32/467712_2.png) [@Abdelrahman\_MoHamed](https://meta.discourse.org/u/Abdelrahman_MoHamed)
#### Post date: [January 11, 2025, 11:34pm UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/201 "2025-01-11T23:34:40Z")

</div>

> [@Discourse](#):
>
> mailgun api key

Hi @pfaffman , thanks for sharing this but quick help please

what if I’m using another email provider rather than the previous list is it still possible?

---

<div class="post-metadata">

### Author: ![Sailor](https://avatars.discourse-cdn.com/v4/letter/s/a587f6/32.png) [@Sailor](https://meta.discourse.org/u/Sailor)
#### Post date: [March 6, 2025, 2:38pm UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/202 "2025-03-06T14:38:11Z")

</div>

In my logs, the endpoint `webhooks/mailjet` produced a warning:

> Received a Mailjet webhook, but no token has been configured. This is unsafe behaviour and will be disallowed in the future.

In `/admin/site_settings/category/email?filter=mailjet` there is the “Mailjet webhook token” field, with no instructions on how to correctly set it up.

I went to [Mailjet](https://app.mailjet.com/account/triggers) and added to the `Endpoint URL` field: [https://discourse.example.org/webhooks/mailjet?t=[your\_token]](https://discourse.example.org/webhooks/mailjet?t=%5Byour_token%5D)

I replaced `[your_token]` with one generated by a [Token Generator](https://it-tools.tech/token-generator), and entered the same value in the “Mailjet webhook token” field at `/admin/site_settings/category/email?filter=mailjet`.

That appears to have eliminated the log warnings.

---

<div class="post-metadata">

### Author: ![markersocial](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/markersocial/32/170136_2.png) [@markersocial](https://meta.discourse.org/u/markersocial)
#### Post date: [April 26, 2025, 10:06am UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/203 "2025-04-26T10:06:33Z")

</div>

> [@markersocial](#):
>
> Is there a simple way to handle email complaints automatically currently using VERP? For the case of users who do not unsubscribe but just mark the email as spam. It’s quite critical to stop emailing people who complain.

Just wanted to note, that I have confirmed that spam complaints for AWS SES are sent from [complaints@email-abuse.amazonses.com](mailto:complaints@email-abuse.amazonses.com) to the ‘Reply by email address’ (in Discourse settings) and are treated as hard bounces by Discourse currently via the standard VERP configuration (without SNS webhooks).

---

<div class="post-metadata">

### Author: ![markersocial](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/markersocial/32/170136_2.png) [@markersocial](https://meta.discourse.org/u/markersocial)
#### Post date: [April 26, 2025, 2:15pm UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/204 "2025-04-26T14:15:40Z")

</div>

Just found this, which might be useful to some using SES also (the ‘ **Using the mailbox simulator** ’ section):

> **[Sending test emails in Amazon SES with the simulator - Amazon Simple Email...](https://docs.aws.amazon.com/ses/latest/dg/send-an-email-from-console.html)**
>
> Send an email to yourself from the Amazon SES console for the easiest way to experiment with sending emails using Amazon SES.

Can use the ‘send a test email’ inside the Discourse admin to send to specific addresses that will simulate things like bounces and complaints without hurting your sending reputation.

e.g.

> [bounce@simulator.amazonses.com](mailto:bounce@simulator.amazonses.com)  
> [complaint@simulator.amazonses.com](mailto:complaint@simulator.amazonses.com)

There are other testing addresses in the link above.

---

<div class="post-metadata">

### Author: ![nathank](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nathank/32/290039_2.png) [@nathank](https://meta.discourse.org/u/nathank)
#### Post date: [March 18, 2026, 11:43pm UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/207 "2026-03-18T23:43:32Z")

</div>

Just updated the Mailgun section as things have changed a wee bit again (for the better!).

---

<div class="post-metadata">

### Author: ![sigmike](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sigmike/32/117797_2.png) [@sigmike](https://meta.discourse.org/u/sigmike)
#### Post date: [July 30, 2026, 9:50pm UTC](https://meta.discourse.org/t/configure-verp-to-handle-bouncing-e-mails/45343/208 "2026-07-30T21:50:55Z")

</div>

I think the AWS SES section should be edited to mention that adding the SNS topic to the `aws_sns_topic_arn_allowlist` parameter is required, as described in [How do I configure aws\_sns\_topic\_arn\_allowlist?](https://meta.discourse.org/t/how-do-i-configure-aws-sns-topic-arn-allowlist/406853)
