关于 twilio-communications
面向 Twilio 通信开发的技能指南,整理 SMS、Verify 验证和 TwiML 语音 IVR 的实现模式,并提示常见安全与交付问题。
主要功能
- 01SMS 发送与状态回调
- 02Verify 手机验证与多因素认证
- 03TwiML 交互式语音菜单
- 04凭据、签名与频率限制注意事项
适用场景
- 01发送通知、交易消息和提醒
- 02为注册、登录或交易添加号码验证
- 03构建电话菜单、语音支持或语音信箱
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ davila7/ claude-code-templates --skill twilio-communications安装后在 Claude Code 中输入/twilio-communications确认已加载。
详细介绍
Twilio 通信
模式
SMS 发送模式
使用 Twilio 发送 SMS 消息的基本模式。 涵盖核心内容:电话号码格式、消息投递 和投递状态回调。
关键注意事项:
- 电话号码必须采用 E.164 格式(+1234567890)
- 默认速率限制:每秒 80 条消息(MPS)
- 超过 160 个字符的消息会被拆分(费用也会更高)
- 运营商过滤可能会拦截消息(尤其是发送至美国号码时)
适用场景:['向用户发送通知', '事务性消息(订单确认、发货通知)', '警报和提醒']
from twilio.rest import Client
from twilio.base.exceptions import TwilioRestException
import os
import re
class TwilioSMS:
"""
SMS sending with proper error handling and validation.
"""
def __init__(self):
self.client = Client(
os.environ["TWILIO_ACCOUNT_SID"],
os.environ["TWILIO_AUTH_TOKEN"]
)
self.from_number = os.environ["TWILIO_PHONE_NUMBER"]
def validate_e164(self, phone: str) -> bool:
"""Validate phone number is in E.164 format."""
pattern = r'^\+[1-9]\d{1,14}$'
return bool(re.match(pattern, phone))
def send_sms(
self,
to: str,
body: str,
status_callback: str = None
) -> dict:
"""
Send an SMS message.
Args:
to: Recipient phone number in E.164 format
body: Message text (160 chars = 1 segment)
status_callback: URL for delivery status webhooks
Returns:
Message SID and status
"""
# Validate phone number format
if not self.validate_e164(to):
return {
"success": False,
"error": "Phone number must be in E.164 format (+1234567890)"
}
# Check message length (warn about segmentation)
segment_count = (len(body) + 159) // 160
if segment_count > 1:
print(f"Warning: Message will be sent as {segment_count} segments")
try:
message = self.client.messages.create(
to=to,
from_=self.from_number,
body=body,
status_callback=status_callback
)
return {
"success": True,
"message_sid": message.sid,
"status": message.status,
"segments": segment_count
}
except TwilioRestException as e:
return self._handle_error(e)
def _handle_error(self, error: Twilio
Twilio Verify 模式(2FA/OTP)
使用 Twilio Verify 进行电话号码验证和 2FA。 负责处理验证码生成、发送、速率限制和欺诈防范。
相比自行实现 OTP 的主要优势:
- Twilio 负责管理验证码的生成和过期
- 内置欺诈防范(已帮助客户节省超过 8200 万美元,拦截 7.47 亿次尝试)
- 自动处理速率限制
- 支持多种渠道:SMS、语音、电子邮件、推送、WhatsApp
Google 发现,SMS 2FA 可拦截“100% 的自动化机器人、96% 的批量 网络钓鱼攻击,以及 76% 的定向攻击。”
适用场景:['用户注册时验证电话号码', '双重身份验证(2FA)', '密码重置验证', '高价值交易确认']
from twilio.rest import Client
from twilio.base.exceptions import TwilioRestException
import os
from enum import Enum
from typing import Optional
class VerifyChannel(Enum):
SMS = "sms"
CALL = "call"
EMAIL = "email"
WHATSAPP = "whatsapp"
class TwilioVerify:
"""
Phone verification with Twilio Verify.
Never store OTP codes - Twilio handles it.
"""
def __init__(self, verify_service_sid: str = None):
self.client = Client(
os.environ["TWILIO_ACCOUNT_SID"],
os.environ["TWILIO_AUTH_TOKEN"]
)
# Create a Verify Service in Twilio Console first
self.service_sid = verify_service_sid or os.environ["TWILIO_VERIFY_SID"]
def send_verification(
self,
to: str,
channel: VerifyChannel = VerifyChannel.SMS,
locale: str = "en"
) -> dict:
"""
Send verification code to phone/email.
Args:
to: Phone number (E.164) or email
channel: SMS, call, email, or whatsapp
locale: Language code for message
Returns:
Verification status
"""
try:
verification = self.client.verify \
.v2 \
.services(self.service_sid) \
.verifications \
.create(
to=to,
channel=channel.value,
locale=locale
)
return {
"success": True,
"status": verification.status, # "pending"
"channel": channel.value,
"valid": verification.valid
}
except TwilioRestException as e:
return self._handle_verify_error(e)
def check_verification(self, to: str, code: str) -> dict:
"""
Check if verification code is correct.
Args:
to: Phone number or email that received code
code: The code entered by user
R
TwiML IVR 模式
使用 TwiML 构建交互式语音应答(IVR)系统。 TwiML(Twilio 标记语言)是一种 XML,用于告知 Twilio 接到来电时 应执行的操作。
核心 TwiML 动词:
- :文本转语音
- :播放音频文件
- :收集按键或语音输入
- :连接到另一个号码
- :录制来电者的语音
- :跳转到另一个 TwiML 端点
关键要点:Twilio 会向你的 webhook 发起 HTTP 请求,你返回 TwiML,Twilio 随即执行。由于此过程无状态,因此请使用 URL 参数或会话。
适用场景:['电话菜单系统(按 1 联系销售……)', '自动化客户支持', '带确认功能的预约提醒', '语音信箱系统']
from flask import Flask, request, Response
from twilio.twiml.voice_response import VoiceResponse, Gather
from twilio.request_validator import RequestValidator
import os
app = Flask(__name__)
def validate_twilio_request(f):
"""Decorator to validate requests are from Twilio."""
def wrapper(*args, **kwargs):
validator = RequestValidator(os.environ["TWILIO_AUTH_TOKEN"])
# Get request details
url = request.url
params = request.form.to_dict()
signature = request.headers.get("X-Twilio-Signature", "")
if not validator.validate(url, params, signature):
return "Invalid request", 403
return f(*args, **kwargs)
wrapper.__name__ = f.__name__
return wrapper
@app.route("/voice/incoming", methods=["POST"])
@validate_twilio_request
def incoming_call():
"""Handle incoming call with IVR menu."""
response = VoiceResponse()
# Gather digits with timeout
gather = Gather(
num_digits=1,
action="/voice/menu-selection",
method="POST",
timeout=5
)
gather.say(
"Welcome to Acme Corp. "
"Press 1 for sales. "
"Press 2 for support. "
"Press 3 to leave a message."
)
response.append(gather)
# If no input, repeat
response.redirect("/voice/incoming")
return Response(str(response), mimetype="text/xml")
@app.route("/voice/menu-selection", methods=["POST"])
@validate_twilio_request
def menu_selection():
"""Route based on menu selection."""
response = VoiceResponse()
digit = request.form.get("Digits", "")
if digit == "1":
# Transfer to sales
response.say("Connecting you to sales.")
response.dial(os.environ["SALES_PHONE"])
elif digit == "2":
# Transfer to support
response.say("Connecting you to support.")
response.dial(os.environ["SUPPORT_PHONE"])
elif digit == "3":
# Voicemail
response.say("Please leave a message after
⚠️ 易踩坑之处
| 问题 | 严重程度 | 解决方案 |
|---|---|---|
| 问题 | 高 | ## 在数据库中跟踪退订状态 |
| 问题 | 中 | ## 为临时故障实现重试逻辑 |
| 问题 | 高 | ## 注册 A2P 10DLC(美国要求) |
| 问题 | 严重 | ## 始终验证签名 |
| 问题 | 高 | ## 跟踪每位用户的会话窗口 |
| 问题 | 严重 | ## 切勿将凭据硬编码 |
| 问题 | 中 | ## 同时实现应用层速率限制 |
评论
支持 Markdown