Claude
Skills
Sign in
Back

twilio-email

Included with Lifetime
$97 forever

SendGrid: transactional email, templates Handlebars, event webhooks, suppression, SPF/DKIM/DMARC

Productivityemailsendgridtwiliotransactional

What this skill does


# twilio-email

## Purpose

Enable OpenClaw to implement, operate, and troubleshoot SendGrid (Twilio) transactional email in production:

- Send transactional emails via SendGrid v3 API with correct auth, retries, idempotency, and observability.
- Use Dynamic Templates (Handlebars) safely (escaping, conditionals, loops), versioning templates, and rolling out changes.
- Process SendGrid Event Webhook (delivered/open/click/bounce/spamreport/dropped/deferred) with signature verification and replay protection.
- Manage suppressions (bounces, blocks, spam reports, unsubscribes) and implement list-unsubscribe correctly.
- Configure domain authentication (SPF/DKIM/DMARC), dedicated IPs, IP warming, and bounce/spam handling.
- Integrate with Twilio cluster patterns (rate limiting, webhook retry logic, error taxonomy, cost/throughput tradeoffs).

This skill is for engineers building reliable email delivery pipelines and maintaining them under real traffic, compliance constraints, and deliverability requirements.

---

## Prerequisites

### Accounts & Access

- Twilio SendGrid account with **Mail Send** enabled.
- API key with minimum scopes:
  - `mail.send` (required)
  - `templates.read`, `templates.write` (if managing templates)
  - `suppression.read`, `suppression.write` (if managing suppressions)
  - `eventwebhook.read`, `eventwebhook.write` (if managing webhook settings)
- Verified sender identity or authenticated domain.

### Runtime Versions (tested)

- Node.js **20.11.1** (LTS) + npm **10.2.4**
- Python **3.11.7** (or 3.12.1) + pip **23.3.2**
- Go **1.22.1** (if implementing webhook verifier or high-throughput sender)
- OpenSSL **3.0.2** (Ubuntu 22.04), **3.2.1** (macOS 14), **3.0.12** (Fedora 39)

### SDK / Libraries (recommended)

- Node: `@sendgrid/[email protected]`, `@sendgrid/[email protected]`
- Python: `sendgrid==6.11.0`
- Webhook signature verification:
  - Node: `@sendgrid/[email protected]` (or implement ECDSA verify manually)
  - Go: `github.com/sendgrid/[email protected]` (mail send), custom verifier for webhook

### Network / Infra

- Outbound HTTPS to `https://api.sendgrid.com` (TCP 443).
- Inbound HTTPS endpoint for Event Webhook (publicly reachable) with:
  - TLS 1.2+ (TLS 1.3 preferred)
  - Stable hostname
  - Ability to handle bursts (SendGrid batches events)

### Auth Setup (exact steps)

1. Create API key:
   - SendGrid Dashboard → Settings → API Keys → Create API Key
   - Name: `prod-mail-send-2026-02`
   - Permissions: **Restricted Access** → enable `Mail Send` (and others as needed)
2. Store secret in your secret manager:
   - AWS Secrets Manager: `prod/sendgrid/api_key`
   - GCP Secret Manager: `prod-sendgrid-api-key`
   - Vault: `secret/data/prod/sendgrid`
3. Export locally for testing (never commit):
   ```bash
   export SENDGRID_API_KEY='SG.xxxxxx.yyyyyy'
   ```

---

## Core Concepts

### Transactional vs Marketing

- **Transactional**: triggered by user/system actions (password reset, receipts, alerts). Must be timely, consistent, and typically exempt from marketing consent rules depending on jurisdiction and content.
- **Marketing**: campaigns, newsletters. Use SendGrid Marketing Campaigns; different compliance and suppression semantics.

This skill focuses on **transactional** via `/v3/mail/send` and Dynamic Templates.

### Message Model (SendGrid v3)

A send request is a JSON payload with:

- `from` (must be verified or domain-authenticated)
- `personalizations[]`:
  - `to[]`, `cc[]`, `bcc[]`
  - `dynamic_template_data` (for dynamic templates)
  - `custom_args` (for correlation IDs; appears in event webhook)
- `template_id` (dynamic template)
- `categories[]` (for analytics grouping)
- `asm` (unsubscribe groups)
- `mail_settings`, `tracking_settings`

### Dynamic Templates (Handlebars)

- Templates are stored in SendGrid; you reference `template_id`.
- Handlebars features:
  - `{{var}}` HTML-escaped by default
  - `{{{var}}}` unescaped (dangerous; avoid unless sanitized)
  - `{{#if}}`, `{{#each}}`, `{{else}}`
