> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mailchannels.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Domain Lockdown

> Learn how to set up your DNS record for Domain Lockdown.

## What is Domain Lockdown?

Domain Lockdown is a DNS-based security feature that tells MailChannels which
accounts or sender identities may send email from your domain. MailChannels
blocks mail when the authenticated account or sender identity is not listed in
your DNS record.

For each domain you send from, create a `TXT` record at the `_mailchannels`
subdomain:

```text theme={null}
_mailchannels.example.com TXT v=mc1 auth=examplecorp
```

This record allows the MailChannels account `examplecorp` to send mail from
`example.com`.

### Record format

A Domain Lockdown record is a space-separated list of fields:

```text theme={null}
_mailchannels.example.com TXT v=mc1 auth=examplecorp senderid=examplecorp|x-authsender|billing@example.com sidw=examplecorp|x-authsender|billing*@example.com
```

* `v=mc1` identifies the Domain Lockdown record version. Always include this
  field.
* `auth=` allows a MailChannels account or sub-account ID to send from the domain.
* `senderid=` allows one exact sender ID.
* `sidw=` allows one sender ID pattern with a limited wildcard `*`.

You must include at least one `auth`, `senderid`, or `sidw` field to specify
the authorized account or sender. You may include more than one `auth`,
`senderid`, or `sidw` field in the same record. A message is allowed if any
field matches.

<Warning>
  Domain Lockdown by Cloudflare Worker ID (cfid) is no longer supported as of August 31, 2024.
</Warning>

### Finding your account ID and sender ID

