Set up and test install alert SMTP¶
This tests the install's configured Django SMTP alert channel with one fixed message
to your current registered mailbox. It is separate from app-owned SES tests.
The default django_ses.SESBackend, Azure ACS, app SMTP and plaintext SMTP are unsupported
by this diagnostic. There is no transport fallback or relay configuration mutation.
The matching offline topic is astro docs show install-alert-mail (aliases
alert-mail and install-smtp). Older CLI releases may not include this guide.
Use the current server schema and installAlertMailSupport; the SES capability
keys do not advertise support for this install channel.
1. Configure the install channel privately¶
An install operator configures these existing settings through the install's private configuration and normal configuration rollout:
| Setting | Required value or purpose |
|---|---|
DJANGO_EMAIL_BACKEND |
django.core.mail.backends.smtp.EmailBackend |
EMAIL_HOST, EMAIL_PORT |
The configured relay hostname and port |
FROM_EMAIL |
Configured diagnostic sender |
EMAIL_HOST_USER, EMAIL_HOST_PASSWORD |
Relay login, if required; keep private |
EMAIL_USE_TLS |
true for STARTTLS, with EMAIL_USE_SSL=false |
EMAIL_USE_SSL |
true for implicit TLS, with EMAIL_USE_TLS=false |
EMAIL_SSL_KEYFILE, EMAIL_SSL_CERTFILE |
Optional private client-certificate paths |
Exactly one TLS mode must be enabled. The native attempt verifies the relay's TLS certificate and hostname. The support query describes configured TLS, not an observed successful connection. Do not put relay credentials or client keys in app manifests, GraphQL variables, shell history, screenshots or the documentation repository. Changing these settings does not configure app-owned mail services.
The install's EMAIL_NOTIFICATIONS master flag must be enabled through authorized
install configuration administration. It defaults off. The caller's current email
preference for the selected event must also be enabled. This diagnostic does not
verify scheduler execution, notification fanout or ordinary alert delivery.
2. Check your event preference¶
These eight existing email event kinds default enabled once the master flag is on; an explicit caller preference can mute each one independently:
| Event kind | Meaning |
|---|---|
deploy.failed |
Deployment failed; diagnostic default |
app.down |
App unavailable |
app.recovered |
App recovered |
domain.cert_expiring |
Certificate expiring |
domain.cert_renewal_failed |
Certificate renewal failed |
cluster.bootstrap_failed |
Cluster bootstrap failed |
secret.revealed |
Secret revealed |
app.deregister_pending |
App deregistration pending |
The existing self-only preference API reads and sets the caller's toggle; it does not change another user's preference or grant operator authority:
query OwnEmailPreferences {
astroliftMyNotificationPreferences(channel: "email") { channel eventKind enabled }
}
To intentionally change your own toggle, save this as alert-preference.graphql:
mutation OwnEmailPreference($input: SetNotificationPreferenceInput!) {
setNotificationPreference(input: $input) {
ok errors { code message }
data { channel eventKind enabled }
}
}
With umask 077, save a private alert-preference.json:
astro --server staging --org ORGANIZATION_GUID api graphql \
--file alert-preference.graphql --vars-file alert-preference.json
Inspect ok/errors/data; setting a preference does not send the diagnostic.
3. Review the current source in Notifications¶
Select the current organization and open Settings → Notifications → Install alert
email test (/settings/notifications?section=install-email). The Test platform
alert email link on the domain Email delivery page opens the same section.
Navigation uses the advisory org.update hint. The server separately requires an
active platform operator, current organization membership and org.update for
support, send and history. An ordinary organization administrator is not admitted
merely because a link is visible. Bearer credentials need the current admin scope
and organization ceiling; session/credential withdrawal is rechecked during transport.
Choose the event, review the sender, your own registered mailbox, configured TLS mode and check time, then select Review source and mailbox. There is no editable recipient, subject, body, relay or credential. Select Send reviewed alert test only for an intentional test. The page rechecks the source immediately before dispatch.
For CLI/API use, save alert-support.graphql:
query InstallAlertMailSupport($event: String!) {
installAlertMailSupport(eventKind: $event) {
allowed reason transport sender recipient tlsMode sourceFingerprint checkedAt
}
}
astro --server staging --org ORGANIZATION_GUID api graphql \
--file alert-support.graphql --var event=deploy.failed
A denied query or allowed=false is a refusal, not an empty healthy configuration.
The opaque sourceFingerprint binds current settings and the selected event using
the install's private HMAC facility. It is not an SMTP account/incarnation proof.
Client-certificate paths are settings metadata, not a hash of certificate contents.
4. Send one reviewed intent¶
Save alert-send.graphql:
mutation InstallAlertMailTest($input: SendInstallAlertMailTestInput!) {
sendInstallAlertMailTest(input: $input) {
ok errors { code message }
data {
id requestId version eventKind transport sender recipient status reasonCode
createdAt acceptedAt deliveryObserved
}
}
}
Generate one UUID for the intentionally reviewed test and retain it. With umask 077,
save a private alert-test.json, replacing the placeholders with that original UUID
and the exact current reviewed fingerprint:
{
"input": {
"requestId": "ORIGINAL_REQUEST_UUID",
"expectedSourceFingerprint": "REVIEWED_SOURCE_FINGERPRINT",
"eventKind": "deploy.failed"
}
}
astro --server staging --org ORGANIZATION_GUID api graphql \
--file alert-send.graphql --vars-file alert-test.json
The send service refuses an enclosing database transaction or disabled autocommit
with ALERT_MAIL_ENCLOSING_TRANSACTION_UNSUPPORTED, after current permission
admission and before reserving an intent or contacting SMTP. Intent and pre-DATA
transitions must commit independently before native effects. Internal integrations
must not wrap the service in a transaction that could roll back nonce history
after sending.
There is no dedicated test-send CLI verb. HTTP success or CLI exit zero does not
establish mutation success; inspect GraphQL errors, ok/errors/data and the receipt.
The message content is fixed. The receipt stores addresses, event and intent/source
metadata, not relay credentials, subject/body or raw native replies. The UI stores
only actor/organization/event-bound nonce/fingerprint recovery metadata in session storage.
5. Recover without resending¶
| Status | Interpretation |
|---|---|
reserved |
Intent committed; the attempt may be in progress |
sent |
Pre-DATA intent committed; acceptance is unconfirmed |
accepted |
Original final SMTP DATA acknowledgement observed and privately recorded |
failed |
Known failure; fixed reason available |
unknown |
Final acceptance unconfirmed; never assume no message was accepted |
Every receipt has deliveryObserved=false. SMTP acceptance transfers responsibility
to the relay; it does not prove delivery, inbox placement or current transport health.
A source/authority change after acceptance preserves the private acknowledgement
and may refuse the public response. Replaying the same original nonce under current
original-source admission returns its record and never reconnects or resends.
After a lost reply, use Refresh checks and history, retaining the request UUID.
The UI offers a new intentional test only after a correlated accepted or known-failed
receipt. reserved, sent, unknown, invalid completion and failed history reads
remain recovery-only. Do not automatically create a fresh UUID after ambiguity.
Save alert-history.graphql for current own-caller recovery:
query InstallAlertMailHistory($event: String!, $after: String, $limit: Int!) {
installAlertMailTestsPage(eventKind: $event, after: $after, limit: $limit) {
items { id requestId version status reasonCode acceptedAt deliveryObserved }
totalCount nextCursor
}
}
astro --server staging --org ORGANIZATION_GUID api graphql \
--file alert-history.graphql --var event=deploy.failed --var limit=25
Page using nextCursor; the maximum is 50, with cursor admission bound to the original
actor, organization and event. History remains readable to an admitted original
operator after source rotation; the send replay refuses a changed source.
New tests are limited to three per caller and ten per organization per minute. There is one transport attempt. Socket operations are capped at five seconds with a 15-second active SMTP budget. System DNS and PostgreSQL are external synchronous services, so this is not a hard end-to-end deadline. Unknown outcomes stay unknown. Retained receipt history prevents migration rollback; use a forward fix, not history deletion.
See capabilities and the API reference. The whole email transport and alert-fanout scope remains open (#2289).