- Versioning: templates have versions; you can activate a version.

### Event Webhook

SendGrid posts batched JSON events to your endpoint, e.g.:

- `delivered`, `open`, `click`, `bounce`, `dropped`, `deferred`, `spamreport`, `unsubscribe`, `group_unsubscribe`, `group_resubscribe`, `processed`

Key production requirements:

- Verify signature (ECDSA) using SendGrid’s public key.
- Handle retries (SendGrid retries on non-2xx).
- Idempotency: events can be duplicated; dedupe by `(sg_event_id)` or `(sg_message_id, event, timestamp)`.

### Suppressions

Suppression lists prevent delivery:

- Global unsubscribes
- Group unsubscribes (ASM groups)
- Bounces
- Blocks
- Spam reports

Your system must:

- Respect unsubscribes (CAN-SPAM, GDPR/PECR depending on context).
- Provide list-unsubscribe headers for one-click where appropriate.
- Monitor bounce/spam rates; automatically stop sending to bad addresses.

### Deliverability: SPF/DKIM/DMARC

- SPF: authorizes sending IPs for your domain.
- DKIM: cryptographic signature; SendGrid provides CNAME records for domain authentication.
- DMARC: policy for alignment and reporting; start with `p=none`, move to `quarantine`/`reject`.

### Error Taxonomy (SendGrid API)

- 4xx: request/auth issues; do not blindly retry.
- 429: rate limiting; retry with backoff.
- 5xx: transient; retry with jitter.

---

## Installation & Setup

### Official Python SDK — Email (SendGrid)

**Repository:** https://github.com/twilio/twilio-python  
**PyPI:** `pip install twilio sendgrid` · **Supported:** Python 3.7–3.13

```python
# SendGrid is the email layer (separate package, same Twilio ecosystem)
import sendgrid
from sendgrid.helpers.mail import Mail
import os

sg = sendgrid.SendGridAPIClient(api_key=os.environ["SENDGRID_API_KEY"])

message = Mail(
    from_email="[email protected]",
    to_emails="[email protected]",
    subject="Hello from Python!",
    html_content="<strong>Hello!</strong>"
)
response = sg.send(message)
print(response.status_code)  # 202 = queued
```

Source: [sendgrid/sendgrid-python](https://github.com/sendgrid/sendgrid-python) (official SendGrid Python SDK, part of the Twilio family)

### Ubuntu 22.04 / 24.04

Install Node 20, Python 3.11, and tools:

```bash
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg jq python3.11 python3.11-venv python3-pip

# NodeSource Node 20
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

node -v   # v20.11.1 (or later 20.x)
npm -v    # 10.2.4 (or later)
```

Project dependencies (Node):

```bash
mkdir -p services/email-sender
cd services/email-sender
npm init -y
npm install @sendgrid/[email protected] @sendgrid/[email protected] [email protected] [email protected]
```

Python venv:

```bash
mkdir -p services/email-worker
cd services/email-worker
python3.11 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip==23.3.2
pip install sendgrid==6.11.0 fastapi==0.109.2 uvicorn==0.27.1 pydantic==2.6.1
```

### Fedora 39 / 40

```bash
sudo dnf install -y nodejs-20.11.1 npm jq python3.11 python3.11-pip python3.11-virtualenv openssl
node -v
python3.11 -V
```

### macOS 14 (Intel + Apple Silicon)

Using Homebrew:

```bash
brew update
brew install node@20 jq [email protected] openssl@3
echo 'export PATH="/opt/homebrew/opt/node@20/bin:$PATH"' >> ~/.zshrc  # Apple Silicon
echo 'export PATH="/usr/local/opt/node@20/bin:$PATH"' >> ~/.zshrc     # Intel
source ~/.zshrc

node -v
python3.11 -V
```

### Environment Variables (local dev)

Create `.env` (do not commit):

Path: `services/email-sender/.env`

```dotenv
SENDGRID_API_KEY=SG.xxxxxx.yyyyyy
[email protected]
SENDGRID_FROM_NAME=Example Notifications
SENDGRID_TEMPLATE_PASSWORD_RESET=d-2f3c4b5a6d7e8f90123456789abcdeff
SENDGRID_TEMPLATE_RECEIPT=d-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
SENDGRID_EVENT_WEBHOOK_PUBLIC_KEY=MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
EMAIL_ENV=prod
```

Load it (bash):

```bash
set -a
source .env
set +a
```

---

## Key

Related in Productivity