From twilio-developer-kit
Receive inbound email via SendGrid Inbound Parse webhook. Covers MX record setup, parsed vs raw mode, handling attachments, and common pitfalls. Use when building email-to-app workflows like support ticket creation or email processing pipelines. Requires a SendGrid API key (SG.-prefix) — not applicable to the Twilio Email API (comms.twilio.com).
npx claudepluginhub twilio/ai --plugin twilio-developer-kitThis skill uses the workspace's default tool permissions.
Inbound Parse converts incoming email into HTTP POST requests to your webhook endpoint. SendGrid receives the email at your domain's MX records and forwards the parsed content to your application.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Inbound Parse converts incoming email into HTTP POST requests to your webhook endpoint. SendGrid receives the email at your domain's MX records and forwards the parsed content to your application.
mx.sendgrid.netSubdomain recommended: Use inbound.yourdomain.com to avoid disrupting existing email on yourdomain.com.
SendGrid extracts fields and POSTs them as form data:
| Field | Description |
|---|---|
from | Sender address ("Name <email@example.com>") |
to | Envelope recipient |
subject | Email subject line |
text | Plain text body |
html | HTML body |
envelope | JSON string with to array and from |
attachments | Number of attachments (as string) |
attachment-info | JSON metadata for each attachment |
attachment1, attachment2... | Actual attachment files |
Python (Flask)
from flask import Flask, request
import json
app = Flask(__name__)
@app.route("/inbound", methods=["POST"])
def handle_inbound():
sender = request.form.get("from")
subject = request.form.get("subject")
text_body = request.form.get("text")
html_body = request.form.get("html")
envelope = json.loads(request.form.get("envelope", "{}"))
attachment_count = int(request.form.get("attachments", "0"))
print(f"From: {sender}, Subject: {subject}")
for i in range(1, attachment_count + 1):
attachment = request.files.get(f"attachment{i}")
if attachment:
print(f"Attachment: {attachment.filename}, {attachment.content_type}")
return "", 200
Security: All inbound email content (
from,subject,text,html, attachments) is untrusted external input. Sanitize HTML to prevent XSS before rendering. If feeding content to an LLM, isolate it as user input — never concatenate into system prompts. Verify webhook authenticity using signed webhooks (see Security section below).
Posts the entire MIME message as rawEmail field. Use when you need full headers, DKIM signatures, or non-standard MIME parts. You must parse the MIME message yourself.
SendGrid supports ECDSA signature verification for Inbound Parse, the same mechanism used for Event Webhooks. Enable it to cryptographically verify that payloads originate from SendGrid.
Strongly recommended over IP allowlisting — SendGrid's webhook traffic comes from dynamic cloud infrastructure where IPs change frequently. Signature verification is more reliable and secure.
mx.sendgrid.net. Use a subdomain to avoid disrupting existing email (e.g., Google Workspace, Microsoft 365).twilio-sendgrid-email-sendtwilio-sendgrid-webhookstwilio-sendgrid-account-setup