---
title: "nextmail.domains"
description: "Every method in this namespace: its signature, its parameters, what it returns and an example."
url: "https://nextmail.sh/docs/python/reference/domains"
area: "Python"
category: "Reference"
---

# nextmail.domains

Every method in this namespace: its signature, its parameters, what it returns and an example.

## Methods

Custom domains attached to the workspace: add and remove them, read the DNS records to publish, check whether they can receive and send, manage their addresses and their photos, and set the catch-all, the tracking and files domains, the DMARC policy, the sender name and the brand logo.

### `domains.list()`

List the workspace's domains and their receiving state

```python
def list(
    *,
    limit: int | None = None,
    cursor: str | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> Page[DomainResource]
```

Returns one page of the domains added to the workspace, alphabetically by domain. `list_all` collects every page and `iterate` walks them lazily. `receiving` reports the inbound checks: `verified` is `True` once `verifiedAt` is set, `catchAll` is the domain's catch all setting, `lastCheckedAt` is the most recent check and `error` is the last verification failure.

`receiving` and `sending` are independent. A verified domain can receive mail, and that says nothing about whether outbound mail from it is signed. `sending['status']` is the signing state as the last check saw it, one of `verified`, `pending`, `failed`, `no_identity` or `unknown`, `sending['canSend']` says whether a send from the domain would be accepted right now, `sending['checkedAt']` dates that verdict, and `sending['error']` carries the last failure. A negative verdict older than a day is treated as unknown rather than as a refusal, so `canSend` can be `True` while `status` is `pending`.

`tracking` reports the domain's custom tracking domain, set with `update`, and only a `tracking['status']` of `active` means tracked links and the open pixel in new mail from the domain use its `host` instead of the default Nextmail host. `storage` reports the domain's custom files domain the same way, and only a `storage['status']` of `active` means the download links for files sent from the domain use its `host`.

Scopes: `domains:read`.

**Parameters**

- `limit` (`int`): Page size, from 1 to 100. The server defaults to 25.
- `cursor` (`str`): The `nextCursor` of the previous page. Leave it out for the first page.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`Page[DomainResource]`, a dict with `items`, `hasMore` and `nextCursor`. Each item has `id`, `domain`, `receiving`, `sending`, `tracking`, `storage`, `logo`, `dmarcPolicy`, `senderName` and `createdAt`.

**Example**

```python
from nextmail import nextmail

page = nextmail.domains.list(limit=50)

for domain in page['items']:
    print(domain['domain'], domain['receiving']['verified'], domain['sending']['canSend'])

if page['hasMore']:
    following = nextmail.domains.list(limit=50, cursor=page['nextCursor'])
    print(len(following['items']), 'more on the next page')
```

**Notes**

- A narrowed key still sees every domain in the workspace, whether it is narrowed by whole domains or by individual addresses.
- Addresses, DNS records and the DMARC reading are only on `get`. `list_addresses` pages through the addresses on one domain.
- The cursor is opaque and holds where the last row sat in this order, so a row deleted or edited between pages never breaks the walk: the next page starts at the first row that sorts after it. A cursor this list did not hand out is a 400 `invalid_cursor`.

