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

# Test environment

> Exercise delivery, bounce, complaint and delay paths with isolated Mail data and no real email delivery.

<Warning>
  **Live with caveats.** This area is real and usable, but the docs intentionally call out operational or UX limits that still matter.
</Warning>

## Goal

Exercise delivery, bounce, complaint and delay paths with isolated Mail data and no real email delivery.

## Prerequisites

* Keep Mail credentials on your backend. API examples use [https://api.stackshift.cloud/v1](https://api.stackshift.cloud/v1) unless a public /api/v1 route is stated.

## Workflow

<Steps>
  <Step>
    Create a test credential and explicitly create isolated test resources.
  </Step>

  <Step>
    Choose a scenario in the dashboard, API body or SMTP header.
  </Step>

  <Step>
    Inspect test logs/events and verify signatures on your test webhook endpoint.
  </Step>
</Steps>

## Credential mode and access

* Create a Mail credential in Settings → Security and choose Test. Test keys start with sspat\_test\_; mode is immutable. Existing credentials remain live. Keep mail:send for submission and mail:read for read access; use mail:manage for resource creation/updates such as brands, audiences and campaigns. These scopes never override environment or billing-owner restrictions.
* The credential selects live or test. X-Mail-Mode cannot change an API token’s environment: a mismatched header returns HTTP 403. The signed-in dashboard uses X-Mail-Mode through its persistent Live/Test selector.
* Test credentials cannot call unrelated platform APIs, manage live sending domains, change tracking settings/domains, use inbound Mail, or access migration checklists. Public DNS audit calls need no credential. GET /mail/billing is available in Test, but billing writes are not.
* Messages, templates, audiences, brands, contacts, suppressions, webhooks, campaigns, batches, scheduled messages, OTPs and related events retain their environment. Resource IDs from the other environment cannot be used to access it. Idempotency is scoped by workspace and mode.
* No production subscriber data is copied. Create test brands, audiences, templates and endpoints explicitly. Domain verification is not required, but address/content/template/consent validation still applies. Test credentials do not grant access to Assets APIs.

## Scenarios and timing

* simulation.scenario accepts delivered, bounced, complained or delayed. Omit simulation to default to delivered in Test. Unknown scenarios are rejected; live credentials reject simulation options.
* delivered records simulated acceptance and delivery; bounced records a simulated hard bounce; complained records simulated delivery followed by a complaint. These can update only test suppressions.
* delayed records a delay, then becomes eligible for simulated delivery 60 seconds later. Actual completion depends on worker polling; this is not a 60-second wall-clock SLA.
* Options are accepted by direct and template sends, individual batch messages, schedules, campaigns, automations, campaign tests and OTP sends. Preserve mode and the chosen scenario when inspecting retries and deferred work.

## API example

```ts theme={null}
import { StackShift } from '@stackshift-cloud/sdk'
const client = new StackShift({ apiKey: process.env.STACKSHIFT_MAIL_TEST_KEY! })
const message = await client.mail.send({
  from: 'hello@example.com', to: 'fixture@example.net',
  subject: 'Delayed simulation', text: 'No email will be delivered.',
  idempotencyKey: 'delayed-fixture-1', simulation: { scenario: 'delayed' },
})
console.log(message.id, message.mode, message.status)
const history = await client.mail.messages.get(message.id)
```

## SMTP selection

* Port 465 supports implicit TLS. Keep certificate verification enabled. Use the test credential as the password and a nonempty username.
* X-Stackshift-Simulation is the SMTP equivalent of simulation.scenario. Duplicate headers, unsupported values and simulation headers on live credentials are rejected.

```ts theme={null}
import nodemailer from 'nodemailer'
const transport = nodemailer.createTransport({
  host: 'smtp.mail.stackshift.cloud', port: 587, secure: false, requireTLS: true,
  auth: { user: 'integration-test', pass: process.env.STACKSHIFT_MAIL_TEST_KEY },
})
await transport.sendMail({
  from: 'hello@example.com', to: 'fixture@example.net',
  subject: 'Bounce simulation', text: 'No real delivery.',
  headers: { 'X-Stackshift-Simulation': 'bounced' },
})
```

## Webhooks, confirmations and reports

* Test webhooks make real HTTP requests to endpoints explicitly created in Test. They use the normal raw-body signature, retry and replay protocol. Deduplicate event IDs; processing is at least once. Test events never enter live automation integrations.
* Subscriber confirmation, signup, preferences and unsubscribe pages display “Simulated—no email delivered” for test records. Obtain confirmation links from test message logs; no confirmation is sent to a real inbox. GET opens the confirmation page; POST confirms.
* Test sends do not consume live allowance/prepaid funds or affect live reputation and engagement reporting. Exhausted live billing allowance does not block Test. The dashboard labels simulated messages.

## Limits and retention

* Simulator defaults are 60 messages/minute and 10,000/day, independently configurable through MAIL\_SIMULATION\_PER\_MINUTE\_LIMIT and MAIL\_SIMULATION\_DAILY\_LIMIT. They are abuse limits, not paid allowance.
* Test messages and event content older than seven days are removed by retention maintenance. Expired events are no longer available for replay. Finished batch/schedule payloads are scrubbed; future pending schedules are not deleted merely because their creation was more than seven days ago.
* The legacy MAIL\_SANDBOX\_ENABLED setting controls a recipient allowlist that still sends REAL email. Its false value does not disable test credentials or the simulator.

## Expected result

<Check>
  Test messages produce simulated states and signed test events without delivery to an MTA or a real inbox.
</Check>

## Related guides

<CardGroup cols={2}>
  <Card title="StackShift Mail overview" href="/stackshift-mail/overview">
    Mail APIs and workflows: isolated simulation, explicit brands, consent-aware campaigns, engagement, domain health, migration, spending, inbound delivery and diagnostics.
  </Card>

  <Card title="Events, webhooks, and timelines" href="/stackshift-mail/events-webhooks-and-timelines">
    List mail events, inspect per-message timelines, subscribe webhooks, rotate secrets, retry deliveries, and verify webhook signatures.
  </Card>

  <Card title="Brands and shared contacts" href="/stackshift-mail/brands-and-contacts">
    Create explicit sending identities and share contact profiles within a brand while keeping audience consent independent.
  </Card>

  <Card title="Subscriber consent and imports" href="/stackshift-mail/subscriber-consent-and-imports">
    Preview imports row by row, preserve consent evidence and use double opt-in before marketing delivery.
  </Card>

  <Card title="SMTP submission" href="/stackshift-mail/smtp-submission">
    Submit existing MIME email through authenticated TLS while retaining StackShift Mail policy, delivery evidence, and attachment scanning.
  </Card>
</CardGroup>
