Exchange is excluded from this API/CLI release. Any historical Exchange API or CLI example in this guide is unavailable; native portal behavior is outside this exclusion. See [current release scope](/developers/guides/release-scope?lang=en).

# Test portal email deliberately

The mail test sends one fixed test message to the **current verified login address of the internal administrator performing the action**. There is no configurable recipient, subject, body or attachment. The message contains only the original test reference, without customer data or secrets. A personal connection with current internal administrator rights and recent passkey verification is required; service connections cannot run a mail test.

`accepted` means the mail transport call confirmed acceptance. It does not prove inbox delivery. Check your own inbox and spam folder. The test does not change SMTP settings, customer data, invoices, passwords or supplier services.

## Portal

Open `/test-application-email-system`. Opening the page sends nothing. Choose **Check recipient and current version**, verify your passkey and check your own displayed address. Tick the explicit confirmation and choose **Request one test message**.

The browser saves the original test number before sending. After an uncertain response or a reload, **Read original attempt** uses only that same number. There is no automatic sending, polling or new attempt after renewed verification. If your passkey expires, read and verify again, then explicitly confirm sending yourself.

One new attempt is allowed per five minutes, across all administration companies and connections of the same administrator. Investigate an uncertain previous outcome first. For an explicit new attempt, enter the displayed original reference and choose the separate review button. The server checks the cooldown period and exact previous attempt again. Do not delete a locally saved reference to bypass an unknown outcome.

## API

All paths are under `/api/v1/accounts/{administratiecontext}`. Use `admin:read` for inspection/status and `admin:write` for requests. The API, write, sensitive and administration flags still apply. The administration context is your own approved management company.

| Method | Path | Result |
| --- | --- | --- |
| GET | `/admin/mail-test` | Your own `actor_id`, fixed `recipient`, `version`/ETag and at most ten of your own attempts within this context |
| POST | `/admin/mail-tests` | One explicit request with the same original UUID |
| GET | `/admin/mail-tests/{intent_id}` | Only safe status of your original attempt within the same context; no email |

Read the recipient and current version first. Send the ETag as `If-Match`, one durable `Idempotency-Key` and only:

```json
{"intent_id":"1fe95bbe-8449-4ea3-a6b2-3f013a2047bc","confirm_user_id":8}
```

`confirm_user_id` must be the actual administrator performing the action, as returned by GET. Save the UUID, body and idempotency key before the POST. `dry_run:true` performs the current checks without an attempt, operation or send. A missing version returns 428; a changed version 412; a new attempt too soon 429. Custom recipient or message fields return 422.

A durable attempt exists before SMTP can begin. The same UUID cannot start a second SMTP call, even with a different HTTP idempotency key. After a lost response, first read the original UUID and existing operation. A `404` does not prove that a concurrent original request will never commit: retain the reference and investigate that same attempt later.

| Status | Meaning |
| --- | --- |
| `prepared` | Original attempt recorded; no confirmed delivery |
| `dispatching` | A transport call may be in progress or interrupted |
| `uncertain` | Acceptance not confirmed; no automatic retry |
| `blocked` | The current check blocked sending |
| `accepted` | Transport acceptance confirmed; inbox delivery remains unproven |

`requires_reconciliation:true` requires investigation of the original attempt. After review, a separate new UUID can be requested, with `replace_attempt_id` equal to the exact last unresolved reference. The CLI uses `--replace-attempt OORSPRONKELIJKE_UUID` for the deliberate new `send` request. This is a deliberate new mail request; the cooldown period and all current checks still apply.

## CLI and AI agents

```sh
binadit admin mail-test get --account 1
binadit admin mail-test send --account 1 \
  --intent-id 1fe95bbe-8449-4ea3-a6b2-3f013a2047bc \
  --confirm-user 8 --version '<data.version uit get>' --dry-run
binadit admin mail-test send --account 1 \
  --intent-id 1fe95bbe-8449-4ea3-a6b2-3f013a2047bc \
  --confirm-user 8 --version '<dezelfde actuele data.version>' --yes
binadit admin mail-test status 1fe95bbe-8449-4ea3-a6b2-3f013a2047bc --account 1
```

An agent never chooses another recipient address and does not create a replacement UUID after an uncertain outcome. Check the explicit administration company, your own recipient and the current version. Retain the original reference after closing the CLI too. The CLI records a private metadata marker before an actual POST; later executions with the same UUID can only investigate the original status. The CLI displays only the fixed safe status contract, not SMTP error text or transport configuration.

The mail test uses one separate SMTP or sendmail transport. SMTP requires TLS and certificate verification; global debug recipients are not inherited. Log, failover and round-robin transports are unsuitable for this explicit test and return a controlled 503. This is a configuration requirement, not proof that an existing external mail server is live and reachable.
