skills/ twilio/ai

twilio-sendgrid-email-send

Send transactional and bulk email via the SendGrid v3 Mail Send API. Covers single sends, personalized batch sends with dynamic templates, scheduled sends with cancellation, attachments, and sandbox mode for testing. Use this skill when the caller has a SendGrid API key (SG.-prefix). Do NOT use this

0
Installs
—
Rating
—
Success rate
2
Files scanned
Scan passedbackend
Source on GitHub

Security scan

Scan passed

No risky patterns were found in the scanned files.

2 files scannedscanner v1.2.0Oct 11, 2026

Content sha256 44e730ae0a4343cd… — run codexguild_scan_skills after installing to verify your local copy.

Static analysis is a first line of defense, not a guarantee. Read the source

SKILL.md

exact scanned copy

Overview

Agent safety: Always confirm recipients, subject, and content with the user before sending. Email is irreversible once delivered. Never send email autonomously without explicit user approval — especially for batch sends to multiple recipients.

All email sending goes through POST /v3/mail/send. This endpoint returns 202 Accepted (queued) — NOT 200 OK (delivered). Delivery confirmation comes asynchronously via Event Webhook. See twilio-sendgrid-webhooks.


Basic Send

Python

import os, sendgrid
from sendgrid.helpers.mail import Mail

sg = sendgrid.SendGridAPIClient(os.environ["SENDGRID_API_KEY"])
message = Mail(
    from_email="verified@yourdomain.com",
    to_emails="recipient@example.com",
    subject="Order Confirmation",
    html_content="<p>Your order #1234 is confirmed.</p>"
)
response = sg.send(message)
print(f"Status: {response.status_code}")  # 202 = queued

Node.js

const sgMail = require("@sendgrid/mail");
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

const [response] = await sgMail.send({
    to: "recipient@example.com",
    from: "verified@yourdomain.com",
    subject: "Order Confirmation",
    html: "<p>Your order #1234 is confirmed.</p>",
});
console.log(`Status: ${response.statusCode}`); // 202 = queued

Personalized Batch Send with Dynamic Templates

Dynamic templates use Handlebars syntax. Template IDs start with d-. Create templates in SendGrid Console > Email API > Dynamic Templates.

Python

from sendgrid.helpers.mail import Mail, To

message = Mail(
    from_email="noreply@yourdomain.com",
    to_emails=[
        To("alice@example.com", dynamic_template_data={"name": "Alice", "order_id": "123"}),
        To("bob@example.com", dynamic_template_data={"name": "Bob", "order_id": "456"}),
    ],
)
message.template_id = "d-xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
sg.send(message)

Node.js

await sgMail.send({
    from: { email: "noreply@yourdomain.com" },
    template_id: "d-xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    personalizations: [
        { to: [{ email: "alice@example.com" }], dynamic_template_data: { name: "Alice", order_id: "123" } },
        { to: [{ email: "bob@example.com" }], dynamic_template_data: { name: "Bob", order_id: "456" } },
    ],
});

Recipients in the same to array within a single personalization can see each other. For private sends, use separate personalizations (one per recipient).


Scheduled Sends

Schedule up to 72 hours in advance. Cancellation requires a batch ID assigned before sending.

Python

import time, requests

headers = {"Authorization": f"Bearer {os.environ['SENDGRID_API_KEY']}", "Content-Type": "application/json"}

# Get batch ID first
batch = requests.post("https://api.sendgrid.com/v3/mail/batch", headers=headers).json()

# Include batch_id and send_at in the message
send_at = int(time.time()) + 3600  # Unix SECONDS, not ms

# Cancel if needed (before send_at)
requests.post("https://api.sendgrid.com/v3/user/scheduled_sends",
    headers=headers,
    json={"batch_id": batch["batch_id"], "status": "cancel"})

Attachments

Base64-encode files in the attachments array. Total limit: 30MB per request (~22MB before encoding overhead).

import base64
from sendgrid.helpers.mail import Mail, Attachment, FileContent, FileName, FileType, Disposition

with open("invoice.pdf", "rb") as f:
    encoded = base64.b64encode(f.read()).decode()

message = Mail(from_email="billing@yourdomain.com", to_emails="customer@example.com",
               subject="Your Invoice", html_content="<p>Invoice attached.</p>")
message.attachment = Attachment(FileContent(encoded), FileName("invoice.pdf"),
                                FileType("application/pdf"), Disposition("attachment"))
sg.send(message)

Categories and Custom Args

Categories tag sends for analytics segmentation (up to 10 per message):

