---
title: "Aliases, routes and groups"
description: "Let a second domain answer for the first, catch whole families of addresses with one pattern, and send the mail of one address to a team."
url: "https://nextmail.sh/docs/knowledge/addresses/address-routing"
area: "Knowledge base"
category: "Domains & addresses"
---

# Aliases, routes and groups

Let a second domain answer for the first, catch whole families of addresses with one pattern, and send the mail of one address to a team.

## How mail finds its way

Every message that arrives for an address on one of your domains is decided in the same order. The first step that knows the address decides, and the rest are not asked.

- When the domain is an alias, the address is read as the same local part on its primary domain, and everything below happens there.
- An address that exists takes the mail, and its own destination applies: its mailbox, its forwards, a webhook or its group members.
- Otherwise the pattern routes of the domain are tried, lowest priority first, and the first one that matches decides.
- Otherwise the catch-all takes the mail when it is on, and the message is turned away when it is off.

> A plus tag never counts. Mail to `sales+march@example.com` is decided as mail to `sales@example.com`, and the tag stays on the message.

## Domain aliases

An alias is a second domain that answers for a first one, its primary. Mail to `ana@example.net` is handled exactly as mail to `ana@example.com`, through the addresses, routes, group addresses and catch-all of the primary, and lands in the same mailbox. `ana@example.net` may also be used as the From address wherever `ana@example.com` may.

Mail sent from `ana@example.net` is treated as mail from `ana@example.com`. It takes the settings, signatures, tracking defaults and display name of that address, and the limits and sending hold of that address count it as their own, so an alias is never a way around them. Only the tracking domain stays the alias domain's: tracked links and the open pixel in that mail use the tracking domain set on `example.net`.

- Both domains belong to the same workspace and are hosted here.
- The primary is not an alias itself, and an alias has no aliases of its own, so there is never a chain to follow.
- An alias holds no addresses created by hand and no routes, because it takes those of its primary. Remove them before the domain becomes an alias, and create new ones on the primary.
- Stopping an alias is immediate: from then on the domain decides its own mail again.

| Refusal | Why |
| --- | --- |
| 409 `alias_not_allowed` | `aliasOf` names the domain itself or no other domain of the workspace, or a route was added on a domain that is an alias. |
| 409 `alias_chain` | The domain named is an alias itself, or other domains are aliases of this one. |
| 409 `alias_has_addresses` | The domain holds addresses created by hand or routes, or an address was created on a domain that is an alias. |

## Pattern routes

A route catches mail to addresses nobody created whose local part matches its pattern. The pattern is the part before the @, from 1 to 64 of the letters a to z, digits, dots, dashes, underscores and plus signs, where `*` stands for any run of characters. A pattern holds at most three wildcards, is compared without case, and is unique on its domain. `support-*` catches `support-eu` and `support-billing`, `*-invoices` catches `march-invoices`, and `*` alone catches every address nobody created.

| Action | What happens to the mail |
| --- | --- |
| `deliver` | It is filed at another address of the workspace, on any of its domains, and that address then applies its own destination, so a group or a forwarding address goes on as it would. |
| `forward` | It is sent on to an address at another provider. That address is first sent an email asking it to confirm, and nothing is forwarded until it does. |
| `webhook` | It is posted to a webhook endpoint of the workspace as the `email.routed` event, with the content and a link to the source, instead of being filed. |
| `rewrite` | It is read as the same local part on another domain of the workspace, and decided there once more. A rewrite there is not followed again. |

Routes are tried by priority, from 0 to 1000 and lowest first, with 100 when none is given. Among routes of the same priority the one with the longest literal text, the pattern without its wildcards, goes first, so `support-eu-*` wins over `support-*`, and among equals the oldest goes first. A domain holds at most 100 routes, and a route can be switched off without deleting it.

| Why a route takes no mail | What to do |
| --- | --- |
| `switched_off` | Switch it back on. |
| `target_removed` | The address it delivered to was removed, or is no longer in the workspace because its domain moved. Point it at another one. |
| `target_disabled` | The address it delivers to is switched off, so the mail it catches is turned away. |
| `forward_pending` | The forwarding destination has not confirmed yet. Saving the route with the same `forwardTo` asks it again. |
| `forward_refused` | The forwarding destination said no to mail from this workspace. |
| `forward_bounced` | Mail forwarded to the destination bounced for good. It takes mail again once the destination confirms again. |
| `webhook_deleted` | The endpoint it posted to was deleted, or stayed behind when the domain moved. Give it another endpoint. |
| `webhook_disabled` | The endpoint it posts to is switched off. |
| `rewrite_domain_removed` | The domain it rewrote to is no longer in the workspace because one of the two domains moved. Point it at another domain. |

> Moving a domain to another workspace takes its routes with it. A route that pointed at an address, a domain or a webhook endpoint left behind loses that target and reads as taking no mail, and so does a route left behind that pointed into the domain, so no mail crosses from one workspace to the other. An alias and its primary are unaliased when one of them moves, and group members that would cross are removed.

