Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sending email

aviso has no built-in email trigger. Email is one more per-notification side effect, sent through the generic triggers: you point a trigger at your own SMTP relay or mail endpoint and supply the credentials, and aviso runs the generic client (it ships no managed-service email client).

Two paths, depending on what you have:

  • The command trigger driving a local SMTP client (msmtp, sendmail, mailx). Unix only, but the most direct SMTP route.
  • The webhook trigger posting to your mail gateway’s HTTP API. Cross-platform.

Either way, email is not idempotent: at-least-once delivery means a redelivered notification (for example after a crash before the cursor is checkpointed) sends a second message. required: false keeps an email failure from terminating the listener or forcing a retry-on-restart, but it does not prevent duplicate sends. If duplicate emails are unacceptable, deduplicate on event_type@sequence. See Idempotency.

With the command trigger (SMTP)

msmtp is a small self-contained SMTP client. Put the relay host, port, TLS, and credentials in its own config (~/.msmtprc), so no secret lives in the listener YAML, then template the message from the notification:

listeners:
  - name: ops-email
    event: mars
    triggers:
      - type: command
        command: >
          printf 'From: %s\nTo: %s\nSubject: aviso %s #%s\n\n%s\n'
          "$MAIL_FROM" "$MAIL_TO" "$AVISO_EVENT_TYPE" "$AVISO_SEQUENCE" "$AVISO_NOTIFICATION_JSON"
          | msmtp --from="$MAIL_FROM" "$MAIL_TO"
        env:
          MAIL_FROM: aviso@example.com
          MAIL_TO: ops@example.com
        required: false        # email is non-idempotent; do not force redelivery
        timeout: 30s
        retries: 2             # transient SMTP failures are retried

The notification fields arrive as the AVISO_* environment variables the command trigger injects: AVISO_EVENT_TYPE, AVISO_SEQUENCE, AVISO_NOTIFICATION_JSON, and so on. See the command trigger reference for the full list. Keep credentials out of the YAML: msmtp reads them from its own config, or export them in the environment running aviso and reference them as $VAR in the command (the child inherits the environment). If your host already has a configured MTA, printf ... | sendmail -t or mailx works the same way.

With the webhook trigger (HTTP)

If you reach mail through an HTTP endpoint (a self-hosted gateway, an internal relay’s REST API), use the webhook trigger with a body_template matching the endpoint and the auth header from the environment:

triggers:
  - type: webhook
    url: "https://mail-gateway.example.org/send"
    headers:
      Authorization: "Bearer {{ env.MAIL_TOKEN }}"
      Content-Type: "application/json"
    body_template: >
      {"to": "ops@example.com",
       "subject": "aviso {{ notification.event_type }} #{{ notification.sequence }}",
       "text": "aviso {{ notification.event_type }} #{{ notification.sequence }} fired"}
    required: false

This is cross-platform and goes through the same template engine as the other HTTP triggers. That engine substitutes values verbatim and does not quote or JSON-escape them, so keep substitutions in quoted, scalar positions (event_type, sequence) as above. Avoid dropping a raw {{ notification.payload }} into the body: a string or number payload renders unquoted and produces invalid JSON, while an object or array payload stays valid JSON but changes the field’s type and likely violates the receiver’s schema. If the body needs the full payload, send it through the command trigger using AVISO_PAYLOAD_JSON / AVISO_NOTIFICATION_JSON instead.

From code

These are ordinary triggers, so the same two recipes work from the library builders, not just the CLI YAML: Trigger::command(...) and Trigger::webhook(...) in Rust and the C++ binding, and the equivalent trigger arguments in the Python package. The CLI YAML above is just the declarative form of those builders.