> For the complete documentation index, see [llms.txt](https://codemash.gitbook.io/codemash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codemash.gitbook.io/codemash/cloud/emails/integrations/providers/mailgun.md).

# Mailgun

Connect Mailgun to Email, and its webhook for bounces, complaints, opens and clicks.

Mailgun sends through your own verified domain and, with its webhook, reports bounces, spam complaints, opens and clicks back into Norbix.

## Get your credentials

1. Open the [Mailgun console](https://app.mailgun.com/) and sign in.
2. **Sending → Domains → Add new domain:** add `mg.acme.com`, create the DNS records Mailgun shows, and wait until the domain is verified. Note its region: **US** or **EU**.
3. **API Security:** copy the **Private API key**.
4. **Sending → Webhooks:** copy the **HTTP webhook signing key**.
5. For opens and clicks, turn on open and click tracking in the domain settings.

## Connect it in Cloud

**Where:** Email → Integrations → **Add New Integration** → Mailgun → **Connect** · `/projects/<project>/emails/integrations/new/mailgun`

| Field                   | Required | What it does                                          | Example                |
| ----------------------- | -------- | ----------------------------------------------------- | ---------------------- |
| Sender Email Address    | yes      | An address on the verified domain.                    | `hello@mg.example.com` |
| Sender Display Name     | no       | The "from" name.                                      | `Acme`                 |
| Sender Domain           | yes      | The verified Mailgun domain.                          | `mg.example.com`       |
| Mailgun Region          | yes      | **US** (default) or **EU** — where the domain lives.  | `EU`                   |
| Mailgun Private API Key | yes      | The private key. Stored encrypted, never shown again. | —                      |
| Webhook Signing Key     | yes      | Checks that webhook calls really come from Mailgun.   | —                      |
| Integration Name        | yes      | The name in Norbix.                                   | `Mailgun (example)`    |

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-c77aa832ffb3a58c5d57ccc9144be2e66eefba3b%2Fmailgun-1.png?alt=media" alt="New Mailgun Integration form filled with made-up values: Sender Email Address, Sender Display Name, Sender Domain mg.acme.example, Mailgun Region US, keys"><figcaption><p>The filled form (made-up values).</p></figcaption></figure>

Press **Save**. The integration opens with its id (`int_EHCfsQqCmMCrhLzxdrX3u`) and badges.

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-58b0cd443795638c3ff4b8e85363673142b46177%2Fmailgun-2.png?alt=media" alt="Editing Mailgun integration: badges DISABLED, NOT TESTED, NOT CONFIRMED; Sender Email Address hello@mg.example.com; Sender Domain mg.example.com"><figcaption><p>After save (this one was just disabled for the <a href="/codemash/cloud/emails/integrations/disable.md">Disable</a> page).</p></figcaption></figure>

### Connect the webhook (bounces, complaints, opens, clicks)

Norbix does not register the webhook for you — paste its URL into Mailgun. The URL is built from your Hub address, your project id and the integration id:

```
https://<your-hub-host>/v3/email/webhooks/mailgun/<projectId>/<integrationId>
```

For an integration saved in another environment than PROD, add the environment: `…/<integrationId>?env=TEST`.

In Mailgun, **Sending → Webhooks → Add webhook**: add this URL for **Permanent failure**, **Spam complaints**, **Opens** and **Clicks**. Do not add **Delivered**, **Unsubscribes** or **Temporary failure**: Norbix accepts them with 200 and changes nothing.

What each event does: a permanent failure or spam complaint blocks marketing to that address; an open sets the message to **Viewed**; a click to **Clicked** (see the [message log](/codemash/cloud/emails/campaigns/log.md)). The webhook only accepts calls signed with this integration's signing key for this exact project and integration.

## Test and set as default

On the saved integration: **Test Email Recipient** → **Test integration** → **I received it** ([Test an integration](/codemash/cloud/emails/integrations/test.md)), then **Actions → Set as default** ([Set as default](/codemash/cloud/emails/integrations/set-default.md)).

## Common errors

| Message                                                              | Cause                                                                                                       | Fix                                                        |
| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| `Property Domain creation failed` (`CM-ERRORS-PROPERTY-002`) on save | **Sender Domain** is not a valid public domain name (a reserved name such as `mg.acme.example` is refused). | Use the domain exactly as Mailgun shows it.                |
| Test failed, unauthorized                                            | Wrong private key, or the wrong **Mailgun Region**.                                                         | Check the key and pick the region of the domain.           |
| Webhook events refused (Mailgun log shows 400)                       | Wrong signing key, or a TEST integration's URL without `?env=TEST`.                                         | Fix the key or the URL; Mailgun retries for about 8 hours. |
| Webhook events refused (406)                                         | A wrong id in the URL, a misspelled environment, or the integration is not Mailgun.                         | Fix the URL; Mailgun stops at once.                        |

## Do it from code

```ts
const { id } = await norbix.hub.notifications.saveEmailIntegration({
  integration: {
    provider: 'MailGun',
    integrationName: 'Mailgun EU',
    isEnabled: true,
    emailAddress: 'hello@mg.example.com',
    emailSenderName: 'Acme',
    domain: 'mg.example.com',
    region: 'Eu', // 'Us' (default) or 'Eu'
    apiKey: process.env.MAILGUN_API_KEY ?? 'made-up-mailgun-key',
    webhookSigningKey: process.env.MAILGUN_SIGNING_KEY ?? 'made-up-signing-key',
  },
});
```

```sh
norbix hub notifications email integration save --integration '{"provider":"MailGun","integrationName":"Mailgun (example)","isEnabled":true,"emailAddress":"hello@mg.example.com","emailSenderName":"Acme","domain":"mg.example.com","apiKey":"made-up-mailgun-key","webhookSigningKey":"made-up-signing-key","region":"Eu"}'
```

API: [Save Email Integration](/codemash/api-reference/notifications/email/save-email-integration.md)
