Source: https://cli.nylas.com/guides/pagerduty-email-notifications

# Send Incident Emails from the CLI

Send severity-gated incident email from a shell script with nylas email send. Run it as a lightweight notifier alongside PagerDuty, with no SMTP host, no Postfix daemon, and no mail server to maintain.

Written by [Pouya Sanooei](https://cli.nylas.com/authors/pouya-sanooei) Software Engineer

Reviewed by [Qasim Muhammad](https://cli.nylas.com/authors/qasim-muhammad)

Updated June 9, 2026

> **TL;DR:** Wrap [`nylas email send`](https://cli.nylas.com/docs/commands/email-send) in a shell function, compare the incident severity against a threshold with a single `case` statement, and send only when severity is `critical` or `error`. The payoff: a paging tool decides who wakes up, while the CLI sends the human-readable record — and you will see why splitting those two jobs keeps your alert volume sane.

## Why send an incident email notification from the CLI?

An incident email notification is a severity-gated message that a monitoring script sends when a service crosses an alert threshold. The Nylas CLI sends it with one command: store an API key as an environment variable, call `nylas email send`, and the message goes out over OAuth2 with no SMTP host. Setup takes under 60 seconds.

PagerDuty handles escalation, on-call rotation, and acknowledgement. Email is the durable, searchable record of what happened. The two jobs are different, and the 2017 Google SRE practice of separating “page a human” from “file a record” still holds. Use the CLI for the record half so a stakeholder who is not on the rotation — a support lead, an account manager, a compliance auditor — gets the same context the responder saw, without a PagerDuty seat.

The tool keeps the script small. There is no Postfix daemon on the host, no TLS certificate to renew, and no provider SDK in your alert code. One binary reads the API key and sends.

## How do I gate incident email on severity?

Gate on severity by comparing the incoming level against a threshold before you call the send command. PagerDuty defines four severity values — `critical`, `error`, `warning`, and `info` — in its Events API v2. A `case` statement that returns early for the bottom two levels stops roughly 60% of alert volume from ever reaching an inbox.

The script below reads a severity argument and exits silently for `warning` and `info`. Only `critical` and `error` proceed to the send step. This is the single most effective noise filter you can add, because alert fatigue causes responders to mute or filter channels, and a muted channel is worse than no channel.

```bash
#!/usr/bin/env bash
# notify.sh SEVERITY "SERVICE" "SUMMARY"
set -euo pipefail

SEVERITY="$1"
SERVICE="$2"
SUMMARY="$3"

case "$SEVERITY" in
  critical|error) ;;            # send
  *) echo "skipping email for $SEVERITY"; exit 0 ;;
esac

nylas email send "$NYLAS_GRANT_ID" \
  --to "$ALERT_EMAIL_TO" \
  --subject "[$SEVERITY] $SERVICE incident" \
  --body "Severity: $SEVERITY
Service: $SERVICE
Summary: $SUMMARY" \
  --yes \
  --json
```

The grant ID is the first positional argument to `nylas email send`; the API key comes from `NYLAS_API_KEY` in the environment. Pass the severity as `$1` from whatever triggers the script so the same wrapper serves a cron health check, a webhook handler, or a PagerDuty custom action.

## What should an incident email body include?

An incident email body should answer four questions in the first three lines: what broke, how bad it is, which service, and where to look. RFC 5424, the syslog standard, encodes severity as a number from 0 (emergency) to 7 (debug); mirror that idea by putting the severity word first so a recipient scanning on a phone sees urgency before detail. Keep the body under 15 lines.

Send HTML when you want a clickable runbook link and a colored severity banner. The `--body` flag accepts HTML or plain text, so an anchor tag in an HTML body becomes a real link. The example below builds the body in a heredoc, which keeps the script readable and lets you interpolate the dashboard URL and incident ID without escaping quotes.

```bash
BODY=$(cat <<HTML
<h2 style="color:#c00">[$SEVERITY] $SERVICE</h2>
<p><strong>Summary:</strong> $SUMMARY</p>
<ul>
  <li>Dashboard: <a href="$DASHBOARD_URL">$DASHBOARD_URL</a></li>
  <li>Incident ID: $INCIDENT_ID</li>
  <li>Owner: platform-oncall@example.com</li>
</ul>
HTML
)

nylas email send "$NYLAS_GRANT_ID" \
  --to "$ALERT_EMAIL_TO" \
  --subject "[$SEVERITY] $SERVICE incident" \
  --body "$BODY" \
  --yes \
  --json
```

Do not paste full logs into the body. A two-line error excerpt plus a dashboard link routes faster than 200 lines of stack trace. Logs belong in your observability tool, where search and retention already exist.

## Why tag and track incident sends?

Tag incident sends so you can prove an alert was delivered and correlate it back to the source incident. The `nylas email send` command accepts `--metadata key=value` pairs, up to 50 per message, with five indexed keys (`key1` through `key5`) that support filtering in later API queries. Stamp the PagerDuty incident ID and severity onto every message.

Add `--track-opens` when you need to know a human actually saw a critical page, not just that the message left the server. The flag records an open event, which matters during a postmortem when the question is whether the alert reached anyone before the 30-minute escalation window elapsed. The send below stamps two indexed keys and turns on open tracking.

```bash
nylas email send "$NYLAS_GRANT_ID" \
  --to "$ALERT_EMAIL_TO" \
  --subject "[$SEVERITY] $SERVICE incident" \
  --body "$BODY" \
  --metadata key1="$INCIDENT_ID" \
  --metadata key2="$SEVERITY" \
  --track-opens \
  --track-label "incident" \
  --yes \
  --json
```

Capture the JSON output and write the returned message ID to your incident timeline. That gives support and engineering a way to confirm the notification was sent without searching inboxes by hand.

## How does this run alongside PagerDuty?

Run the CLI script as a second, parallel sink — never as a replacement for the pager. PagerDuty triggers the on-call phone and tracks acknowledgement; the script files the email record at the same instant. Wire it into a PagerDuty webhook extension or a custom event action so both fire from one trigger. PagerDuty's Events API v2 expects a JSON payload with a `severity` field, which maps directly to the `$SEVERITY` argument in the wrapper.

Keep the email recipient list distinct from the on-call rotation. The rotation gets paged; the email list is for people who need the context but not the 3 a.m. phone call. A typical split sends to a shared `incidents@` inbox plus one or two team leads. Review that list monthly — in practice an incident list grows to 12 recipients within a quarter, and an alert nobody can act on is noise.

```bash
# PagerDuty custom action calls this with its payload fields:
./notify.sh "$PD_SEVERITY" "$PD_SERVICE_NAME" "$PD_INCIDENT_TITLE"

# Cron health check reuses the same wrapper:
if ! curl -fsS https://api.example.com/health >/dev/null; then
  ./notify.sh critical "api" "health check failed"
fi
```

Because the wrapper takes plain arguments, the same script serves PagerDuty, a cron probe, and a deploy hook. One notifier, three triggers, no duplicated send logic.

## Next steps

- [Terraform email alerts](https://cli.nylas.com/guides/terraform-email-alerts) — fire notifications from infrastructure plans and applies
- [Send email from Jenkins pipelines](https://cli.nylas.com/guides/jenkins-email-notifications) — build-failure alerts without an SMTP plugin
- [GitHub Actions email notifications](https://cli.nylas.com/guides/github-actions-email-notifications) — CI failure alerts gated on job status
- [Forward email to Mattermost](https://cli.nylas.com/guides/email-to-mattermost-notifications) — route the same alerts into a team channel
- [Forward email to Telegram](https://cli.nylas.com/guides/email-to-telegram-notifications) — push critical pages to a phone
- [Getting started with Nylas CLI](https://cli.nylas.com/guides/getting-started) — install and authenticate in under a minute
- [Command reference](https://cli.nylas.com/docs/commands) — every email send flag and JSON field
- [PagerDuty severity and priority](https://developer.pagerduty.com/docs/severity-and-priority/) — the critical/error/warning/info levels this guide gates on
- [RFC 5424 (Syslog Protocol)](https://www.ietf.org/rfc/rfc5424.txt) — the 0–7 severity scale incident bodies mirror
- [Google SRE Book: Being On-Call](https://sre.google/sre-book/being-on-call/) — why paging and record-keeping are separate jobs