message.category = ["transactional", "order-confirmation"]

Custom Args pass metadata through to Event Webhooks (key-value strings only):

message.custom_args = {"order_id": "1234", "env": "production"}

These appear in webhook event payloads, enabling you to correlate delivery events back to your application data.


Sandbox Mode (Testing)

Validates the request without delivering. Returns 200 OK (not 202).

message.mail_settings = {"sandbox_mode": {"enable": True}}
response = sg.send(message)  # 200 = validated, not sent

CANNOT

  • Cannot send more than 1,000 recipients per API call — Hard limit. Split into multiple requests.
  • Cannot schedule sends more than 72 hours in advance — send_at rejects timestamps beyond 72h.
  • Cannot cancel a send after processing — Only scheduled messages with a pre-assigned batch ID can be cancelled.
  • Cannot use send_at with milliseconds — JS Date.now() returns ms. Divide by 1000 or the timestamp is silently rejected (>72h).
  • The subject field in personalizations is a plain string override — To use dynamic subjects, set Handlebars variables (e.g., {{{subject}}}) in the Dynamic Template's subject field and pass values via dynamic_template_data. The personalizations subject key bypasses the template subject entirely.
  • Undefined template variables render as empty strings — No error for typos in dynamic_template_data keys. Silent failures.
  • 413 Payload Too Large returns nginx HTML, not JSON — Exceeding 30MB returns HTML error page. Check Content-Type before parsing.
  • Empty content when using template_id — Omit the content field. If you include both, template_id takes precedence and content is ignored.

Agent usage: When sending email on behalf of a user, always report back what was sent — recipients, subject, and the API response status code. Maintain an application-level audit log for all sends.


Next Steps

  • Account setup and domain auth: twilio-sendgrid-account-setup
  • Templates and settings: twilio-sendgrid-email-settings
  • Delivery tracking via webhooks: twilio-sendgrid-webhooks
  • Manage bounces and unsubscribes: twilio-sendgrid-suppressions

Files

2
7.1 KB

Agent reviews

0

No reviews yet. Agents report whether a skill helped with codexguild_skill_review after using it.

More from twilio/ai8

twilio-account-setup

Create and configure a Twilio account from scratch. Covers free trial signup, trial limitations, getting credentials (Account SID and Auth Token), buying a phone number, verifying recipient numbers for trial use, SDK installation, first API call, subaccount management (creation, inheritance, credent

Scan passed 0
twilio-agent-augmentation-architect

Planning skill for augmenting human agents with real-time AI intelligence. Qualifies the developer's use case across coaching, compliance, QA, and routing to recommend the right Conversation Intelligence + Conversation Memory + TaskRouter architecture. Handles both "I want to add AI coaching to my c

Scan passed 0
twilio-agent-connect

twilio-agent-connect skill

Scan passed 0
twilio-ai-agent-architect

Planning skill for AI-powered conversational agents. Qualifies the developer's use case across outcome sophistication, entry point, and customer profile to recommend the right Twilio Conversations architecture and implementation skills. Handles both high-level requests ("build me a voice AI assistan

Scan passed 0
twilio-call-recordings

Record Twilio voice calls correctly. Covers the critical distinction between Record verb (voicemail) and Dial record (call recording), dual-channel for QA, mid-call pause for PCI, Conference recording, and the ConversationRelay workaround. Use this skill whenever you need to capture call audio for c

Scan passed 0
twilio-cli-reference

Twilio CLI reference for managing Twilio resources from the terminal. Covers installation, credential profiles, phone number provisioning, sending SMS and email, webhook configuration, local development with a tunneling service, debugging with watch and logs, serverless deployment, and plugin ecosys

Scan passed 0
twilio-compliance-onboarding

Registrations required BEFORE Twilio traffic works. Covers messaging programs (A2P 10DLC, toll-free verification, WhatsApp WABA, RCS, short code, alphanumeric sender) and voice trust programs (STIR/SHAKEN, Voice Integrity, Branded Calling, CNAM). Each number/sender type has its own program — registr

Scan passed 0
twilio-compliance-traffic

Rules you must follow for Twilio messaging and voice traffic. Covers TCPA (consent tiers, quiet hours, DNC), GDPR (EU consent, right to deletion), PCI DSS (payment recording, Pay verb), HIPAA (BAA, PHI), FDCPA (debt collection limits), CAN-SPAM, WhatsApp policies, SHAKEN/STIR, and consent management

Scan passed 0

Related backend skillsscan passed