Source: https://cli.nylas.com/guides/terraform-email-alerts

# Send Email Alerts from Terraform

When Terraform changes production infrastructure, the team should hear about it. Terraform has no native email, and wiring an SES topic or a monitoring stack is heavy for a simple 'we just applied' note. A local-exec provisioner running the Nylas CLI does the job: one command emails the team when a resource is created or replaced, with the API key read from the environment so it never lands in state. This guide adds apply-time email alerts to Terraform safely.

Written by [Hazik](https://cli.nylas.com/authors/hazik) Director of Product Management

Updated June 8, 2026

> **TL;DR:** Add a `null_resource` with a `local-exec` provisioner that runs `nylas email send` when infrastructure changes. Read the API key from the `NYLAS_API_KEY` environment variable, never a `tfvars` file or variable that lands in state. Use `triggers` to fire the alert only when the resources you care about change.

Command references used in this guide: [`nylas email send`](https://cli.nylas.com/docs/commands/email-send), [`nylas auth config`](https://cli.nylas.com/docs/commands/auth-config), and [`nylas auth whoami`](https://cli.nylas.com/docs/commands/auth-whoami).

## How do you send email from Terraform?

You send email from Terraform with a `local-exec` provisioner that runs `nylas email send` on the machine running `terraform apply`. Terraform itself has no email resource, so the provisioner is the seam: it shells out after a resource is created, and the CLI sends over API with no SMTP server. The provisioner pattern is documented in the [Terraform local-exec docs](https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec).

Provisioners are a last resort in Terraform's own guidance, so reserve this for genuine notification side effects, not for managing resources. Attach the provisioner to a `null_resource` with a `triggers` map so it re-runs only when the values you name change — for example, a new instance ID or an AMI. That keeps the alert tied to real infrastructure changes rather than firing on every plan.

```hcl
resource "null_resource" "notify" {
  triggers = {
    instance_id = aws_instance.web.id   # re-run when this changes
  }

  provisioner "local-exec" {
    command = <<-EOT
      nylas auth config --api-key "$NYLAS_API_KEY"
      nylas email send --to ops@example.com \
        --subject "Terraform applied: web instance" \
        --body "Instance ${aws_instance.web.id} created in ${var.region}." --yes
    EOT
  }
}
```

## How do you keep the API key out of state?

Read the API key from an environment variable in the provisioner's shell — `$NYLAS_API_KEY` — and never pass it through a Terraform variable. Anything you put in a `tfvars` file or a `variable` can end up in the state file, which Terraform stores in plaintext unless your backend encrypts it. The environment-variable path keeps the secret out of state entirely.

For teams, source the key from a secrets manager before running Terraform, or have the runner export it from Vault or a CI secret. This follows the same rule as any infrastructure credential: secrets live in a manager, not in `tfvars` and not in committed HCL. If your state ever did capture a secret, rotate it, because remote state is readable by anyone with backend access.

```bash
# Export the key in the environment before apply (e.g. from Vault or CI)
export NYLAS_API_KEY="$(vault kv get -field=key secret/nylas)"
terraform apply

# The provisioner reads $NYLAS_API_KEY — it never enters tfvars or state.
```

## When should you use this versus a monitoring stack?

Use the provisioner for lightweight, apply-time notifications: “we just replaced the load balancer,” “a new environment is up.” It's a few lines and runs where Terraform already runs, so there's no extra infrastructure to maintain. For one team that wants to know when an apply touched production, that's the right weight.

Reach for a real monitoring stack — CloudWatch alarms, an SNS topic, a paging tool — when you need ongoing runtime alerts, deduplication, escalation, or an audit trail. The provisioner fires once per apply and has no retry semantics, so it's a notifier, not an alerting system. Match the tool to the need: apply-time note here, operational alerting there.

## Next steps

- [Send email from a bash script](https://cli.nylas.com/guides/send-email-from-bash-script) — the command the provisioner runs
- [GitLab CI email notifications](https://cli.nylas.com/guides/gitlab-ci-email-notifications) — notify from the pipeline instead
- [Automate email reports](https://cli.nylas.com/guides/automate-email-reports-terminal) — scheduled summaries over API
- [Handle email API outages](https://cli.nylas.com/guides/handle-email-api-outages) — make notifications resilient
- [Full command reference](https://cli.nylas.com/docs/commands) — every flag and subcommand documented