> The refusals are 422 `invalid_route_pattern` for a pattern outside the rules, 409 `route_pattern_taken` for a pattern the domain already routes, 422 `route_target_not_found` for an address, endpoint or domain that is not in the workspace, and 422 `route_limit_reached` at 100 routes.

## The route tester

The route tester answers where mail to an address would go, without sending anything. Give it a local part, read on the domain, or a whole address on the domain or one of its aliases.

| Step | What decided |
| --- | --- |
| `address` | An address that exists takes the mail. |
| `alias` | The domain is an alias, and its primary decided. |
| `route` | A pattern route caught it, and the answer names the route. |
| `catch_all` | The catch-all took it. |
| `none` | Nothing takes it, so it would be turned away, and the answer says why. |

The answer also says where the mail would end up: a mailbox, a forward that keeps no copy, a webhook or a group, with the address it is filed at.

## Group addresses

A group address sends every message it receives to its group members. Its destination is `group`, and its group members are addresses of the workspace or addresses at other providers. Group members are not the people who can read the address, the members its access lists, and the two never mix.

| Who may post | What it checks |
| --- | --- |
| `anyone` | Mail from anyone is sent on. This is the default. |
| `members` | The sender has to be a group member and pass DMARC. |
| `workspace` | The sender has to be on one of the domains of the workspace and pass DMARC. |

- A message the posting rule turns away is refused with 5.7.1, so its sender is told.
- A group member of the workspace gets the message through its own destination, so a group inside a group sends it on to its own group members.
- Groups nest at most three deep, a group never contains itself, and each mailbox gets one copy of a message however many groups lead to it.
- Keep a copy files the message in the mailbox of the group address as well.
- A group holds at most 1,000 group members, added up to 100 at a time.

> The refusals are 409 `not_a_group` when the address is not a group address yet, 422 `group_member_limit` past 1,000, 422 `group_nesting_too_deep` for a group three deep or one that would contain itself, and `group_member_not_found` for an address that is not in the workspace or a group member that is not there.

## Outside group members

An address at another provider becomes a group member the same way it becomes a forwarding destination. It is sent an email asking it to confirm that it wants the mail of this workspace, and it receives nothing until it does. Until then it reads `pending`, once it confirms `live`, `refused` when it said no, and `bounced` when its server refused mail passed on to it for good, which stops it until it confirms again. An address hosted in this workspace is added as that address, and one hosted in another workspace on Nextmail cannot be a group member.

- Adding a pending address again asks it once more, at most once every few minutes.
- An address that already confirmed for a forward of the same domain is live at once.
- Removing a group member keeps its confirmation, so adding it back needs no new one.

## Where to manage them

- In the web app, the Routes tab of the domain page holds the Alias section, the routes and the route tester. An address whose Delivers to is A group gets a Group section on its Delivery tab, with Who may send, Keep a copy here and its group members.
- In the phone app, the Routing tab of the domain screen has the alias picker, the routes and the tester, and a group address gets a Group members tab.
- Over REST, `aliasOf` on `PATCH /domains/{id}`, the routes under `/domains/{id}/routes`, the tester at `POST /domains/{id}/routes/test` and the group members under `/domains/{id}/addresses/{addressId}/group-members`. Every domain reports `aliasOf` and `aliases`.
- In the SDKs, `domains.update` with `aliasOf`, `domains.listRoutes`, `createRoute`, `getRoute`, `updateRoute`, `deleteRoute` and `testRoute`, and `domains.listGroupMembers`, `addGroupMembers` and `removeGroupMember`.
- On the command line, `nextmail domains update --alias-of`, `nextmail domains list-routes` and its neighbours, `nextmail domains test-route` and `nextmail domains add-group-members`.
- Over MCP and in the assistant, `setDomainAlias`, `listDomainRoutes`, `getDomainRoute`, `createDomainRoute`, `updateDomainRoute`, `deleteDomainRoute`, `testDomainRoute`, `listGroupMembers`, `addGroupMembers` and `removeGroupMember`. Every one that changes something asks before it runs.

> Creating or changing a route and adding group members decide where mail goes, so an app signed in for a person needs a verification code for them, as it does for forwarding. An API key is never asked for one.

**Terminal**

```
nextmail domains update <domain-id> --alias-of <primary-domain-id>
nextmail domains create-route <domain-id> --pattern 'support-*' --action deliver --target-address-id <address-id>
nextmail domains test-route <domain-id> --address support-eu
nextmail domains add-group-members <domain-id> <group-address-id> --members '[{"addressId":"<address-id>"},{"email":"ops@partner.example"}]'
```

- [SDK methods](https://nextmail.sh/docs/sdk/reference/domains.md): The route, group member and alias methods of `domains`, with every field they take.
- [CLI commands](https://nextmail.sh/docs/cli/reference/domains.md): The `nextmail domains` commands, with every flag.
- [MCP tools](https://nextmail.sh/docs/mcp/tools/domains.md): The domain and address tools an agent can call.