Your MailChannels account ID is shown in the [panel footer](https://dash.mailchannels.com) when you log in.
If your plan supports sub-accounts, sub-account IDs are listed in the [Sub-Account panel](https://dash.mailchannels.com/sub-accounts).

To find a sender ID, check the headers of a message sent through MailChannels:

```text theme={null}
X-MailChannels-SenderId: examplecorp|x-authsender|billing@example.com
X-MailChannels-Auth-Id: examplecorp
Content-Type: text/plain; charset="utf-8"
Date: Mon, 22 Aug 2022 14:15:57 -0500
From: billing@example.com
To: customer@example.net
Subject: Your invoice is ready
```

* Use the `X-MailChannels-Auth-Id` value in an `auth=` field. Note that messages
  sent by a sub-account will show the sub-account ID here, not the parent.
* Use the `X-MailChannels-SenderId` value in a `senderid=` field, or as a
  reference when writing a `sidw=` pattern.

### Choosing a lockdown method

Use `auth` when every sender under a MailChannels account should be allowed to
send from the domain.

```text theme={null}
_mailchannels.example.com TXT v=mc1 auth=examplecorp
```

To authorize a sub-account to also send from the domain:

```text theme={null}
_mailchannels.example.com TXT v=mc1 auth=examplecorp auth=examplecorp_sub
```

This is the simplest setup and works well when a small number of accounts control
all authorized sending for the domain.

Use `senderid` when only specific sender identities should be allowed.

```text theme={null}
_mailchannels.example.com TXT v=mc1 senderid=examplecorp|x-authsender|billing@example.com senderid=examplecorp|x-authsender|alerts@example.com
```

Messages from the same MailChannels account with any other sender ID are blocked
by this record.

Use `sidw` to allow a controlled group of sender IDs without listing every
address individually.

```text theme={null}
_mailchannels.example.com TXT v=mc1 sidw=examplecorp|x-authsender|*.head@example.com
```

This is useful for hosting providers, agencies, or platforms where multiple
customers send through the same MailChannels account and `auth` would be too
broad.

### Sender ID wildcard

The `sidw` field supports one `*` wildcard in the sender part of the sender ID.
The wildcard matches any number of characters.

```text theme={null}
_mailchannels.example.com TXT v=mc1 sidw=examplecorp|x-authsender|billing*@example.com
```

This allows sender IDs such as:

```text theme={null}
examplecorp|x-authsender|billing.no-reply@example.com
examplecorp|x-authsender|billing.alerts@example.com
examplecorp|x-authsender|billing@example.com
```

`sidw` patterns must follow these rules:

* **Format**: exactly three pipe-separated parts:
  `<account>|<sender-type>|<sender>`.
* **Pipe character**: `|` is always a separator. Do not include a literal `|`
  in the sender part; use `*` to match across that portion instead.
* **Constraint**: edge cases such as `<account>|mailer-daemon|<clientip>|NOTNDR` are not supported.
* **Wildcard**: one wildcard is permitted only in the sender part. A standalone
  wildcard, such as `examplecorp|x-authsender|*`, is prohibited.

<Warning>
  Invalid `sidw` patterns are skipped. Use [Testing Your Setup](#testing-your-setup)
  to confirm that your record matches the sender IDs you expect.
</Warning>

#### Escaping in `sidw` patterns

In the sender part of a `sidw` pattern, `*` is a wildcard. To match a literal
asterisk, write `\*`. To match a literal backslash, write `\\`.

For example, this record matches
`examplecorp|x-authsender|*depart\billing@example.com` and
`examplecorp|x-authsender|*depart\alerts@example.com`:

```text theme={null}
_mailchannels.example.com TXT v=mc1 sidw=examplecorp|x-authsender|\*depart\\*@example.com
```

Escaping any other character, such as `\a`, makes the `sidw` pattern invalid.

Some DNS providers process backslashes before publishing the TXT record. After
creating the record, verify the value DNS returns:

```bash theme={null}
resolvectl query --type=TXT _mailchannels.example.com
```

MailChannels evaluates the published TXT value, so adjust your input until DNS
returns the intended record.

### Testing your setup

After publishing the DNS record, confirm the expected TXT value is visible:

Use the [check-domain tool](https://dash.mailchannels.com/domain-health), or use the check-domain API
to verify:

<CodeGroup>
  ```bash cURL theme={null}
  #!/usr/bin/env bash
  # Check that a domain's DKIM, SPF, and Domain Lockdown records are configured
  # correctly and have propagated.
  set -u
  : "${MAILCHANNELS_API_KEY:?Set MAILCHANNELS_API_KEY before running}"
  : "${DOMAIN:?Set DOMAIN (the sending domain, e.g. example.com)}"

  curl -X POST "https://api.mailchannels.net/tx/v1/check-domain" \
    -H "Content-Type: application/json" \
    -H "X-Api-Key: $MAILCHANNELS_API_KEY" \
    -d @- <<JSON
  {
    "domain": "$DOMAIN"
  }
  JSON
  ```

  ```javascript Node.js theme={null}
  import { MailChannels } from "mailchannels-sdk";

  const { MAILCHANNELS_API_KEY, DOMAIN } = process.env;
  if (!MAILCHANNELS_API_KEY) throw new Error("Set MAILCHANNELS_API_KEY before running");
  if (!DOMAIN) throw new Error("Set DOMAIN (the sending domain, e.g. example.com)");

  const mailchannels = new MailChannels(MAILCHANNELS_API_KEY);

  const { data, error } = await mailchannels.domains.check(DOMAIN);

  if (error) {
    console.error("Check domain failed:", error);
    process.exit(1);
  }
  console.log(data);
  ```

  ```python Python theme={null}
  import os
  import sys

  import mailchannels

  if not os.environ.get("MAILCHANNELS_API_KEY"):
      sys.exit("Set MAILCHANNELS_API_KEY before running")

  domain = os.environ.get("DOMAIN")
  if not domain:
      sys.exit("Set DOMAIN (the sending domain, e.g. example.com)")

  # Check that DKIM, SPF, and Domain Lockdown records are configured correctly
  # and have propagated.
  response = mailchannels.CheckDomain.check(domain)

  print(response)
  ```

  ```php PHP theme={null}
  <?php

  require_once __DIR__ . '/vendor/autoload.php';

  use MailChannels\Client;

  $api_key = getenv('MAILCHANNELS_API_KEY') or exit("Error: MAILCHANNELS_API_KEY is not set\n");
  $domain  = getenv('DOMAIN') or exit("Error: DOMAIN is not set\n");

  $client = new Client(apiKey: $api_key);

  // Check that DKIM, SPF, and Domain Lockdown records are configured correctly
  // and have propagated.
  $response = $client->checkDomain->check($domain);

  print_r($response->toArray());
  ```
</CodeGroup>

#### Troubleshooting invalid `sidw` patterns

Use this table for reference when a `sidw` rule is present in DNS but does
not match the sender ID you expect. Invalid `sidw` patterns are skipped
while MailChannels continues evaluating any other fields in the record.

| Invalid pattern                                                     | Why it is skipped                                                                                     |
| ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| <code>sidw=\*\|x-authsender\|sender\*@example.com</code>            | Wildcard `*` is allowed only in the sender part.                                                      |
| <code>sidw=examplecorp\|x-authsender\|\*</code>                     | The wildcard cannot be the entire sender part.                                                        |
| <code>sidw=examplecorp\|x-authsender\|\*sender\*@example.com</code> | More than one wildcard is present.                                                                    |
| <code>sidw=examplecorp\|x-authsender\|sender\|\*@example.com</code> | The extra <code>\|</code> creates a fourth part. `sidw` must have exactly three pipe-separated parts. |
| <code>sidw=examplecorp\|x-authsender\|se\nder\*@example.com</code>  | `\n` is not a valid escape sequence. In the sender part, only `\*` and `\\` are valid escapes.        |

### Best practices

* Start with the narrowest rule that matches your sending model: `auth` for one
  trusted account, `senderid` or `sidw` for shared sending environments.
* Keep records simple and prefer a few clear fields over broad wildcard patterns.
* Review Domain Lockdown records when you add new sending systems, customer
  domains, or sender ID formats.
* Remove old `auth`, `senderid`, and `sidw` fields when they are no longer
  needed.
