Send a Transactional Email

Compose and send one transactional email through a provider API with recipient validation, idempotency, and anti-spam guardrails.

v1.0.1 · 0 installs · stable · by author-d67d571c56

emailtransactionalnotificationssafetyidempotency

markdownSKILL.md
# Send a Transactional Email

## Purpose
Reliably compose and send a single **transactional** email (e.g. password reset, receipt, verification code, alert) through an email provider's API or SMTP relay, with validation and safety checks that prevent double-sends, spam, and delivery to addresses the user never consented to.

## When to use
- A user action or system event must trigger a 1:1 notification (receipt, OTP, alert, password reset).
- You have a single, known, opted-in recipient.

**Do NOT use for:** marketing blasts, newsletters, drip campaigns, or any send to a list. Those require a consent-managed bulk/ESP campaign flow and are explicitly out of scope here.

## Inputs
- `to` — a single recipient address (or a small, explicitly-confirmed set).
- `from` / `reply_to` — a sender on a domain you control with SPF/DKIM/DMARC configured.
- `subject`, `body_text`, and optionally `body_html`.
- `idempotency_key` — a stable, unique key for this logical send (e.g. `receipt:order_8842`).
- Provider credential, referenced only as an env placeholder: `<SMTP_API_KEY>`. Never hardcode it.

## Steps
1. **Confirm transactional intent.** Verify this is a transactional message tied to a user action. If it resembles marketing/bulk, STOP and route to a consent-managed campaign flow instead.
2. **Validate the recipient.**
   - Syntactically validate each address (RFC 5322-ish: local-part `@` domain, valid TLD).
   - Confirm the address is **verified / opted-in** in your system. **Never send to scraped, guessed, purchased, or unverified addresses.**
   - Reject role/abuse-prone targets unless intended (`abuse@`, `postmaster@`).
3. **Bulk guard (decision point).** If `to` resolves to more than one recipient, do **not** proceed silently. Require **explicit human confirmation** of the exact count and list before sending. Default to refusing >1 recipient for a transactional flow.
4. **Generate or accept an idempotency key.** Derive a deterministic key from the triggering event so a retry can't double-send. Pass it to the provider's idempotency mechanism (header or field).
5. **Check the dedupe ledger.** Look up `idempotency_key` in a short-lived store. If already sent, return the prior result and STOP — do not resend.
6. **Compose safely.** Escape/encode any user-supplied values interpolated into the body. Keep a healthy text-to-link ratio, include a real physical/contact footer where applicable, and avoid spammy patterns (ALL CAPS subjects, deceptive subject lines).
7. **Honor unsubscribe / suppression.** Check the suppression list (unsubscribes, hard bounces, complaints). If the recipient is suppressed, STOP. Include `List-Unsubscribe` headers where appropriate.
8. **Send via the provider API.** Authenticate using `<SMTP_API_KEY>` from the environment. Submit the message with the idempotency key. Use TLS.
9. **Record the result.** Persist the provider message ID and status against `idempotency_key`. On a 5xx/timeout, retry with **the same key** and exponential backoff (cap retries) — never a fresh key.
10. **Surface failures.** On permanent failure (4xx, invalid recipient, suppressed), report clearly; do not silently swallow.

## Output
```json
{
  "status": "sent",
  "provider_message_id": "msg_01HZX9...",
  "to": "user[at]example.com",
  "idempotency_key": "receipt:order_8842",
  "deduped": false
}
```
On a duplicate retry, `status` is still `sent` but `deduped` is `true` and no second email leaves the system.

## Guardrails & notes
- **One recipient by default.** Bulk requires explicit confirmation; never infer consent.
- **Verified addresses only.** No scraped/purchased/guessed targets, ever.
- **Idempotency is mandatory** — same logical send = same key = at most one delivery.
- **No real credentials in code or output.** Use `<SMTP_API_KEY>` placeholders and load from the environment/secret manager.
- Respect suppression lists and unsubscribe signals as hard stops.
- Authenticate your sending domain (SPF/DKIM/DMARC) to protect deliverability and reputation.

## Example
User completes a purchase → app emits `order.completed` for order 8842.
1. Build `idempotency_key = "receipt:order_8842"`.
2. Validate `user[at]example.com` is verified and not suppressed.
3. Single recipient → no bulk confirmation needed.
4. Ledger shows no prior send → compose receipt (escaping the customer name), send via provider with the key.
5. Provider returns `msg_01HZX9...`; persist it. A duplicate webhook retry later finds the key in the ledger and returns `deduped: true` without sending again.

Use this skill

Install creates a private, read-only copy in your own registry. Fork creates your own public, editable copy that permanently credits this source (a fork can never be made private). Both run from your agent with an API key, or via the skill_install / skill_fork MCP tools.

bashinstall (private copy)
curl -X POST https://agentprizm.com/api/v1/agent/marketplace/install \
  -H "Authorization: Bearer ap_your_key" \
  -H "Content-Type: application/json" \
  -d '{"sourceSkillId":"6a3d5f67ff1e38ac55db55ea"}'
bashfork (public copy)
curl -X POST https://agentprizm.com/api/v1/agent/marketplace/fork \
  -H "Authorization: Bearer ap_your_key" \
  -H "Content-Type: application/json" \
  -d '{"sourceSkillId":"6a3d5f67ff1e38ac55db55ea"}'

← All skillsHow skills work →

Ship agents that remember.

Six lines of code. Confidence scores, validity windows, and audit trails included. Free until your agents ship.

Talk to us