Also available in: API [`GET /domains`](https://nextmail.sh/docs/api/reference/domains#get-domains); TypeScript [`nextmail.domains.list()`](https://nextmail.sh/docs/sdk/reference/domains#list); Ruby [`domains.list`](https://nextmail.sh/docs/ruby/reference/domains#list); PHP [`domains->list`](https://nextmail.sh/docs/php/reference/domains#list); Go [`Domains.List`](https://nextmail.sh/docs/go/reference/domains#list); Java [`domains().list`](https://nextmail.sh/docs/java/reference/domains#list); C# [`Domains.ListAsync`](https://nextmail.sh/docs/csharp/reference/domains#list); CLI [`nextmail domains list`](https://nextmail.sh/docs/cli/reference/domains#domains-list).

### `domains.list_all()`

Collect every domain into one list

```python
def list_all(
    *,
    limit: int | None = None,
    cursor: str | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> builtins.list[DomainResource]
```

Walks every page of `list` and returns all the domains as one list, alphabetically by domain. One request per page.

Scopes: `domains:read`.

**Parameters**

- `limit` (`int`): Page size for each request, from 1 to 100. The server defaults to 25.
- `cursor` (`str`): Starts the walk after this cursor instead of the first page.
- `api_key` (`str`): Overrides the client's API key for every page of this walk.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`list[DomainResource]` holding every domain.

**Example**

```python
from nextmail import nextmail

domains = nextmail.domains.list_all(limit=100)
unverified = [domain for domain in domains if not domain['receiving']['verified']]

for domain in unverified:
    print(domain['domain'], domain['receiving']['error'] or 'waiting for DNS')
```

**Notes**

- If any page fails, the call raises and the domains already fetched are discarded.

Also available in: API [`GET /domains`](https://nextmail.sh/docs/api/reference/domains#get-domains); TypeScript [`nextmail.domains.listAll()`](https://nextmail.sh/docs/sdk/reference/domains#listAll); Ruby [`domains.list_all`](https://nextmail.sh/docs/ruby/reference/domains#listAll); PHP [`domains->listAll`](https://nextmail.sh/docs/php/reference/domains#listAll); Go [`Domains.ListAll`](https://nextmail.sh/docs/go/reference/domains#listAll); Java [`domains().listAll`](https://nextmail.sh/docs/java/reference/domains#listAll); C# [`Domains.ListAllAsync`](https://nextmail.sh/docs/csharp/reference/domains#listAll).

### `domains.iterate()`

Stream the domains one at a time

```python
def iterate(
    *,
    limit: int | None = None,
    cursor: str | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> Iterator[DomainResource]
```

Returns a generator that yields the domains one at a time, alphabetically by domain, and requests the next page only once the current one is used up. Nothing is fetched until you start iterating, and breaking out of the loop stops the requests.

Scopes: `domains:read`.

**Parameters**

- `limit` (`int`): Page size for each request, from 1 to 100. The server defaults to 25.
- `cursor` (`str`): Starts the walk after this cursor instead of the first page.
- `api_key` (`str`): Overrides the client's API key for every page of this walk.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`Iterator[DomainResource]`, a generator yielding one domain per step.

**Example**

```python
from nextmail import nextmail

for domain in nextmail.domains.iterate():
    print(domain['domain'], domain['sending']['status'], domain['tracking']['status'])
```

**Notes**

- The generator is lazy, so an abandoned loop costs only the pages you consumed.

Also available in: API [`GET /domains`](https://nextmail.sh/docs/api/reference/domains#get-domains); TypeScript [`nextmail.domains.iterate()`](https://nextmail.sh/docs/sdk/reference/domains#iterate); Ruby [`domains.iterate`](https://nextmail.sh/docs/ruby/reference/domains#iterate); PHP [`domains->iterate`](https://nextmail.sh/docs/php/reference/domains#iterate); Go [`Domains.Iterate`](https://nextmail.sh/docs/go/reference/domains#iterate); Java [`domains().iterate`](https://nextmail.sh/docs/java/reference/domains#iterate); C# [`Domains.IterateAsync`](https://nextmail.sh/docs/csharp/reference/domains#iterate).

### `domains.get()`

Read one domain with its addresses, DNS records and DMARC reading

```python
def get(
    id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainDetailResource
```

Returns the same `receiving` and `sending` blocks as `list`, plus `addresses`: every address on the domain as a full lower cased address with its `enabled` flag. Disabled addresses are listed too. `list_addresses` returns the same addresses with their ids and labels. It also carries the `tracking` and `storage` blocks described on `list`, whose `record` is the CNAME record to add at your DNS provider for the tracking domain and for the files domain.

`records` is every DNS record the domain uses, each with `type`, `name`, `value`, `priority` on an MX record, a `purpose` written to be shown to a person, and `status`: `found` when the last check saw it in public DNS, `missing` when it did not, and `None` when it has not been checked yet. Publish each one exactly as given, since the values are specific to this domain. `dmarc` is the domain's DMARC record as public DNS has it, with its `stage`, any `issues`, and whether a policy stricter than `p=none` is safe yet. It is `None` until the domain is verified.

Reading an unverified domain checks its DNS again when the last check is more than 20 seconds old, so polling `get` is one way to wait for verification. `verify` checks straight away.

The id must belong to the calling workspace. Another workspace's domain id is a 404, the same as an id that does not exist, and the domain name is not accepted in its place.

Scopes: `domains:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list`, a UUID.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainDetailResource`, a `DomainResource` plus `addresses`, each a dict with `address` and `enabled`, `records` as a list of `DomainRecordResource`, and `dmarc` as a `DomainDmarcResource` or `None`.

**Example**

```python
from nextmail import nextmail

domain = nextmail.domains.get('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f')
live = [entry['address'] for entry in domain['addresses'] if entry['enabled']]

print(domain['domain'], domain['receiving']['verified'], live)
```

**Notes**

- `sending['canSend']` is the value to branch on before a send: when it is `False`, `emails.send` from this domain is refused with 409 `domain_not_sendable`.
- A narrowed key still sees every address on the domain, whether it is narrowed by whole domains or by individual addresses.

Also available in: API [`GET /domains/{id}`](https://nextmail.sh/docs/api/reference/domains#get-domains-id); TypeScript [`nextmail.domains.get()`](https://nextmail.sh/docs/sdk/reference/domains#get); Ruby [`domains.get`](https://nextmail.sh/docs/ruby/reference/domains#get); PHP [`domains->get`](https://nextmail.sh/docs/php/reference/domains#get); Go [`Domains.Get`](https://nextmail.sh/docs/go/reference/domains#get); Java [`domains().get`](https://nextmail.sh/docs/java/reference/domains#get); C# [`Domains.GetAsync`](https://nextmail.sh/docs/csharp/reference/domains#get); CLI [`nextmail domains get`](https://nextmail.sh/docs/cli/reference/domains#domains-get).

### `domains.create()`

Add a domain to the workspace

```python
def create(
    body: DomainCreate,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainDetailResource
```

Adds a domain and returns it with every DNS record to publish, in the same shape as `get`. The first DNS check runs during the call, so the `status` of each entry in `records` already says what public DNS answers with.

The domain receives mail once public DNS answers with its MX records and its `_openemail-challenge` TXT record, and it can send once its signing records are in place. Publish every entry in `records` exactly as given, since the values are specific to this domain, then call `verify` or poll `get` until `receiving['verified']` is `True`.

A new domain starts with its catch-all on and no addresses. Create addresses with `create_address`, or turn the catch-all off with `update`.

Scopes: `domains:write`.

**Parameters**

- `body['domain']` (`str`, required): A bare domain such as `example.com`. It is trimmed, lower cased and converted to its ASCII form, so an internationalised name is stored as punycode.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainDetailResource`: the new domain with `addresses` empty, `records` holding every DNS record to publish, and `dmarc` set to `None` until the domain is verified.

**Example**

```python
from nextmail import nextmail

domain = nextmail.domains.create({'domain': 'example.com'})

for record in domain['records']:
    print(record['type'], record['name'], record['value'], record['priority'] or '')
```

**Notes**

- How many domains you can add is set by the plan of the workspace, counted within that workspace. Past it the call is refused with 403 `domain_allowance_reached`, and the message says which plan includes more.
- A domain you already added is 409 `domain_already_added`, one somebody else added is 409 `domain_claimed`, one whose parent or subdomain belongs to somebody else is 409 `related_domain_owned`, and one that belongs to Nextmail is 409 `operator_domain`. Anything that is not a hostname is 422 `invalid_parameter` on `domain`.
- Adding a domain reaches the whole workspace, so a key or app limited to particular addresses or domains is refused with 422 `capability_unsupported` on `domainAllowlist`. Use a key with no address or domain restriction.
- The SDK does not retry a create after a network failure. A second attempt after a lost response is refused with 409 `domain_already_added`, which means the first one worked: read the domain with `list`.

Also available in: API [`POST /domains`](https://nextmail.sh/docs/api/reference/domains#post-domains); TypeScript [`nextmail.domains.create()`](https://nextmail.sh/docs/sdk/reference/domains#create); Ruby [`domains.create`](https://nextmail.sh/docs/ruby/reference/domains#create); PHP [`domains->create`](https://nextmail.sh/docs/php/reference/domains#create); Go [`Domains.Create`](https://nextmail.sh/docs/go/reference/domains#create); Java [`domains().create`](https://nextmail.sh/docs/java/reference/domains#create); C# [`Domains.CreateAsync`](https://nextmail.sh/docs/csharp/reference/domains#create); CLI [`nextmail domains create`](https://nextmail.sh/docs/cli/reference/domains#domains-create).

### `domains.verify()`

Check a domain's DNS now

```python
def verify(
    id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainDetailResource
```

Checks the DNS of the domain straight away and returns it in the same shape as `get`. On an unverified domain it looks for the records that verify it, and `receiving['verified']` comes back `True` when they are found. On a verified domain it checks the signing and return path records again and asks whether mail from the domain can be sent, so `sending` is fresh.

When the last check ran less than 10 seconds ago, nothing new is checked and the domain comes back as it stands, so calling it faster than that gains nothing. A record published a moment ago can take a few minutes to show up in public DNS.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainDetailResource` as the check left it.

**Example**

```python
import time

from nextmail import nextmail

domain = nextmail.domains.verify('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f')

for _ in range(20):
    if domain['receiving']['verified']:
        break
    waiting = [record['name'] for record in domain['records'] if record['status'] != 'found']
    print(domain['receiving']['error'], waiting)
    time.sleep(30)
    domain = nextmail.domains.verify(domain['id'])
```

**Notes**

- Reading an unverified domain with `get` also checks it again when its last check is more than 20 seconds old, so either call works for polling. `verify` needs `domains:write` and `get` needs only `domains:read`.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- A domain id from another workspace is a 404, the same as an id that does not exist.
- Retried automatically on network failure and retryable statuses, since a repeated check changes nothing but the time of the check.

Also available in: API [`POST /domains/{id}/verify`](https://nextmail.sh/docs/api/reference/domains#post-domains-id-verify); TypeScript [`nextmail.domains.verify()`](https://nextmail.sh/docs/sdk/reference/domains#verify); Ruby [`domains.verify`](https://nextmail.sh/docs/ruby/reference/domains#verify); PHP [`domains->verify`](https://nextmail.sh/docs/php/reference/domains#verify); Go [`Domains.Verify`](https://nextmail.sh/docs/go/reference/domains#verify); Java [`domains().verify`](https://nextmail.sh/docs/java/reference/domains#verify); C# [`Domains.VerifyAsync`](https://nextmail.sh/docs/csharp/reference/domains#verify); CLI [`nextmail domains verify`](https://nextmail.sh/docs/cli/reference/domains#domains-verify).

### `domains.update()`

Turn the catch-all on or off, set or remove the tracking and files domains, and set the DMARC policy and the sender name

```python
def update(
    id: str,
    patch: DomainPatch,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainDetailResource
```

`catchAll` set to `True` accepts mail to any address on the domain that nobody created, and the address shows up in `list_addresses` from its first message on. `False` refuses mail to every address that was not created by hand, including the ones the catch-all picked up before. It applies to the whole domain, so only a key that holds the whole domain may change it.

`trackingHost` and `storageHost` set the two custom names a domain can carry once it is verified or its `_openemail-challenge` TXT record is published, each of them a subdomain of it. `trackingHost`, such as `links.example.com`, is the name tracked links and the open pixel use. `storageHost`, such as `files.example.com`, is the name the download links for files sent from the domain use. All five keys are optional and independent: a key left out is left alone, and for either host `None` or an empty string removes that name and a string sets it. A patch carrying none of them changes nothing and answers with the domain as it stands. Each value is trimmed and lower cased, and a leading `https://` or `http://`, any path, query or fragment and any trailing dots are stripped.

A new host is validated, saved and checked in the same call, so the response already carries the result of that first check. `trackingHost` reports into the `tracking` block and `storageHost` into `storage`, and the two blocks carry the same fields. The check asks the host over HTTPS for an answer signed by Nextmail, on `/t/v/<nonce>` for a tracking domain and `/f/v/<nonce>` for a files domain, so the host needs a CNAME record named `record['name']` with the value `record['value']`, with any proxying turned off. That value, also reported as `target`, is an address prepared for this host alone. When it could not be prepared during the call, `record` is `None`, `target` is an empty string and `error` says so, and it is finished within a few minutes without another call. Until a check passes, `status` is `pending` and new mail keeps using the default Nextmail host. Once one passes, `status` is `active` and new mail from the domain uses the host.

Sending a host the domain already has runs the check again, unless the last check was less than 30 seconds ago, in which case the stored state comes back unchanged. A different host replaces the current one at once, so new mail uses the default host until the new one passes a check. `None` or an empty string removes that name, and its block then reports `status` as `none` with `host` and `record` set to `None`.

`dmarcPolicy` is what the domain's DMARC record tells receivers to do with mail that fails its checks: `none` only monitors, `quarantine` sends it to spam and `reject` refuses it. Inboxes show the domain logo only at `quarantine` or `reject`, and where Nextmail writes the DNS for the domain the record is updated during the call, keeping its other tags such as `rua`, while elsewhere you publish the DMARC record `records` lists.

`senderName` is the name recipients see beside every address on the domain that has no name of its own, such as `Acme Support`. Mail sent without a name in `from` goes out under the name of the address, then this one, then the name of the workspace. It is trimmed, and `None` or a string that is empty once trimmed removes it.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list`, a UUID.
- `patch['catchAll']` (`bool`): `True` accepts mail to any address on the domain that nobody created, `False` refuses it. Leaving the key out leaves the catch-all alone.
- `patch['trackingHost']` (`str | None`): A subdomain of the domain of at most 512 characters, such as `links.example.com`. `None` or an empty string removes the tracking domain, and leaving the key out leaves it alone.
- `patch['storageHost']` (`str | None`): A subdomain of the domain of at most 512 characters, such as `files.example.com`. `None` or an empty string removes the files domain, and leaving the key out leaves it alone.
- `patch['dmarcPolicy']` (`DomainDmarcPolicy`): `none`, `quarantine` or `reject`. A policy stricter than `none` needs mail from the domain to be signed first. Leaving the key out leaves the policy alone.
- `patch['senderName']` (`str | None`): The name mail from the domain goes out under when the address has no name of its own, at most 120 characters once trimmed, such as `Acme Support`. `None` or an empty string removes it, and leaving the key out leaves it alone.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainDetailResource`, the same body as `get`, with `receiving['catchAll']`, `tracking`, `storage`, `dmarcPolicy` and `senderName` as they stand after the call.

**Example**

```python
from nextmail import nextmail

domain = nextmail.domains.update(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    {'trackingHost': 'links.example.com', 'storageHost': 'files.example.com'},
)

print(domain['tracking']['status'], domain['tracking']['record'], domain['tracking']['error'])
print(domain['storage']['status'], domain['storage']['record'])
```

**Notes**

- The host is refused with 422 `invalid_tracking_host`, or `invalid_storage_host` for the files domain, when it is not a hostname, is not a strict subdomain of the domain, is the return path host `bounce.<domain>`, belongs to Nextmail or is a domain set up to receive mail. A new host on a domain whose `receiving['verified']` is `False` and whose `_openemail-challenge` TXT record is not published yet gets 409 `domain_not_verified`. The domain does not have to be receiving mail for a host to be accepted. A host another domain already uses gets 409 `tracking_host_in_use` or `storage_host_in_use`, and so does a host already in use for the other feature, since one name cannot be both. A `dmarcPolicy` stricter than `none` while `sending['status']` is not `verified` gets 409 `domain_not_sendable`, since unsigned mail from the domain would then go to spam. Every refusal names the field it came from in the error's `param`, and a refused field changes nothing. The fields are applied in order, `catchAll` first, then `trackingHost`, then `storageHost`, then `dmarcPolicy`, then `senderName`, so a patch carrying more than one can have an earlier change saved before a later field is refused. Send them in separate calls when any of them has to stand on its own.
- Every call on a domain whose tracking domain is managed by a different Nextmail server, removal included, gets 409 `tracking_host_in_use` until it is removed on that server. A files domain behaves the same way under `storage_host_in_use`.
- A tracking domain and a files domain each apply to every address on the domain, so only a key that holds the whole domain may set one. A key whose `domainAllowlist` contains this domain is allowed through, and any other narrowed key gets 422 `capability_unsupported` on `domainAllowlist`. The catch-all, the DMARC policy and the sender name need the whole domain the same way. A body key other than `catchAll`, `trackingHost`, `storageHost`, `dmarcPolicy` and `senderName` is a 422 `unknown_parameter`, and a `catchAll` that is not a `bool`, a `dmarcPolicy` that is not one of the three policies, a `senderName` that is neither a `str` nor `None` or runs past 120 characters once trimmed, or a host key that is present but is neither a `str` nor `None`, or runs past 512 characters, is a 422 `invalid_parameter`. A body carrying none of the keys is not an error: it changes nothing and comes back 200.
- Nextmail keeps checking on its own. A host that has not passed a check yet is checked every 2 minutes in its first hour, every 10 minutes in its first day, hourly in its first week and every 6 hours after that. An active host is checked every 10 minutes, and a failed check on it is retried after 1 minute and then 2. From the third failure in a row the wait starts at 4 minutes and doubles each time, up to an hour.
- An active host that fails one or two checks in a row still reads `active`, with the reason in `error`. It stops being used after the third, or once its last successful check is 2 hours old. New mail then goes back to the default host, and `status` reads `failed` until a check passes again.
- A tracking domain serves only tracking paths and a files domain serves only download paths, and each answers only for mail sent by the workspace that owns it.
- Links in mail already sent keep the host they were sent with, and that covers the download link on a file as much as a tracked link. After removing or changing a name, those links work only for as long as the old CNAME record stays in place. Setting a host up again can give it a different `record['value']`, so publish the one the response reports.
- Retried automatically on network failure and retryable statuses, since repeating a call that already went through finds the catch-all, the DMARC policy, the sender name and the hosts already set, or already removed, and at most checks a host again.

Also available in: API [`PATCH /domains/{id}`](https://nextmail.sh/docs/api/reference/domains#patch-domains-id); TypeScript [`nextmail.domains.update()`](https://nextmail.sh/docs/sdk/reference/domains#update); Ruby [`domains.update`](https://nextmail.sh/docs/ruby/reference/domains#update); PHP [`domains->update`](https://nextmail.sh/docs/php/reference/domains#update); Go [`Domains.Update`](https://nextmail.sh/docs/go/reference/domains#update); Java [`domains().update`](https://nextmail.sh/docs/java/reference/domains#update); C# [`Domains.UpdateAsync`](https://nextmail.sh/docs/csharp/reference/domains#update); CLI [`nextmail domains update`](https://nextmail.sh/docs/cli/reference/domains#domains-update).

### `domains.delete()`

Remove a domain from the workspace

```python
def delete(
    id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DeletedDomainResource
```

Removes the domain. Mail to it stops being accepted and nothing can be sent from it. Every address on it goes with it, their password sign-ins are revoked, its signing key is released, its tracking and files domains are retired, and the `domain.deleted` webhook fires. Mail already received stays in the mailbox.

Where Nextmail wrote the DNS for this domain itself, it takes those records back, and any it could not take back are listed in `leftBehind` for you to remove at your DNS provider. Records you published yourself are never touched, so remove them too once the domain is gone.

There is no undo. Adding the domain again starts it from scratch.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DeletedDomainResource` with `object` set to `'domain'`, `id`, `domain`, `deleted` set to `True`, and `leftBehind`, the DNS records that have to be removed by hand, one line each.

**Example**

```python
from nextmail import nextmail

removed = nextmail.domains.delete('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f')

for line in removed['leftBehind']:
    print('Remove by hand:', line)
```

**Notes**

- The last domain in a workspace cannot be removed here, because in the app removing it deletes the whole mailbox with it. The call is refused with 409 `last_domain`. Remove it in the app, where that is confirmed first.
- A domain that holds reserved account addresses is refused with 409 `domain_holds_reserved_addresses`.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- An access token acting for a member also needs `workspace:manage` in that member's role, as removing one in the app does. It is console-only, so no approval can give it to an app, and without it the call is refused with 403 `insufficient_authority`.
- The SDK does not retry a delete. A 404 on your own second attempt after a lost response means the first one worked.

Also available in: API [`DELETE /domains/{id}`](https://nextmail.sh/docs/api/reference/domains#delete-domains-id); TypeScript [`nextmail.domains.delete()`](https://nextmail.sh/docs/sdk/reference/domains#delete); Ruby [`domains.delete`](https://nextmail.sh/docs/ruby/reference/domains#delete); PHP [`domains->delete`](https://nextmail.sh/docs/php/reference/domains#delete); Go [`Domains.Delete`](https://nextmail.sh/docs/go/reference/domains#delete); Java [`domains().delete`](https://nextmail.sh/docs/java/reference/domains#delete); C# [`Domains.DeleteAsync`](https://nextmail.sh/docs/csharp/reference/domains#delete); CLI [`nextmail domains delete`](https://nextmail.sh/docs/cli/reference/domains#domains-delete).

### `domains.get_logo()`

Read the brand logo of a domain and what public DNS publishes for it

```python
def get_logo(
    id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainLogoStatusResource
```

Returns the logo inboxes show next to mail from the domain through BIMI, with its mark certificate and DMARC policy, and asks public DNS what `default._bimi.<domain>` holds right now: `published['ours']` turns `True` once the record pointing at the logo is live. For a subdomain, `parentDmarc` reports the DMARC record of the domain it belongs to, because inboxes show the logo only when its `p=` and `sp=` both quarantine or reject at 100 percent.

Scopes: `domains:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainLogoStatusResource`: `url`, `record`, `certificate`, `matchesCertificate` and `dmarcPolicy`, plus `published`, a dict with `found`, `ours` and `value`, and `parentDmarc`, which is `None` unless the domain is a subdomain.

**Example**

```python
from nextmail import nextmail

logo = nextmail.domains.get_logo('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f')
parent = logo['parentDmarc']

print(logo['url'], logo['published']['ours'], parent['enforced'] if parent else None)
```

**Notes**

- `get` and `list` carry the same `url`, `record`, `certificate` and `matchesCertificate` in each domain's `logo`, but only `get_logo` asks public DNS what is published.
- A domain id from another workspace is a 404, the same as an id that does not exist.

Also available in: API [`GET /domains/{id}/logo`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-logo); TypeScript [`nextmail.domains.getLogo()`](https://nextmail.sh/docs/sdk/reference/domains#getLogo); Ruby [`domains.get_logo`](https://nextmail.sh/docs/ruby/reference/domains#getLogo); PHP [`domains->getLogo`](https://nextmail.sh/docs/php/reference/domains#getLogo); Go [`Domains.GetLogo`](https://nextmail.sh/docs/go/reference/domains#getLogo); Java [`domains().getLogo`](https://nextmail.sh/docs/java/reference/domains#getLogo); C# [`Domains.GetLogoAsync`](https://nextmail.sh/docs/csharp/reference/domains#getLogo); CLI [`nextmail domains get-logo`](https://nextmail.sh/docs/cli/reference/domains#domains-get-logo).

### `domains.set_logo()`

Upload the brand logo inboxes show for a domain

```python
def set_logo(
    id: str,
    body: DomainLogoSet,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainLogoChangeResource
```

Converts the SVG to the SVG Tiny PS format inboxes require, replaces any logo the domain had, and publishes the BIMI record where Nextmail writes the DNS for the domain. Inboxes show the logo once `dmarcPolicy` is `quarantine` or `reject`, which `update` sets, and Gmail also needs a mark certificate from `set_logo_certificate`.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `body['svg']` (`str`, required): The logo as SVG markup in a `str`, up to 1 MB. A file that is SVG Tiny PS already is kept byte for byte, so it stays the same as the copy inside a mark certificate.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainLogoChangeResource`, the logo as it stands. `records` is `published` once the BIMI record is in place, `manual` when you publish `record` yourself, `blocked` when a record you published is in the way, and `busy` or `failed` when calling again may help.

**Example**

```python
from nextmail import nextmail

svg = (
    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">'
    '<title>Acme</title><rect width="64" height="64" rx="12" fill="#1d4ed8"/></svg>'
)

logo = nextmail.domains.set_logo('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', {'svg': svg})
record = logo['record']

if logo['records'] == 'manual' and record is not None:
    print('Publish', record['type'], record['name'], record['value'])
```

**Notes**

- A domain that is not verified is refused with 409 `domain_not_verified`. An `svg` that is not SVG, is over 1 MB or uses something inboxes do not draw, such as a bitmap image, a filter or a link to another file, is a 422 `invalid_parameter` whose message says which.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`. Safe to replay, so the SDK retries it after a network failure.

Also available in: API [`PUT /domains/{id}/logo`](https://nextmail.sh/docs/api/reference/domains#put-domains-id-logo); TypeScript [`nextmail.domains.setLogo()`](https://nextmail.sh/docs/sdk/reference/domains#setLogo); Ruby [`domains.set_logo`](https://nextmail.sh/docs/ruby/reference/domains#setLogo); PHP [`domains->setLogo`](https://nextmail.sh/docs/php/reference/domains#setLogo); Go [`Domains.SetLogo`](https://nextmail.sh/docs/go/reference/domains#setLogo); Java [`domains().setLogo`](https://nextmail.sh/docs/java/reference/domains#setLogo); C# [`Domains.SetLogoAsync`](https://nextmail.sh/docs/csharp/reference/domains#setLogo); CLI [`nextmail domains set-logo`](https://nextmail.sh/docs/cli/reference/domains#domains-set-logo).

### `domains.remove_logo()`

Remove the brand logo of a domain

```python
def remove_logo(
    id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainLogoChangeResource
```

Removes the logo and deletes the stored file, and takes the BIMI record down where Nextmail writes the DNS for the domain. Elsewhere remove the record yourself. Any mark certificate stays, ready for the next logo.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainLogoChangeResource` with `url` and `record` set to `None`, and `records` saying what happened to the BIMI record.

**Example**

```python
from nextmail import nextmail

logo = nextmail.domains.remove_logo('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f')

print(logo['url'], logo['records'])
```

**Notes**

- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- Removing a logo from a domain that has none changes nothing, so the SDK retries it after a network failure.

Also available in: API [`DELETE /domains/{id}/logo`](https://nextmail.sh/docs/api/reference/domains#delete-domains-id-logo); TypeScript [`nextmail.domains.removeLogo()`](https://nextmail.sh/docs/sdk/reference/domains#removeLogo); Ruby [`domains.remove_logo`](https://nextmail.sh/docs/ruby/reference/domains#removeLogo); PHP [`domains->removeLogo`](https://nextmail.sh/docs/php/reference/domains#removeLogo); Go [`Domains.RemoveLogo`](https://nextmail.sh/docs/go/reference/domains#removeLogo); Java [`domains().removeLogo`](https://nextmail.sh/docs/java/reference/domains#removeLogo); C# [`Domains.RemoveLogoAsync`](https://nextmail.sh/docs/csharp/reference/domains#removeLogo); CLI [`nextmail domains remove-logo`](https://nextmail.sh/docs/cli/reference/domains#domains-remove-logo).

### `domains.set_logo_certificate()`

Upload the mark certificate for a domain logo

```python
def set_logo_certificate(
    id: str,
    body: DomainLogoCertificateSet,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainLogoChangeResource
```

Stores the Verified Mark Certificate (VMC) or Common Mark Certificate (CMC) a certificate authority issued for the domain, replacing any there was, and points the BIMI record at it. Gmail shows the logo only with one and Apple Mail only with a VMC, and when the logo inside the certificate differs from the published one, it becomes the published one and `logoFromCertificate` is `True`.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `body['certificate']` (`str`, required): The file the certificate authority sent as a `str`, up to 128 KB: PEM text as it came, which can hold the whole chain, or a DER or PKCS #7 file encoded as base64, which `to_base64` does for `bytes`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainLogoChangeResource` with `certificate`, a dict with `url`, `mark`, `expiresAt`, `domains` and `issuer`, plus `matchesCertificate`, `records` and `logoFromCertificate`.

**Example**

```python
from nextmail import nextmail

pem = (
    '-----BEGIN CERTIFICATE-----\n'
    'MIIIGDCCBgCgAwIBAgIQC0lDqKvKoTW8AHbyHU0ASTANBgkqhkiG9w0BAQsFADBN\n'
    '-----END CERTIFICATE-----\n'
)

logo = nextmail.domains.set_logo_certificate(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', {'certificate': pem}
)
certificate = logo['certificate']

if certificate is not None:
    print(certificate['mark'], certificate['expiresAt'], logo['logoFromCertificate'])
```

**Notes**

- A domain that is not verified is refused with 409 `domain_not_verified`. A file that cannot be read, is over 128 KB, holds no VMC or CMC, was issued for a different domain or has expired is a 422 `invalid_parameter` on `certificate` whose message says which.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`. Safe to replay, so the SDK retries it after a network failure.

Also available in: API [`PUT /domains/{id}/logo/certificate`](https://nextmail.sh/docs/api/reference/domains#put-domains-id-logo-certificate); TypeScript [`nextmail.domains.setLogoCertificate()`](https://nextmail.sh/docs/sdk/reference/domains#setLogoCertificate); Ruby [`domains.set_logo_certificate`](https://nextmail.sh/docs/ruby/reference/domains#setLogoCertificate); PHP [`domains->setLogoCertificate`](https://nextmail.sh/docs/php/reference/domains#setLogoCertificate); Go [`Domains.SetLogoCertificate`](https://nextmail.sh/docs/go/reference/domains#setLogoCertificate); Java [`domains().setLogoCertificate`](https://nextmail.sh/docs/java/reference/domains#setLogoCertificate); C# [`Domains.SetLogoCertificateAsync`](https://nextmail.sh/docs/csharp/reference/domains#setLogoCertificate); CLI [`nextmail domains set-logo-certificate`](https://nextmail.sh/docs/cli/reference/domains#domains-set-logo-certificate).

### `domains.remove_logo_certificate()`

Remove the mark certificate of a domain logo

```python
def remove_logo_certificate(
    id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainLogoChangeResource
```

Removes the mark certificate and deletes the stored file, while the logo stays. The BIMI record no longer points at a certificate, so Gmail and Apple Mail stop showing the logo.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainLogoChangeResource` with `certificate` and `matchesCertificate` set to `None`.

**Example**

```python
from nextmail import nextmail

logo = nextmail.domains.remove_logo_certificate('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f')

print(logo['url'], logo['certificate'])
```

**Notes**

- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- Removing a certificate from a domain that has none changes nothing, so the SDK retries it after a network failure.

Also available in: API [`DELETE /domains/{id}/logo/certificate`](https://nextmail.sh/docs/api/reference/domains#delete-domains-id-logo-certificate); TypeScript [`nextmail.domains.removeLogoCertificate()`](https://nextmail.sh/docs/sdk/reference/domains#removeLogoCertificate); Ruby [`domains.remove_logo_certificate`](https://nextmail.sh/docs/ruby/reference/domains#removeLogoCertificate); PHP [`domains->removeLogoCertificate`](https://nextmail.sh/docs/php/reference/domains#removeLogoCertificate); Go [`Domains.RemoveLogoCertificate`](https://nextmail.sh/docs/go/reference/domains#removeLogoCertificate); Java [`domains().removeLogoCertificate`](https://nextmail.sh/docs/java/reference/domains#removeLogoCertificate); C# [`Domains.RemoveLogoCertificateAsync`](https://nextmail.sh/docs/csharp/reference/domains#removeLogoCertificate); CLI [`nextmail domains remove-logo-certificate`](https://nextmail.sh/docs/cli/reference/domains#domains-remove-logo-certificate).

### `domains.list_addresses()`

List one page of the addresses on a domain

```python
def list_addresses(
    id: str,
    *,
    limit: int | None = None,
    cursor: str | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> Page[DomainAddressResource]
```

Returns one page of the addresses on the domain, alphabetically by address, with each one's `id`, `label`, `enabled` and `lastReceivedAt`. That covers the addresses created by hand or through the API and the ones the catch-all picked up when mail first arrived for them. Disabled addresses are listed. Removed addresses and the catch-all itself are not: the catch-all is `receiving['catchAll']` on the domain.

`list_all_addresses` collects every page and `iterate_addresses` walks them lazily.

Scopes: `domains:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `limit` (`int`): Page size, from 1 to 100. The server defaults to 25.
- `cursor` (`str`): The `nextCursor` of the previous page. Leave it out for the first page.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`Page[DomainAddressResource]`, a dict with `items`, `hasMore` and `nextCursor`.

**Example**

```python
from nextmail import nextmail

page = nextmail.domains.list_addresses('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', limit=100)

for address in page['items']:
    print(address['address'], address['enabled'], address['label'] or '')
```

**Notes**

- A narrowed key still sees every address on the domain, the same as `get`.
- A domain id from another workspace is a 404, the same as an id that does not exist.
- The cursor is opaque. A cursor this list did not hand out is a 400 `invalid_cursor`.

Also available in: API [`GET /domains/{id}/addresses`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-addresses); TypeScript [`nextmail.domains.listAddresses()`](https://nextmail.sh/docs/sdk/reference/domains#listAddresses); Ruby [`domains.list_addresses`](https://nextmail.sh/docs/ruby/reference/domains#listAddresses); PHP [`domains->listAddresses`](https://nextmail.sh/docs/php/reference/domains#listAddresses); Go [`Domains.ListAddresses`](https://nextmail.sh/docs/go/reference/domains#listAddresses); Java [`domains().listAddresses`](https://nextmail.sh/docs/java/reference/domains#listAddresses); C# [`Domains.ListAddressesAsync`](https://nextmail.sh/docs/csharp/reference/domains#listAddresses); CLI [`nextmail domains list-addresses`](https://nextmail.sh/docs/cli/reference/domains#domains-list-addresses).

### `domains.list_all_addresses()`

Collect every address on a domain into one list

```python
def list_all_addresses(
    id: str,
    *,
    limit: int | None = None,
    cursor: str | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> builtins.list[DomainAddressResource]
```

Walks every page of `list_addresses` and returns all the addresses on the domain as one list, alphabetically by address. One request per page.

Scopes: `domains:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `limit` (`int`): Page size for each request, from 1 to 100. The server defaults to 25.
- `cursor` (`str`): Starts the walk after this cursor instead of the first page.
- `api_key` (`str`): Overrides the client's API key for every page of this walk.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`list[DomainAddressResource]` holding every address on the domain.

**Example**

```python
from nextmail import nextmail

addresses = nextmail.domains.list_all_addresses('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f')
disabled = [address['address'] for address in addresses if not address['enabled']]

print(len(addresses), 'addresses, switched off:', disabled)
```

**Notes**

- If any page fails, the call raises and the addresses already fetched are discarded.

Also available in: API [`GET /domains/{id}/addresses`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-addresses); TypeScript [`nextmail.domains.listAllAddresses()`](https://nextmail.sh/docs/sdk/reference/domains#listAllAddresses); Ruby [`domains.list_all_addresses`](https://nextmail.sh/docs/ruby/reference/domains#listAllAddresses); PHP [`domains->listAllAddresses`](https://nextmail.sh/docs/php/reference/domains#listAllAddresses); Go [`Domains.ListAllAddresses`](https://nextmail.sh/docs/go/reference/domains#listAllAddresses); Java [`domains().listAllAddresses`](https://nextmail.sh/docs/java/reference/domains#listAllAddresses); C# [`Domains.ListAllAddressesAsync`](https://nextmail.sh/docs/csharp/reference/domains#listAllAddresses).

### `domains.iterate_addresses()`

Stream the addresses on a domain one at a time

```python
def iterate_addresses(
    id: str,
    *,
    limit: int | None = None,
    cursor: str | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> Iterator[DomainAddressResource]
```

Returns a generator that yields the addresses on the domain one at a time, alphabetically by address, and requests the next page only once the current one is used up. Nothing is fetched until you start iterating, and breaking out of the loop stops the requests.

Scopes: `domains:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `limit` (`int`): Page size for each request, from 1 to 100. The server defaults to 25.
- `cursor` (`str`): Starts the walk after this cursor instead of the first page.
- `api_key` (`str`): Overrides the client's API key for every page of this walk.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`Iterator[DomainAddressResource]`, a generator yielding one address per step.

**Example**

```python
from nextmail import nextmail

for address in nextmail.domains.iterate_addresses('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f'):
    print(address['address'], address['lastReceivedAt'])
```

**Notes**

- The generator is lazy, so an abandoned loop costs only the pages you consumed.

Also available in: API [`GET /domains/{id}/addresses`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-addresses); TypeScript [`nextmail.domains.iterateAddresses()`](https://nextmail.sh/docs/sdk/reference/domains#iterateAddresses); Ruby [`domains.iterate_addresses`](https://nextmail.sh/docs/ruby/reference/domains#iterateAddresses); PHP [`domains->iterateAddresses`](https://nextmail.sh/docs/php/reference/domains#iterateAddresses); Go [`Domains.IterateAddresses`](https://nextmail.sh/docs/go/reference/domains#iterateAddresses); Java [`domains().iterateAddresses`](https://nextmail.sh/docs/java/reference/domains#iterateAddresses); C# [`Domains.IterateAddressesAsync`](https://nextmail.sh/docs/csharp/reference/domains#iterateAddresses).

### `domains.create_address()`

Create an address on a domain

```python
def create_address(
    id: str,
    body: DomainAddressCreate,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainAddressResource
```

Creates an address on the domain, enabled, and returns it. The domain does not have to be verified yet, but the address receives nothing until it is.

When the domain has its catch-all on, the new address starts with the per-address settings of the catch-all, such as its signature and tracking, apart from the privacy settings. They are copied once, not kept in step.

Creating an address that already exists, or one that was removed, is not an error: it comes back enabled, with the `label` you sent or none, and keeps its id. An address the catch-all picked up becomes one created by hand, so it keeps receiving when the catch-all is turned off.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `body['localPart']` (`str`, required): The part in front of the @, 1 to 64 characters once trimmed, lower cased. Letters, digits, the backtick and ! # $ % & ' * + / = ? ^ _ { | } ~ - are allowed, and so are dots between them. `*` on its own is how the catch-all is written and is refused.
- `body['label']` (`str | None`): A name for the address shown in the app, trimmed, up to 120 characters. Leave it out, or send `None` or an empty string, for none.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainAddressResource` with its `id`, `address`, `label` and `enabled` set to `True`.

**Example**

```python
from nextmail import nextmail

address = nextmail.domains.create_address(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', {'localPart': 'support', 'label': 'Support'}
)

print(address['id'], address['address'])
```

**Notes**

- An address reserved as somebody's account address is refused with 409 `address_reserved` on `localPart`. Past the workspace limit on addresses the call is refused with 422 `workspace_limit_reached`.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- A domain id from another workspace is a 404, the same as an id that does not exist.
- Retried automatically on network failure and retryable statuses, since creating the same address twice leaves one address with the same id.

Also available in: API [`POST /domains/{id}/addresses`](https://nextmail.sh/docs/api/reference/domains#post-domains-id-addresses); TypeScript [`nextmail.domains.createAddress()`](https://nextmail.sh/docs/sdk/reference/domains#createAddress); Ruby [`domains.create_address`](https://nextmail.sh/docs/ruby/reference/domains#createAddress); PHP [`domains->createAddress`](https://nextmail.sh/docs/php/reference/domains#createAddress); Go [`Domains.CreateAddress`](https://nextmail.sh/docs/go/reference/domains#createAddress); Java [`domains().createAddress`](https://nextmail.sh/docs/java/reference/domains#createAddress); C# [`Domains.CreateAddressAsync`](https://nextmail.sh/docs/csharp/reference/domains#createAddress); CLI [`nextmail domains create-address`](https://nextmail.sh/docs/cli/reference/domains#domains-create-address).

### `domains.get_address()`

Read one address on a domain

```python
def get_address(
    id: str,
    address_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainAddressResource
```

Returns one address on the domain with its `label`, `enabled`, `lastReceivedAt` and timestamps.

Scopes: `domains:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainAddressResource`.

**Example**

```python
from nextmail import NextmailApiError, nextmail

try:
    address = nextmail.domains.get_address(
        'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70'
    )
except NextmailApiError as error:
    if error.is_not_found:
        print('No such address on this domain')
    else:
        raise
else:
    print(address['address'], address['enabled'], address['lastReceivedAt'])
```

**Notes**

- An address id that is not on this domain, or an address that was removed, is a 404 `resource_not_found`, and so is a domain from another workspace.

Also available in: API [`GET /domains/{id}/addresses/{addressId}`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-addresses-addressid); TypeScript [`nextmail.domains.getAddress()`](https://nextmail.sh/docs/sdk/reference/domains#getAddress); Ruby [`domains.get_address`](https://nextmail.sh/docs/ruby/reference/domains#getAddress); PHP [`domains->getAddress`](https://nextmail.sh/docs/php/reference/domains#getAddress); Go [`Domains.GetAddress`](https://nextmail.sh/docs/go/reference/domains#getAddress); Java [`domains().getAddress`](https://nextmail.sh/docs/java/reference/domains#getAddress); C# [`Domains.GetAddressAsync`](https://nextmail.sh/docs/csharp/reference/domains#getAddress); CLI [`nextmail domains get-address`](https://nextmail.sh/docs/cli/reference/domains#domains-get-address).

### `domains.update_address()`

Rename an address, turn it off and on, or choose where its mail goes

```python
def update_address(
    id: str,
    address_id: str,
    patch: DomainAddressPatch,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainAddressResource
```

Changes the keys you send and leaves the rest alone. `label` renames the address, and `None` or an empty string removes the name. `enabled` set to `False` stops the address taking mail: mail to it is refused while the sending server is still connected, so the sender gets a bounce, and nothing can be sent from it. It keeps its mail, its settings and the people who can reach it, so `enabled` set to `True` picks up where it left off. That is the difference from `delete_address`.

`destination` chooses where the mail of the address goes: `mailbox` keeps a copy here, as an address does by default, and `forward` only sends it on to the destinations from `add_address_forwards`, keeping nothing here. `forward` needs at least one destination that is switched on.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `patch['label']` (`str | None`): A new name, trimmed, up to 120 characters. `None` or an empty string removes it.
- `patch['enabled']` (`bool`): `False` stops the address taking mail, `True` takes mail again.
- `patch['destination']` (`DomainAddressDestination`): `mailbox` keeps a copy of the mail here, `forward` only forwards it.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainAddressResource` as it stands after the change.

**Example**

```python
from nextmail import nextmail

address = nextmail.domains.update_address(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    {'enabled': False},
)

print(address['address'], address['enabled'])
```

**Notes**

- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- A body key other than `label`, `enabled` and `destination` is a 422 `unknown_parameter`.
- `{'destination': 'forward'}` on an address with no destination switched on is refused with 409 `forward_required` on `destination`.
- Sending `destination` with an OAuth access token needs a verification code, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An access token acting for a member can only change where the mail of an address goes when that member reaches it, or it is refused with 403 `insufficient_authority`. An API key is never asked for a code.
- Retried automatically on network failure and retryable statuses, since the same patch sent twice leaves the same address.

Also available in: API [`PATCH /domains/{id}/addresses/{addressId}`](https://nextmail.sh/docs/api/reference/domains#patch-domains-id-addresses-addressid); TypeScript [`nextmail.domains.updateAddress()`](https://nextmail.sh/docs/sdk/reference/domains#updateAddress); Ruby [`domains.update_address`](https://nextmail.sh/docs/ruby/reference/domains#updateAddress); PHP [`domains->updateAddress`](https://nextmail.sh/docs/php/reference/domains#updateAddress); Go [`Domains.UpdateAddress`](https://nextmail.sh/docs/go/reference/domains#updateAddress); Java [`domains().updateAddress`](https://nextmail.sh/docs/java/reference/domains#updateAddress); C# [`Domains.UpdateAddressAsync`](https://nextmail.sh/docs/csharp/reference/domains#updateAddress); CLI [`nextmail domains update-address`](https://nextmail.sh/docs/cli/reference/domains#domains-update-address).

### `domains.set_address_photo()`

Upload the photo shown for an address

```python
def set_address_photo(
    id: str,
    address_id: str,
    data: RawBody,
    *,
    content_type: ContactPhotoType | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainAddressResource
```

Sends the image bytes as the request body, replacing any photo the address had: PNG, JPEG, WebP or GIF up to 5 MB, cropped to a 512 pixel square, stored as JPEG or PNG and shown for the address in Nextmail in place of the domain logo. Name the type in `content_type=`: without it the bytes go as `application/octet-stream`, which the server refuses with 422 `invalid_image`.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `data` (`RawBody`, required): The image as `bytes`, `bytearray` or `memoryview`.
- `content_type` (`ContactPhotoType`): `image/png`, `image/jpeg`, `image/webp` or `image/gif`, the type of `data`. Leaving it out gets the bytes refused with 422 `invalid_image`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainAddressResource` with the new `photoUrl`.

**Example**

```python
from pathlib import Path

from nextmail import nextmail

address = nextmail.domains.set_address_photo(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    Path('photo.jpg').read_bytes(),
    content_type='image/jpeg',
)

print(address['photoUrl'])
```

**Notes**

- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- A busy image service answers 503 `image_busy` and a failed save 502 `image_not_stored`, which the SDK retries like any other retryable status.

Also available in: API [`PUT /domains/{id}/addresses/{addressId}/photo`](https://nextmail.sh/docs/api/reference/domains#put-domains-id-addresses-addressid-photo); TypeScript [`nextmail.domains.setAddressPhoto()`](https://nextmail.sh/docs/sdk/reference/domains#setAddressPhoto); Ruby [`domains.set_address_photo`](https://nextmail.sh/docs/ruby/reference/domains#setAddressPhoto); PHP [`domains->setAddressPhoto`](https://nextmail.sh/docs/php/reference/domains#setAddressPhoto); Go [`Domains.SetAddressPhoto`](https://nextmail.sh/docs/go/reference/domains#setAddressPhoto); Java [`domains().setAddressPhoto`](https://nextmail.sh/docs/java/reference/domains#setAddressPhoto); C# [`Domains.SetAddressPhotoAsync`](https://nextmail.sh/docs/csharp/reference/domains#setAddressPhoto); CLI [`nextmail domains set-address-photo`](https://nextmail.sh/docs/cli/reference/domains#domains-set-address-photo).

### `domains.remove_address_photo()`

Remove the photo of an address

```python
def remove_address_photo(
    id: str,
    address_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainAddressResource
```

Removes the photo of the address and deletes the stored image, so the domain logo is shown for it again.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainAddressResource` with `photoUrl` set to `None`.

**Example**

```python
from nextmail import nextmail

address = nextmail.domains.remove_address_photo(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70'
)

print(address['address'], address['photoUrl'])
```

**Notes**

- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- Removing a photo from an address that has none changes nothing, so the SDK retries it after a network failure.

Also available in: API [`DELETE /domains/{id}/addresses/{addressId}/photo`](https://nextmail.sh/docs/api/reference/domains#delete-domains-id-addresses-addressid-photo); TypeScript [`nextmail.domains.removeAddressPhoto()`](https://nextmail.sh/docs/sdk/reference/domains#removeAddressPhoto); Ruby [`domains.remove_address_photo`](https://nextmail.sh/docs/ruby/reference/domains#removeAddressPhoto); PHP [`domains->removeAddressPhoto`](https://nextmail.sh/docs/php/reference/domains#removeAddressPhoto); Go [`Domains.RemoveAddressPhoto`](https://nextmail.sh/docs/go/reference/domains#removeAddressPhoto); Java [`domains().removeAddressPhoto`](https://nextmail.sh/docs/java/reference/domains#removeAddressPhoto); C# [`Domains.RemoveAddressPhotoAsync`](https://nextmail.sh/docs/csharp/reference/domains#removeAddressPhoto); CLI [`nextmail domains remove-address-photo`](https://nextmail.sh/docs/cli/reference/domains#domains-remove-address-photo).

### `domains.delete_address()`

Remove an address from a domain

```python
def delete_address(
    id: str,
    address_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DeletedDomainAddressResource
```

Removes the address. Mail to it is refused from then on, even when the catch-all on the domain is on. Its forwarding stops, its settings are deleted, the people who were given access to it lose that access, and its password sign-in is revoked. Mail it already received stays in the mailbox.

Creating the same address again with `create_address` brings it back with the same id, enabled, but without its old settings or access.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DeletedDomainAddressResource` with `object` set to `'address'`, `id`, `address` and `deleted` set to `True`.

**Example**

```python
from nextmail import nextmail

removed = nextmail.domains.delete_address(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70'
)

print(removed['address'], removed['deleted'])
```

**Notes**

- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- An access token acting for a member also needs `workspace:manage` in that member's role, as removing one in the app does. It is console-only, so no approval can give it to an app, and without it the call is refused with 403 `insufficient_authority`.
- The SDK does not retry a delete. A 404 on your own second attempt after a lost response means the first one worked.

Also available in: API [`DELETE /domains/{id}/addresses/{addressId}`](https://nextmail.sh/docs/api/reference/domains#delete-domains-id-addresses-addressid); TypeScript [`nextmail.domains.deleteAddress()`](https://nextmail.sh/docs/sdk/reference/domains#deleteAddress); Ruby [`domains.delete_address`](https://nextmail.sh/docs/ruby/reference/domains#deleteAddress); PHP [`domains->deleteAddress`](https://nextmail.sh/docs/php/reference/domains#deleteAddress); Go [`Domains.DeleteAddress`](https://nextmail.sh/docs/go/reference/domains#deleteAddress); Java [`domains().deleteAddress`](https://nextmail.sh/docs/java/reference/domains#deleteAddress); C# [`Domains.DeleteAddressAsync`](https://nextmail.sh/docs/csharp/reference/domains#deleteAddress); CLI [`nextmail domains delete-address`](https://nextmail.sh/docs/cli/reference/domains#domains-delete-address).

### `domains.list_address_forwards()`

List where the mail of an address is forwarded

```python
def list_address_forwards(
    id: str,
    address_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> AddressForwardListResource
```

Returns every place the mail of the address is forwarded to, oldest first, as the Forwarding section of the address in the app lists them. Each destination says whether it is switched on (`enabled`) and where it stands (`status`): only a `live` destination, one that confirmed by email that it wants this mail, receives anything.

`destination` on the list says whether the address also keeps a copy of its mail here (`mailbox`) or only forwards it (`forward`), and `max` is how many destinations one address may have.

Scopes: `domains:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`AddressForwardListResource`: `address`, `destination`, `max` and the destinations in `data`.

**Example**

```python
from nextmail import nextmail

forwards = nextmail.domains.list_address_forwards(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70'
)

print(forwards['address'], forwards['destination'])

for forward in forwards['data']:
    print(forward['email'], forward['status'], forward['enabled'])
```

**Notes**

- An address id that is not on this domain, or an address that was removed, is a 404 `resource_not_found`, and so is a domain from another workspace.
- A GET is retried automatically on network failure and on 408, 500, 502, 503 and 504 responses, up to the client's `max_retries`, and on a 429 only when it carries a `Retry-After` of a minute or less.

Also available in: API [`GET /domains/{id}/addresses/{addressId}/forwards`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-addresses-addressid-forwards); TypeScript [`nextmail.domains.listAddressForwards()`](https://nextmail.sh/docs/sdk/reference/domains#listAddressForwards); Ruby [`domains.list_address_forwards`](https://nextmail.sh/docs/ruby/reference/domains#listAddressForwards); PHP [`domains->listAddressForwards`](https://nextmail.sh/docs/php/reference/domains#listAddressForwards); Go [`Domains.ListAddressForwards`](https://nextmail.sh/docs/go/reference/domains#listAddressForwards); Java [`domains().listAddressForwards`](https://nextmail.sh/docs/java/reference/domains#listAddressForwards); C# [`Domains.ListAddressForwardsAsync`](https://nextmail.sh/docs/csharp/reference/domains#listAddressForwards); CLI [`nextmail domains list-address-forwards`](https://nextmail.sh/docs/cli/reference/domains#domains-list-address-forwards).

### `domains.add_address_forwards()`

Forward the mail of an address to more places

```python
def add_address_forwards(
    id: str,
    address_id: str,
    body: AddressForwardsAdd,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> AddressForwardsAddedResource
```

Adds places the mail of the address goes to, as adding a destination in the app does. Each new destination is sent an email asking it to confirm, and receives nothing until it does, so it comes back `pending` and turns `live` once its owner confirms.

An address hosted here, one already on the list, one that would make a loop, one past the limit of 10 and one that refused mail from this workspace before are not added. Each is named in `skipped` with the reason, and the rest are still added.

The address keeps a copy of its mail here as before. To stop keeping one, set `destination` to `forward` with `update_address` once a destination is switched on.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `body['emails']` (`list[str]`, required): The addresses to forward to, 1 to 10 of them. Each is trimmed and lowercased.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`AddressForwardsAddedResource`: the destinations added in `added`, and every address that was not, with the reason, in `skipped`.

**Example**

```python
from nextmail import nextmail

result = nextmail.domains.add_address_forwards(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    {'emails': ['ops@partner.example', 'ada@example.com']},
)

for forward in result['added']:
    print('Asked to confirm:', forward['email'], forward['status'])

for skipped in result['skipped']:
    print('Not added:', skipped['email'], skipped['reason'])
```

**Notes**

- An address that is switched off is refused with 409 `address_disabled`. Switch it on with `update_address` first.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`. An access token acting for a member can only change the forwarding of an address that member reaches, or it is refused with 403 `insufficient_authority`.
- An OAuth access token needs a verification code for this call, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An API key is never asked for a code.
- Not retried automatically by the SDK, since a lost attempt may already have asked a destination to confirm.

Also available in: API [`POST /domains/{id}/addresses/{addressId}/forwards`](https://nextmail.sh/docs/api/reference/domains#post-domains-id-addresses-addressid-forwards); TypeScript [`nextmail.domains.addAddressForwards()`](https://nextmail.sh/docs/sdk/reference/domains#addAddressForwards); Ruby [`domains.add_address_forwards`](https://nextmail.sh/docs/ruby/reference/domains#addAddressForwards); PHP [`domains->addAddressForwards`](https://nextmail.sh/docs/php/reference/domains#addAddressForwards); Go [`Domains.AddAddressForwards`](https://nextmail.sh/docs/go/reference/domains#addAddressForwards); Java [`domains().addAddressForwards`](https://nextmail.sh/docs/java/reference/domains#addAddressForwards); C# [`Domains.AddAddressForwardsAsync`](https://nextmail.sh/docs/csharp/reference/domains#addAddressForwards); CLI [`nextmail domains add-address-forwards`](https://nextmail.sh/docs/cli/reference/domains#domains-add-address-forwards).

### `domains.update_address_forward()`

Pause a forwarding destination or switch it back on

```python
def update_address_forward(
    id: str,
    address_id: str,
    forward_id: str,
    patch: AddressForwardPatch,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> AddressForwardChangeResource
```

`enabled` set to `False` pauses the destination: nothing is forwarded to it until it is switched on again. It keeps its confirmation, so switching it back on needs no new one, and switching it on clears the failures recorded against it.

When the last destination that is on is paused, the address goes back to keeping its mail here. `destination` in the result says where the mail of the address goes now.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `forward_id` (`str`, required): A destination id from `list_address_forwards` or `add_address_forwards`. It has to be a destination of the address named by `address_id`.
- `patch['enabled']` (`bool`, required): `False` pauses the destination, `True` switches it back on.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`AddressForwardChangeResource`: the destination as it is now, with `destination` for the address.

**Example**

```python
from nextmail import nextmail

forward = nextmail.domains.update_address_forward(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    '5e8f1a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b',
    {'enabled': False},
)

print(forward['status'], forward['destination'])
```

**Notes**

- A destination id that is not on this address is a 404 `resource_not_found`.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`. An access token acting for a member can only change the forwarding of an address that member reaches, or it is refused with 403 `insufficient_authority`.
- An OAuth access token needs a verification code for this call, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An API key is never asked for a code.
- Retried automatically on network failure, since the same patch sent twice leaves the same destination.

Also available in: API [`PATCH /domains/{id}/addresses/{addressId}/forwards/{forwardId}`](https://nextmail.sh/docs/api/reference/domains#patch-domains-id-addresses-addressid-forwards-forwardid); TypeScript [`nextmail.domains.updateAddressForward()`](https://nextmail.sh/docs/sdk/reference/domains#updateAddressForward); Ruby [`domains.update_address_forward`](https://nextmail.sh/docs/ruby/reference/domains#updateAddressForward); PHP [`domains->updateAddressForward`](https://nextmail.sh/docs/php/reference/domains#updateAddressForward); Go [`Domains.UpdateAddressForward`](https://nextmail.sh/docs/go/reference/domains#updateAddressForward); Java [`domains().updateAddressForward`](https://nextmail.sh/docs/java/reference/domains#updateAddressForward); C# [`Domains.UpdateAddressForwardAsync`](https://nextmail.sh/docs/csharp/reference/domains#updateAddressForward); CLI [`nextmail domains update-address-forward`](https://nextmail.sh/docs/cli/reference/domains#domains-update-address-forward).

### `domains.delete_address_forward()`

Stop forwarding to a destination

```python
def delete_address_forward(
    id: str,
    address_id: str,
    forward_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DeletedAddressForwardResource
```

Removes the destination, so nothing more is forwarded to it. When it was the last destination that was on, the address goes back to keeping its mail here, and `destination` in the result says where the mail of the address goes now.

To stop forwarding for a while instead, pause the destination with `update_address_forward`, which keeps its confirmation.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `forward_id` (`str`, required): A destination id from `list_address_forwards` or `add_address_forwards`. It has to be a destination of the address named by `address_id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DeletedAddressForwardResource` with `object` set to `'address_forward'`, `id`, `addressId`, `email`, `deleted` set to `True`, and `destination`.

**Example**

```python
from nextmail import nextmail

removed = nextmail.domains.delete_address_forward(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    '5e8f1a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b',
)

print(removed['email'], removed['destination'])
```

**Notes**

- A destination id that is not on this address is a 404 `resource_not_found`.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`. An access token acting for a member can only change the forwarding of an address that member reaches, or it is refused with 403 `insufficient_authority`.
- An OAuth access token needs a verification code for this call, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An API key is never asked for a code.
- Not retried by the SDK. Repeating a delete that succeeded is a 404.

Also available in: API [`DELETE /domains/{id}/addresses/{addressId}/forwards/{forwardId}`](https://nextmail.sh/docs/api/reference/domains#delete-domains-id-addresses-addressid-forwards-forwardid); TypeScript [`nextmail.domains.deleteAddressForward()`](https://nextmail.sh/docs/sdk/reference/domains#deleteAddressForward); Ruby [`domains.delete_address_forward`](https://nextmail.sh/docs/ruby/reference/domains#deleteAddressForward); PHP [`domains->deleteAddressForward`](https://nextmail.sh/docs/php/reference/domains#deleteAddressForward); Go [`Domains.DeleteAddressForward`](https://nextmail.sh/docs/go/reference/domains#deleteAddressForward); Java [`domains().deleteAddressForward`](https://nextmail.sh/docs/java/reference/domains#deleteAddressForward); C# [`Domains.DeleteAddressForwardAsync`](https://nextmail.sh/docs/csharp/reference/domains#deleteAddressForward); CLI [`nextmail domains delete-address-forward`](https://nextmail.sh/docs/cli/reference/domains#domains-delete-address-forward).

### `domains.resend_address_forward_consent()`

Ask a forwarding destination to confirm again

```python
def resend_address_forward_consent(
    id: str,
    address_id: str,
    forward_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> AddressForwardConsentResource
```

Sends the confirmation email to the destination once more, for when the first one was lost or ignored. `status` says what became of the request: `sent`, `already-confirmed` when the destination has confirmed and needs nothing, `too-soon` when the last email went out moments ago, `revoked` when the destination refused mail from this workspace, and `send-failed` when the email could not be sent.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `forward_id` (`str`, required): A destination id from `list_address_forwards` or `add_address_forwards`. It has to be a destination of the address named by `address_id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`AddressForwardConsentResource` with the `status` of the request.

**Example**

```python
from nextmail import nextmail

asked = nextmail.domains.resend_address_forward_consent(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    '5e8f1a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b',
)

if asked['status'] == 'too-soon':
    print('Wait a moment before asking again.')
else:
    print(asked['email'], asked['status'])
```

**Notes**

- A destination id that is not on this address is a 404 `resource_not_found`.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`. An access token acting for a member can only change the forwarding of an address that member reaches, or it is refused with 403 `insufficient_authority`.
- An OAuth access token needs a verification code for this call, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An API key is never asked for a code.
- Not retried automatically by the SDK, since every attempt can send an email.

Also available in: API [`POST /domains/{id}/addresses/{addressId}/forwards/{forwardId}/resend`](https://nextmail.sh/docs/api/reference/domains#post-domains-id-addresses-addressid-forwards-forwardid-resend); TypeScript [`nextmail.domains.resendAddressForwardConsent()`](https://nextmail.sh/docs/sdk/reference/domains#resendAddressForwardConsent); Ruby [`domains.resend_address_forward_consent`](https://nextmail.sh/docs/ruby/reference/domains#resendAddressForwardConsent); PHP [`domains->resendAddressForwardConsent`](https://nextmail.sh/docs/php/reference/domains#resendAddressForwardConsent); Go [`Domains.ResendAddressForwardConsent`](https://nextmail.sh/docs/go/reference/domains#resendAddressForwardConsent); Java [`domains().resendAddressForwardConsent`](https://nextmail.sh/docs/java/reference/domains#resendAddressForwardConsent); C# [`Domains.ResendAddressForwardConsentAsync`](https://nextmail.sh/docs/csharp/reference/domains#resendAddressForwardConsent); CLI [`nextmail domains resend-address-forward-consent`](https://nextmail.sh/docs/cli/reference/domains#domains-resend-address-forward-consent).

### `domains.list_address_members()`

List who can reach an address

```python
def list_address_members(
    id: str,
    address_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> AddressMemberListResource
```

Returns everybody who can read the mail of the address and how each one reaches it, in `via`: `owner` for the owner of the workspace, `every-address` for a role that reaches every address, `whole-domain` for a grant of the whole domain named in `viaDomain`, and `direct` for a grant of the address itself. Each person appears once.

`access` is `member` for somebody who reads and sends from the address and `viewer` for somebody who only reads it. `removable` is `True` for a grant of the address itself, which `members.revoke_address` takes back. The others come from the role or a domain grant, and change there.

Scopes: `members:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`AddressMemberListResource`, with the people in `data`.

**Example**

```python
from nextmail import nextmail

reach = nextmail.domains.list_address_members(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70'
)

for person in reach['data']:
    print(person['email'], person['access'], person['via'])
```

**Notes**

- An address id that is not on this domain, or an address that was removed, is a 404 `resource_not_found`, and so is a domain from another workspace.
- A GET is retried automatically on network failure and on 408, 500, 502, 503 and 504 responses, up to the client's `max_retries`, and on a 429 only when it carries a `Retry-After` of a minute or less.

Also available in: API [`GET /domains/{id}/addresses/{addressId}/members`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-addresses-addressid-members); TypeScript [`nextmail.domains.listAddressMembers()`](https://nextmail.sh/docs/sdk/reference/domains#listAddressMembers); Ruby [`domains.list_address_members`](https://nextmail.sh/docs/ruby/reference/domains#listAddressMembers); PHP [`domains->listAddressMembers`](https://nextmail.sh/docs/php/reference/domains#listAddressMembers); Go [`Domains.ListAddressMembers`](https://nextmail.sh/docs/go/reference/domains#listAddressMembers); Java [`domains().listAddressMembers`](https://nextmail.sh/docs/java/reference/domains#listAddressMembers); C# [`Domains.ListAddressMembersAsync`](https://nextmail.sh/docs/csharp/reference/domains#listAddressMembers); CLI [`nextmail domains list-address-members`](https://nextmail.sh/docs/cli/reference/domains#domains-list-address-members).

### `domains.get_address_login()`

Read the password sign-in of an address

```python
def get_address_login(
    id: str,
    address_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> AddressLoginResource
```

Says whether the address has a password of its own, which lets somebody sign in to Nextmail as that address alone and read and send only its mail. `login` is `None` when it has none, and otherwise says who set the password and when, and when it was last used to sign in.

Scopes: `members:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`AddressLoginResource`, with `login` set to `None` when the address has no password.

**Example**

```python
from nextmail import nextmail

login = nextmail.domains.get_address_login(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70'
)['login']

print(login['lastSignedInAt'] if login else 'no password')
```

**Notes**

- It needs `members:write`, the scope that sets a password, as the app does, rather than a read scope.
- An address id that is not on this domain, or an address that was removed, is a 404 `resource_not_found`, and so is a domain from another workspace.
- A key limited to particular addresses or domains is refused with 422 `capability_unsupported`. An access token acting for a member can only reach the sign-in of an address that member reaches, or it is refused with 403 `insufficient_authority`.
- A GET is retried automatically on network failure and on 408, 500, 502, 503 and 504 responses, up to the client's `max_retries`, and on a 429 only when it carries a `Retry-After` of a minute or less.

Also available in: API [`GET /domains/{id}/addresses/{addressId}/login`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-addresses-addressid-login); TypeScript [`nextmail.domains.getAddressLogin()`](https://nextmail.sh/docs/sdk/reference/domains#getAddressLogin); Ruby [`domains.get_address_login`](https://nextmail.sh/docs/ruby/reference/domains#getAddressLogin); PHP [`domains->getAddressLogin`](https://nextmail.sh/docs/php/reference/domains#getAddressLogin); Go [`Domains.GetAddressLogin`](https://nextmail.sh/docs/go/reference/domains#getAddressLogin); Java [`domains().getAddressLogin`](https://nextmail.sh/docs/java/reference/domains#getAddressLogin); C# [`Domains.GetAddressLoginAsync`](https://nextmail.sh/docs/csharp/reference/domains#getAddressLogin); CLI [`nextmail domains get-address-login`](https://nextmail.sh/docs/cli/reference/domains#domains-get-address-login).

### `domains.set_address_login()`

Give an address a password, or replace it

```python
def set_address_login(
    id: str,
    address_id: str,
    body: AddressLoginSet,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> AddressLoginResource
```

Sets the password somebody uses to sign in to Nextmail as this address alone. Whoever holds it reads and sends only the mail of the address and reaches nothing else in the workspace. Nextmail sends the password to nobody, so hand it over yourself.

Calling it again replaces the password, signs out everybody who signed in with the old one and removes the forwarding destinations they added. `created` says whether the sign-in is new.

Scopes: `members:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `body['password']` (`str`, required): At least 8 characters, with a lowercase letter, an uppercase letter, a number and a special character.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`AddressLoginResource` as it stands after the change, with `created`.

**Example**

```python
import os

from nextmail import nextmail

result = nextmail.domains.set_address_login(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    {'password': os.environ.get('SUPPORT_INBOX_PASSWORD', '')},
)

print('Sign-in created' if result.get('created') else 'Password replaced')
```

**Notes**

- A password that misses a rule is a 422 `invalid_parameter` on `password`. An address that an account on Nextmail already signs in as is refused with 409 `account_exists`, so invite that account to the workspace instead, and an address that is switched off is refused with 409 `address_unavailable`.
- The first password on a workspace whose plan has no team access is refused with 403 `plan_required`.
- A key or an access token has to hold every scope a sign-in for one address may use, or it is refused with 403 `insufficient_authority`. A key limited to particular addresses or domains is refused with 422 `capability_unsupported`, and an access token acting for a member can only set the password of an address that member reaches with `member` access.
- An OAuth access token needs a verification code for this call, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An API key is never asked for a code.
- Not retried automatically by the SDK.

Also available in: API [`PUT /domains/{id}/addresses/{addressId}/login`](https://nextmail.sh/docs/api/reference/domains#put-domains-id-addresses-addressid-login); TypeScript [`nextmail.domains.setAddressLogin()`](https://nextmail.sh/docs/sdk/reference/domains#setAddressLogin); Ruby [`domains.set_address_login`](https://nextmail.sh/docs/ruby/reference/domains#setAddressLogin); PHP [`domains->setAddressLogin`](https://nextmail.sh/docs/php/reference/domains#setAddressLogin); Go [`Domains.SetAddressLogin`](https://nextmail.sh/docs/go/reference/domains#setAddressLogin); Java [`domains().setAddressLogin`](https://nextmail.sh/docs/java/reference/domains#setAddressLogin); C# [`Domains.SetAddressLoginAsync`](https://nextmail.sh/docs/csharp/reference/domains#setAddressLogin); CLI [`nextmail domains set-address-login`](https://nextmail.sh/docs/cli/reference/domains#domains-set-address-login).

### `domains.delete_address_login()`

Remove the password sign-in of an address

```python
def delete_address_login(
    id: str,
    address_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DeletedAddressLoginResource
```

Takes the password away and signs out everybody who signed in with it. The address, its mail and the people who reach it otherwise stay as they are, and the forwarding destinations added by whoever signed in as the address are removed with it.

Scopes: `members:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DeletedAddressLoginResource` with `object` set to `'address_login'`, `addressId`, `address` and `deleted` set to `True`.

**Example**

```python
from nextmail import NextmailApiError, nextmail

try:
    removed = nextmail.domains.delete_address_login(
        'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70'
    )
except NextmailApiError as error:
    if error.is_not_found:
        print('This address has no password')
    else:
        raise
else:
    print(removed['address'], removed['deleted'])
```

**Notes**

- An address with no password is a 404.
- A key limited to particular addresses or domains is refused with 422 `capability_unsupported`. An access token acting for a member can only reach the sign-in of an address that member reaches, or it is refused with 403 `insufficient_authority`.
- Not retried by the SDK. Repeating a delete that succeeded is a 404.

Also available in: API [`DELETE /domains/{id}/addresses/{addressId}/login`](https://nextmail.sh/docs/api/reference/domains#delete-domains-id-addresses-addressid-login); TypeScript [`nextmail.domains.deleteAddressLogin()`](https://nextmail.sh/docs/sdk/reference/domains#deleteAddressLogin); Ruby [`domains.delete_address_login`](https://nextmail.sh/docs/ruby/reference/domains#deleteAddressLogin); PHP [`domains->deleteAddressLogin`](https://nextmail.sh/docs/php/reference/domains#deleteAddressLogin); Go [`Domains.DeleteAddressLogin`](https://nextmail.sh/docs/go/reference/domains#deleteAddressLogin); Java [`domains().deleteAddressLogin`](https://nextmail.sh/docs/java/reference/domains#deleteAddressLogin); C# [`Domains.DeleteAddressLoginAsync`](https://nextmail.sh/docs/csharp/reference/domains#deleteAddressLogin); CLI [`nextmail domains delete-address-login`](https://nextmail.sh/docs/cli/reference/domains#domains-delete-address-login).

### `domains.get_mail_app_settings()`

Read the mail app settings of an address

```python
def get_mail_app_settings(
    id: str,
    address_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> MailAppSettingsResource
```

Returns what to enter in Apple Mail, Gmail, Outlook, Thunderbird or any other mail app to add the address to it: the IMAP, SMTP and POP3 servers, each with its `host`, `port` and `security`, and the `username` to sign in with, which is the address itself. Each of those three encrypts the connection from the first byte, so its `security` is `'ssl-tls'`. `smtpSubmission` is the same SMTP server on port 587 for apps, devices and libraries that only offer STARTTLS: its `security` is `'starttls'`, the connection is upgraded before the sign-in, and it takes the same username and password.

`caldav` is the server that puts the calendar of the address into Apple Calendar, Thunderbird, DAVx5 on Android or any other CalDAV app, and `carddav` the one that puts the contacts of the workspace into Apple Contacts or any other CardDAV app. Each has a `url` to enter, with the same username and password, a `principalUrl` for apps that ask for the account address on the server, and `host`, `port` and `security` like the others.

`protocols` says which of these connections the address accepts, as `True` or `False` for `imap`, `smtp`, `pop3`, `caldav` and `carddav`. `update_mail_app_settings` changes them.

The password is an app password of the address, such as one `create_app_password` makes, or the password `set_address_login` set when the address has a sign-in of its own without two-factor.

Scopes: `domains:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`MailAppSettingsResource`: `address`, `username`, `imap`, `smtp`, `smtpSubmission` and `pop3`, each with `host`, `port` and `security`, `caldav` and `carddav` with the same three, their `url` and `principalUrl`, and `protocols`.

**Example**

```python
from nextmail import nextmail

settings = nextmail.domains.get_mail_app_settings(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70'
)

print('Sign in as', settings['username'])
print('IMAP', settings['imap']['host'], settings['imap']['port'])
print('SMTP', settings['smtp']['host'], settings['smtp']['port'])
```

**Notes**

- An address id that is not on this domain, or an address that was removed, is a 404 `resource_not_found`, and so is a domain from another workspace. An access token acting for a member gets the same 404 for an address that member cannot read.
- A key or an access token limited to particular addresses or domains reads only the addresses it is limited to, and any other address is a 404 `resource_not_found`.
- A GET is retried automatically on network failure and on 408, 500, 502, 503 and 504 responses, up to the client's `max_retries`, and on a 429 only when it carries a `Retry-After` of a minute or less.

Also available in: API [`GET /domains/{id}/addresses/{addressId}/mail-apps`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-addresses-addressid-mail-apps); TypeScript [`nextmail.domains.getMailAppSettings()`](https://nextmail.sh/docs/sdk/reference/domains#getMailAppSettings); Ruby [`domains.get_mail_app_settings`](https://nextmail.sh/docs/ruby/reference/domains#getMailAppSettings); PHP [`domains->getMailAppSettings`](https://nextmail.sh/docs/php/reference/domains#getMailAppSettings); Go [`Domains.GetMailAppSettings`](https://nextmail.sh/docs/go/reference/domains#getMailAppSettings); Java [`domains().getMailAppSettings`](https://nextmail.sh/docs/java/reference/domains#getMailAppSettings); C# [`Domains.GetMailAppSettingsAsync`](https://nextmail.sh/docs/csharp/reference/domains#getMailAppSettings); CLI [`nextmail domains get-mail-app-settings`](https://nextmail.sh/docs/cli/reference/domains#domains-get-mail-app-settings).

### `domains.update_mail_app_settings()`

Turn mail app connections on or off for an address

```python
def update_mail_app_settings(
    id: str,
    address_id: str,
    patch: MailAppSettingsPatch,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> MailAppSettingsResource
```

Switches each kind of connection the address accepts on or off: `imap`, `smtp` and `pop3` for mail, `caldav` for its calendar and `carddav` for contacts. Send only the ones to change, and the rest stay as they are. Every kind is on until it is switched off.

A switched-off kind refuses every sign-in to it, whatever the password, with a message that says it is turned off. Mail apps and calendar or contacts apps that are already connected over it are signed out within minutes. App passwords stay as they are, so switching a kind back on lets them in again.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `patch['imap']` (`bool`): IMAP, which keeps folders and read state in step with Nextmail.
- `patch['smtp']` (`bool`): SMTP, for sending from a mail app, on port 465 and on port 587 alike.
- `patch['pop3']` (`bool`): POP3, for apps that only download the inbox.
- `patch['caldav']` (`bool`): CalDAV, which puts the calendar of the address into calendar apps.
- `patch['carddav']` (`bool`): CardDAV, which puts the contacts of the workspace into contacts apps.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`MailAppSettingsResource`: the settings as `get_mail_app_settings` returns them, with `protocols` as the switches now stand.

**Example**

```python
from nextmail import nextmail

settings = nextmail.domains.update_mail_app_settings(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    {'pop3': False},
)

print(settings['protocols'])
```

**Notes**

- Only the workspace owner, or someone whose role manages domains, may change the switches. An access token acting for anyone else is refused with 403 `insufficient_authority`. An API key acts for the workspace owner.
- An address id that is not on this domain is a 404 `resource_not_found`. A key or an access token limited to particular addresses or domains changes only the addresses it is limited to, and any other address is a 404 `resource_not_found`.
- An unknown key is refused with 422 `unknown_parameter`, and a value that is not a `bool` with 422 `invalid_parameter`.
- Retried automatically on network failure, since the same patch sent twice leaves the same switches.

Also available in: API [`PATCH /domains/{id}/addresses/{addressId}/mail-apps`](https://nextmail.sh/docs/api/reference/domains#patch-domains-id-addresses-addressid-mail-apps); TypeScript [`nextmail.domains.updateMailAppSettings()`](https://nextmail.sh/docs/sdk/reference/domains#updateMailAppSettings); Ruby [`domains.update_mail_app_settings`](https://nextmail.sh/docs/ruby/reference/domains#updateMailAppSettings); PHP [`domains->updateMailAppSettings`](https://nextmail.sh/docs/php/reference/domains#updateMailAppSettings); Go [`Domains.UpdateMailAppSettings`](https://nextmail.sh/docs/go/reference/domains#updateMailAppSettings); Java [`domains().updateMailAppSettings`](https://nextmail.sh/docs/java/reference/domains#updateMailAppSettings); C# [`Domains.UpdateMailAppSettingsAsync`](https://nextmail.sh/docs/csharp/reference/domains#updateMailAppSettings); CLI [`nextmail domains update-mail-app-settings`](https://nextmail.sh/docs/cli/reference/domains#domains-update-mail-app-settings).

### `domains.list_app_passwords()`

List the app passwords of an address

```python
def list_app_passwords(
    id: str,
    address_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> AppPasswordListResource
```

Returns every app password a mail app can sign in to the address with, newest first. Each one has the `name` it was given, `last4`, the last four letters of the password, to tell them apart, `owner`, the person it signs in as, and `origin`, which says where it was made: `'settings'` in the app, `'api'` through `create_app_password`, and `'setup-link'` by opening an emailed setup link, such as one `send_mail_app_setup` sends.

`lastUsedAt` and `lastUsedProtocol` say when an app last signed in with it and over which of `'imap'`, `'smtp'`, `'pop3'`, `'caldav'` and `'carddav'`, and `lastUsedClient` names the mail app when it named itself. The passwords themselves are shown only when they are made, and revoked ones are left out.

Scopes: `members:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`AppPasswordListResource`, with the app passwords in `data`, newest first.

**Example**

```python
from nextmail import nextmail

passwords = nextmail.domains.list_app_passwords(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70'
)

for password in passwords['data']:
    last_used = password['lastUsedAt'] or 'never used'
    print(password['name'], password['last4'], password['owner']['email'], last_used)
```

**Notes**

- It needs `members:write`, the scope that makes and revokes app passwords, as the app does, rather than a read scope.
- An address id that is not on this domain, or an address that was removed, is a 404 `resource_not_found`, and so is a domain from another workspace.
- A key or an access token limited to particular addresses or domains is refused with 422 `capability_unsupported`, and so is an app a member connected, because its access token is always limited to the addresses that member reaches.
- A GET is retried automatically on network failure and on 408, 500, 502, 503 and 504 responses, up to the client's `max_retries`, and on a 429 only when it carries a `Retry-After` of a minute or less.

Also available in: API [`GET /domains/{id}/addresses/{addressId}/app-passwords`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-addresses-addressid-app-passwords); TypeScript [`nextmail.domains.listAppPasswords()`](https://nextmail.sh/docs/sdk/reference/domains#listAppPasswords); Ruby [`domains.list_app_passwords`](https://nextmail.sh/docs/ruby/reference/domains#listAppPasswords); PHP [`domains->listAppPasswords`](https://nextmail.sh/docs/php/reference/domains#listAppPasswords); Go [`Domains.ListAppPasswords`](https://nextmail.sh/docs/go/reference/domains#listAppPasswords); Java [`domains().listAppPasswords`](https://nextmail.sh/docs/java/reference/domains#listAppPasswords); C# [`Domains.ListAppPasswordsAsync`](https://nextmail.sh/docs/csharp/reference/domains#listAppPasswords); CLI [`nextmail domains list-app-passwords`](https://nextmail.sh/docs/cli/reference/domains#domains-list-app-passwords).

### `domains.create_app_password()`

Create an app password for an address

```python
def create_app_password(
    id: str,
    address_id: str,
    body: AppPasswordCreate,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> CreatedAppPasswordResource
```

Makes a password a mail app signs in to the address with, using the address as the username, and returns it in `password` with the server settings in `servers`. That is the only time the password is shown, so hand it over or store it then.

The password signs in as the caller for this address alone: an API key makes it for the workspace owner, and an access token for the person who connected the app. A mail app using it reaches the mail of the address with what that person may do there, and nothing else in the workspace. It is 16 letters in four groups joined by dashes, and the dashes, or spaces in their place, can be left out when it is typed.

Scopes: `members:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `body['name']` (`str`, required): What to call the password, such as the device it is for, 1 to 64 characters. It is trimmed.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`CreatedAppPasswordResource`: the app password as `list_app_passwords` returns it, with `origin` set to `'api'`, plus `password`, shown this once, `servers`, the settings `get_mail_app_settings` returns, and `appleProfile`, an Apple configuration profile with the password inside. Saved as a `.mobileconfig` file and opened on an iPhone, iPad or Mac, the profile adds the address to Mail and its calendar and contacts to Calendar and Contacts in one step, for the connections the address accepts. It holds the password, so keep it like one.

**Example**

```python
from nextmail import nextmail

created = nextmail.domains.create_app_password(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    {'name': 'Front desk iPad'},
)
servers = created['servers']

print('Sign in as', servers['username'], 'with', created['password'])
print('IMAP', servers['imap']['host'], servers['imap']['port'])
print('SMTP', servers['smtp']['host'], servers['smtp']['port'])
```

**Notes**

- One person can hold 20 app passwords for one address, and the 21st is refused with 422 `app_password_limit_reached`, so revoke one with `delete_app_password` first. An address that only forwards its mail, or is switched off, has no mailbox for a mail app to open and is refused with 422 `address_has_no_mailbox`.
- A key or an access token limited to particular addresses or domains is refused with 422 `capability_unsupported`, and so is an app a member connected, because its access token is always limited to the addresses that member reaches.
- An OAuth access token needs a verification code for this call, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An API key is never asked for a code.
- Not retried automatically by the SDK, since a lost attempt may already have made a password. The success status is 201.

Also available in: API [`POST /domains/{id}/addresses/{addressId}/app-passwords`](https://nextmail.sh/docs/api/reference/domains#post-domains-id-addresses-addressid-app-passwords); TypeScript [`nextmail.domains.createAppPassword()`](https://nextmail.sh/docs/sdk/reference/domains#createAppPassword); Ruby [`domains.create_app_password`](https://nextmail.sh/docs/ruby/reference/domains#createAppPassword); PHP [`domains->createAppPassword`](https://nextmail.sh/docs/php/reference/domains#createAppPassword); Go [`Domains.CreateAppPassword`](https://nextmail.sh/docs/go/reference/domains#createAppPassword); Java [`domains().createAppPassword`](https://nextmail.sh/docs/java/reference/domains#createAppPassword); C# [`Domains.CreateAppPasswordAsync`](https://nextmail.sh/docs/csharp/reference/domains#createAppPassword); CLI [`nextmail domains create-app-password`](https://nextmail.sh/docs/cli/reference/domains#domains-create-app-password).

### `domains.update_app_password()`

Rename an app password

```python
def update_app_password(
    id: str,
    address_id: str,
    password_id: str,
    patch: AppPasswordPatch,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> AppPasswordResource
```

Changes the name shown for the app password, such as when the device it is for changes hands. The password itself stays the same, and a mail app signed in with it stays signed in.

A person renames the app passwords they hold. The workspace owner, and someone whose role manages members, rename anyone's.

Scopes: `members:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `password_id` (`str`, required): An app password id from `list_app_passwords` or `create_app_password`. It has to be an app password of the address named by `address_id`.
- `patch['name']` (`str`, required): The new name, 1 to 64 characters. It is trimmed.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`AppPasswordResource`: the app password as `list_app_passwords` returns it, with its new `name`.

**Example**

```python
from nextmail import nextmail

password = nextmail.domains.update_app_password(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    'map_3f9a1c7e5b2d4f6a8c0e1b3d',
    {'name': 'Reception iPad'},
)

print(password['name'], password['last4'])
```

**Notes**

- An app password id that is not on this address, one already revoked, or one held by someone else when the caller cannot manage members, is a 404 `resource_not_found`.
- A key or an access token limited to particular addresses or domains is refused with 422 `capability_unsupported`, and so is an app a member connected, because its access token is always limited to the addresses that member reaches.
- Retried automatically on network failure, since the same name sent twice leaves the same password.

Also available in: API [`PATCH /domains/{id}/addresses/{addressId}/app-passwords/{passwordId}`](https://nextmail.sh/docs/api/reference/domains#patch-domains-id-addresses-addressid-app-passwords-passwordid); TypeScript [`nextmail.domains.updateAppPassword()`](https://nextmail.sh/docs/sdk/reference/domains#updateAppPassword); Ruby [`domains.update_app_password`](https://nextmail.sh/docs/ruby/reference/domains#updateAppPassword); PHP [`domains->updateAppPassword`](https://nextmail.sh/docs/php/reference/domains#updateAppPassword); Go [`Domains.UpdateAppPassword`](https://nextmail.sh/docs/go/reference/domains#updateAppPassword); Java [`domains().updateAppPassword`](https://nextmail.sh/docs/java/reference/domains#updateAppPassword); C# [`Domains.UpdateAppPasswordAsync`](https://nextmail.sh/docs/csharp/reference/domains#updateAppPassword); CLI [`nextmail domains update-app-password`](https://nextmail.sh/docs/cli/reference/domains#domains-update-app-password).

### `domains.delete_app_password()`

Revoke an app password

```python
def delete_app_password(
    id: str,
    address_id: str,
    password_id: str,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DeletedAppPasswordResource
```

Revokes the app password, so no mail app can sign in with it again, and a mail app that is signed in with it is signed out within minutes. The address, its mail and its other app passwords stay as they are.

Scopes: `members:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `password_id` (`str`, required): An app password id from `list_app_passwords` or `create_app_password`. It has to be an app password of the address named by `address_id`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DeletedAppPasswordResource` with `object` set to `'app_password'`, `id` and `deleted` set to `True`.

**Example**

```python
from nextmail import NextmailApiError, nextmail

try:
    revoked = nextmail.domains.delete_app_password(
        'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
        '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
        'map_3f9a1c7e5b2d4f6a8c0e1b3d',
    )
except NextmailApiError as error:
    if error.is_not_found:
        print('This app password was already revoked')
    else:
        raise
else:
    print('Revoked', revoked['id'])
```

**Notes**

- An app password id that is not on this address, or one already revoked, is a 404 `resource_not_found`.
- A key or an access token limited to particular addresses or domains is refused with 422 `capability_unsupported`, and so is an app a member connected, because its access token is always limited to the addresses that member reaches.
- Not retried by the SDK. Repeating a delete that succeeded is a 404.

Also available in: API [`DELETE /domains/{id}/addresses/{addressId}/app-passwords/{passwordId}`](https://nextmail.sh/docs/api/reference/domains#delete-domains-id-addresses-addressid-app-passwords-passwordid); TypeScript [`nextmail.domains.deleteAppPassword()`](https://nextmail.sh/docs/sdk/reference/domains#deleteAppPassword); Ruby [`domains.delete_app_password`](https://nextmail.sh/docs/ruby/reference/domains#deleteAppPassword); PHP [`domains->deleteAppPassword`](https://nextmail.sh/docs/php/reference/domains#deleteAppPassword); Go [`Domains.DeleteAppPassword`](https://nextmail.sh/docs/go/reference/domains#deleteAppPassword); Java [`domains().deleteAppPassword`](https://nextmail.sh/docs/java/reference/domains#deleteAppPassword); C# [`Domains.DeleteAppPasswordAsync`](https://nextmail.sh/docs/csharp/reference/domains#deleteAppPassword); CLI [`nextmail domains delete-app-password`](https://nextmail.sh/docs/cli/reference/domains#domains-delete-app-password).

### `domains.send_mail_app_setup()`

Email a mail app setup link for an address

```python
def send_mail_app_setup(
    id: str,
    address_id: str,
    body: MailAppSetupSend,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> MailAppSetupResource
```

Emails the recipient a link that sets the address up in a mail app. Opening it makes an app password named after the recipient, shows it once with the server settings, and offers a profile that sets up an Apple device in one step. The link works once and expires in three days, at `expiresAt`.

The app password it makes signs in as the caller, as one from `create_app_password` does: an API key makes it for the workspace owner, and an access token for the person who connected the app. It then appears in `list_app_passwords` with `origin` set to `'setup-link'`.

Scopes: `members:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `address_id` (`str`, required): Address id from `list_addresses` or `create_address`, a UUID. It has to be an address on the domain named by `id`.
- `body['recipient']` (`str`, required): The email address to send the link to, such as the person who will use the mail app. It is trimmed and lowercased.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`MailAppSetupResource`: `address`, `recipient` and `expiresAt`, when the link stops working.

**Example**

```python
from nextmail import nextmail

setup = nextmail.domains.send_mail_app_setup(
    'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f',
    '7c9d2e41-0b8f-4a63-9e25-1f4d6a8b3c70',
    {'recipient': 'ada@example.com'},
)

print('Sent', setup['recipient'], 'a link for', setup['address'])
print('It works once, until', setup['expiresAt'])
```

**Notes**

- When the email cannot be sent the call is a 503 `setup_email_not_sent` and nothing is made, so it is safe to call again. An address that only forwards its mail, or is switched off, has no mailbox for a mail app to open and is refused with 422 `address_has_no_mailbox`. A workspace can email 50 setup links a day, and past that the call is a 429 `setup_email_rate_limited`.
- A key or an access token limited to particular addresses or domains is refused with 422 `capability_unsupported`, and so is an app a member connected, because its access token is always limited to the addresses that member reaches. Only the workspace owner, or someone whose role holds `members:write`, can send a link, and anyone else is refused with 403 `insufficient_authority`.
- An OAuth access token needs a verification code for this call, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An API key is never asked for a code.
- Not retried automatically by the SDK, since every attempt can send an email.

Also available in: API [`POST /domains/{id}/addresses/{addressId}/mail-app-setup`](https://nextmail.sh/docs/api/reference/domains#post-domains-id-addresses-addressid-mail-app-setup); TypeScript [`nextmail.domains.sendMailAppSetup()`](https://nextmail.sh/docs/sdk/reference/domains#sendMailAppSetup); Ruby [`domains.send_mail_app_setup`](https://nextmail.sh/docs/ruby/reference/domains#sendMailAppSetup); PHP [`domains->sendMailAppSetup`](https://nextmail.sh/docs/php/reference/domains#sendMailAppSetup); Go [`Domains.SendMailAppSetup`](https://nextmail.sh/docs/go/reference/domains#sendMailAppSetup); Java [`domains().sendMailAppSetup`](https://nextmail.sh/docs/java/reference/domains#sendMailAppSetup); C# [`Domains.SendMailAppSetupAsync`](https://nextmail.sh/docs/csharp/reference/domains#sendMailAppSetup); CLI [`nextmail domains send-mail-app-setup`](https://nextmail.sh/docs/cli/reference/domains#domains-send-mail-app-setup).

### `domains.get_dns()`

Read how the DNS of a domain is set up

```python
def get_dns(
    id: str,
    *,
    refresh: bool | None = None,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainDnsResource
```

Returns whether Nextmail writes the records of the domain itself (`managing`), through which connection and zone, where each kind of record stands in `steps`, and the records left behind to delete by hand.

`zone` says which connected zone answers for the domain: one is `resolved`, several are `ambiguous` and need `set_dns_zone`, `none` holds it, with the reason, or the connections could not be asked (`unusable`). The answer is kept for a few minutes, and `refresh=True` asks the providers again.

Scopes: `domains:read`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `refresh` (`bool`): `True` asks the providers again which zone answers for the domain.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainDnsResource`.

**Example**

```python
from nextmail import nextmail

dns = nextmail.domains.get_dns('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f', refresh=True)

print(dns['managing'], dns['state'], dns['zone']['kind'])

for step in dns['steps']:
    print(step['purpose'], step['ok'], step['detail'])
```

**Notes**

- A domain id that is not in this workspace is a 404 `resource_not_found`.
- A GET is retried automatically on network failure and on 408, 500, 502, 503 and 504 responses, up to the client's `max_retries`, and on a 429 only when it carries a `Retry-After` of a minute or less.

Also available in: API [`GET /domains/{id}/dns`](https://nextmail.sh/docs/api/reference/domains#get-domains-id-dns); TypeScript [`nextmail.domains.getDns()`](https://nextmail.sh/docs/sdk/reference/domains#getDns); Ruby [`domains.get_dns`](https://nextmail.sh/docs/ruby/reference/domains#getDns); PHP [`domains->getDns`](https://nextmail.sh/docs/php/reference/domains#getDns); Go [`Domains.GetDNS`](https://nextmail.sh/docs/go/reference/domains#getDns); Java [`domains().getDns`](https://nextmail.sh/docs/java/reference/domains#getDns); C# [`Domains.GetDnsAsync`](https://nextmail.sh/docs/csharp/reference/domains#getDns); CLI [`nextmail domains get-dns`](https://nextmail.sh/docs/cli/reference/domains#domains-get-dns).

### `domains.set_dns_zone()`

Choose the zone a domain is set up through

```python
def set_dns_zone(
    id: str,
    body: DomainDnsZoneSet,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainDnsResource
```

Attaches the domain to a zone of a connection, when several connected zones could answer for it. The zone has to cover the domain, be active at the provider and take a test record. Nothing is written yet: call `sync_dns` to write the records.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `body['connectionId']` (`str`, required): The connection that holds the zone, from `dns_connections.list`.
- `body['zoneId']` (`str`, required): The zone, as the `candidates` in the `zone` of `get_dns` list it: a candidate's `candidate['zone']['id']`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainDnsResource` as it stands after the change.

**Example**

```python
from nextmail import nextmail

domain_id = 'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f'
candidates = nextmail.domains.get_dns(domain_id)['zone']['candidates']

if candidates:
    choice = candidates[0]
    dns = nextmail.domains.set_dns_zone(
        domain_id, {'connectionId': choice['connectionId'], 'zoneId': choice['zone']['id']}
    )
    print(dns['zoneName'], dns['state'])
```

**Notes**

- A zone that does not cover the domain is a 422 `invalid_parameter` on `zoneId`. A domain already set up through another zone is refused with 409 `dns_zone_conflict`, a zone that is not active or refuses the test record with 409 `dns_zone_unusable`, and a connection that was disconnected with 409 `dns_connection_unusable`.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- An OAuth access token needs a verification code for this call, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An API key is never asked for a code.
- Not retried by the SDK.

Also available in: API [`PUT /domains/{id}/dns`](https://nextmail.sh/docs/api/reference/domains#put-domains-id-dns); TypeScript [`nextmail.domains.setDnsZone()`](https://nextmail.sh/docs/sdk/reference/domains#setDnsZone); Ruby [`domains.set_dns_zone`](https://nextmail.sh/docs/ruby/reference/domains#setDnsZone); PHP [`domains->setDnsZone`](https://nextmail.sh/docs/php/reference/domains#setDnsZone); Go [`Domains.SetDNSZone`](https://nextmail.sh/docs/go/reference/domains#setDnsZone); Java [`domains().setDnsZone`](https://nextmail.sh/docs/java/reference/domains#setDnsZone); C# [`Domains.SetDnsZoneAsync`](https://nextmail.sh/docs/csharp/reference/domains#setDnsZone); CLI [`nextmail domains set-dns-zone`](https://nextmail.sh/docs/cli/reference/domains#domains-set-dns-zone).

### `domains.sync_dns()`

Write the DNS records of a domain

```python
def sync_dns(
    id: str,
    body: DomainDnsSync | None = None,
    *,
    api_key: str | None = None,
    timeout: float | None = None,
) -> DomainDnsSyncResource
```

Writes or repairs every record the domain needs through the connected zone that answers for it, as Sync does in the app. When exactly one zone answers it is attached first, and `attached` says so. With `purpose`, only that kind of record is written. A domain that was waiting for its records is verified once they are in place.

When no single zone answers, nothing is written: `outcome` is `refused`, `message` says why and `zone` shows the zones to choose from with `set_dns_zone`.

Scopes: `domains:write`.

**Parameters**

- `id` (`str`, required): Domain id from `list` or `create`, a UUID.
- `body['purpose']` (`DnsSyncPurpose`): Only this kind of record: `dmarc`, `tracking`, `storage`, `bimi` or `app-host`.
- `api_key` (`str`): Overrides the client's API key for this call only.
- `timeout` (`float`): Seconds this call may take, the response included, before it raises `NextmailNetworkError` with `is_timeout`. It overrides the client's `timeout` for this call, and `0` turns the limit off.

**Returns**

`DomainDnsSyncResource` with `outcome`, the `provision` that ran and the DNS setup as it is now in `dns`.

**Example**

```python
from nextmail import nextmail

sync = nextmail.domains.sync_dns('b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f')
provision = sync['provision']

if sync['outcome'] == 'refused':
    print(sync['message'])
elif provision is not None:
    for record in provision['written']:
        print(record['type'], record['name'], record['mode'])
```

**Notes**

- A sync already running on the domain is refused with 409 `dns_busy`. A provider that refuses the request is a 502 `dns_provider_error`.
- A key limited to particular addresses or domains has to hold this whole domain in its `domainAllowlist`, or the call is refused with 422 `capability_unsupported` on `domainAllowlist`.
- An OAuth access token needs a verification code for this call, and is refused with 403 `step_up_required` until the app has verified one in the last 60 minutes. `is_step_up_required` on the error says so. An API key is never asked for a code.
- Not retried by the SDK.

Also available in: API [`POST /domains/{id}/dns/sync`](https://nextmail.sh/docs/api/reference/domains#post-domains-id-dns-sync); TypeScript [`nextmail.domains.syncDns()`](https://nextmail.sh/docs/sdk/reference/domains#syncDns); Ruby [`domains.sync_dns`](https://nextmail.sh/docs/ruby/reference/domains#syncDns); PHP [`domains->syncDns`](https://nextmail.sh/docs/php/reference/domains#syncDns); Go [`Domains.SyncDNS`](https://nextmail.sh/docs/go/reference/domains#syncDns); Java [`domains().syncDns`](https://nextmail.sh/docs/java/reference/domains#syncDns); C# [`Domains.SyncDnsAsync`](https://nextmail.sh/docs/csharp/reference/domains#syncDns); CLI [`nextmail domains sync-dns`](https://nextmail.sh/docs/cli/reference/domains#domains-sync-dns).
