短信的打开率高达 98%,远超邮件。对于需要向海外用户发送验证码(OTP)、系统通知、营销消息的开发者来说,一个稳定、覆盖广、接入简单的国际短信平台至关重要。
SUBMAIL (赛邮云通信)是国内领先的通信云服务商,其国际短信服务具备以下优势:
sms/unionsend),单一接口搞定全球用户在开始编码之前,你需要完成以下准备工作:
1.注册SUBMAIL账号
前往 mysubmail.com 注册开发者账号。
2.创建国际短信应用
登录控制台后,进入“应用集成”→“国际短信”,创建一个新应用,获取:
AppID:应用唯一标识AppKey:应用密钥(相当于密码,请妥善保管)3.申请短信模板(可选)
需要使用模板发送(internationalsms/xsend),需要提前在控制台创建并审核通过模板。本教程使用自定义内容发送(internationalsms/send),无需提前建立模板。
SUBMAIL API 基于标准 HTTP,Python 只需安装 requests 库:
pip install requestshttps://api-v4.mysubmail.com/internationalsms/send请求参数说明:
appid (必需):你的国际短信应用 AppIDsignature (必需):当 sign_type=normal 时,直接填写 AppKey 明文to (必需):收件人手机号,必须携带国际区号,格式如 +1xxxxxxxxxx (美国)、+44xxxxxxxxxx (英国)content (必需):短信正文内容sign_type (可选):认证类型, normal (明文,适合测试)或 md5(生产环境推荐)import requests
import os
# ======== 配置区 ========
# 推荐从环境变量读取,避免硬编码密钥
APPID = os.environ.get("SUBMAIL_APPID", "your_appid_here")
APPKEY = os.environ.get("SUBMAIL_APPKEY", "your_appkey_here")
API_URL = "https://api-v4.mysubmail.com/internationalsms/send"
def send_international_sms(to: str, content: str) -> dict:
"""
发送国际短信(normal 明文认证模式)
参数:
to - 收件人手机号,需带国际区号,如 +1xxxxxxxxxx
content - 短信正文内容
返回:
API 响应的 JSON 字典
"""
payload = {
"appid": APPID,
"signature": APPKEY, # normal 模式直接传 appkey
"to": to,
"content": content,
"sign_type": "normal"
}
try:
response = requests.post(API_URL, data=payload, timeout=10)
response.raise_for_status()
result = response.json()
return result
except requests.exceptions.Timeout:
return {"error": "请求超时,请检查网络连接"}
except requests.exceptions.RequestException as e:
return {"error": f"请求失败:{str(e)}"}
# ======== 示例调用 ========
if __name__ == "__main__":
# 发送给美国号码
result = send_international_sms(
to="+11234567890",
content="Your verification code is 8866. Valid for 5 minutes. --SUBMAIL"
)
print("API 响应:", result)
import requests
import hashlib
import os
APPID = os.environ.get("SUBMAIL_APPID", "your_appid_here")
APPKEY = os.environ.get("SUBMAIL_APPKEY", "your_appkey_here")
API_URL = "https://api-v4.mysubmail.com/internationalsms/send"
def gettimestamp():
res = requests.get('https://api-v4.mysubmail.com/service/timestamp').json()
timestamp = str(res['timestamp'])
return timestamp
def build_md5_signature(params: dict) -> str:
"""
构建 SUBMAIL MD5 数字签名
签名规则:appid + appkey + 排序后的参数字符串 + appid + appkey,再取 MD5
"""
# 过滤掉 sign_type 参数后排序
filtered = {k: v for k, v in params.items()}
sorted_keys = sorted(filtered.keys())
param_str = "&".join(f"{k}={filtered[k]}" for k in sorted_keys)
raw = f"{APPID}{APPKEY}{param_str}{APPID}{APPKEY}"
print(raw)
m = hashlib.md5()
b = raw.encode(encoding='utf-8')
m.update(b)
return m.hexdigest()
def send_sms_with_md5(to: str, content: str) -> dict:
"""发送国际短信(MD5 签名认证模式)"""
params = {
"appid": APPID,
"to": to,
"content": content,
"timestamp":gettimestamp(),
"sign_type": "md5",
}
# 生成签名
signature = build_md5_signature(params)
payload = {
**params,
"signature": signature,
}
response = requests.post(API_URL, data=payload, timeout=10)
return response.json()
if __name__ == "__main__":
result = send_sms_with_md5(
to="+447911123456", # 英国号码示例
content="Hello! Your order has been confirmed. Track it at: https://example.com"
)
print("API 响应:", result)如果你的用户群同时包含国内和国际用户,SUBMAIL 提供 sms/unionsend 接口,一次请求自动按国家路由:
UNION_API_URL = "https://api-v4.mysubmail.com/sms/unionsend"
def send_union_sms(to: str, content: str,
domestic_appid: str, domestic_appkey: str,
inter_appid: str, inter_appkey: str) -> dict:
"""
国内+国际联合发送(仅支持 normal 认证模式)
"""
payload = {
"appid": domestic_appid, # 国内短信 AppID
"signature": domestic_appkey, # 国内短信 AppKey
"inter_appid": inter_appid, # 国际短信 AppID
"inter_signature": inter_appkey, # 国际短信 AppKey
"to": to,
"content": content,
"sign_type": "normal"
}
response = requests.post(UNION_API_URL, data=payload, timeout=10)
return response.json()SUBMAIL API 的响应结构如下:
成功响应示例:
{
"status": "success",
"send_id": "abcdef1234567890",
"fee": 1,
"sms_credits": 99
}失败响应示例:
{
"status": "error",
"code": "1xx",
"msg": "No recipient"
}常见错误码:
103:AppID 或 AppKey 错误,请检查配置104:签名验证失败,检查 MD5 签名算法108:短信额度不足,请前往控制台充值401:收件人号码格式错误,国际号码需要带 + 区号402:内容违规,检查短信正文是否包含敏感词建议在生产代码中统一处理错误:
def handle_response(result: dict):
if result.get("status") == "success":
print(f"✅ 发送成功,send_id: {result['send_id']}")
else:
print(f"❌ 发送失败,错误码: {result.get('code')},原因: {result.get('msg')}")🔐绝对不要将 AppKey 硬编码在代码里,应使用环境变量:
# Linux / macOS
export SUBMAIL_APPID="your_appid"
export SUBMAIL_APPKEY="your_appkey"# Python 中读取
import os
APPID = os.environ["SUBMAIL_APPID"]
APPKEY = os.environ["SUBMAIL_APPKEY"]如果使用 Docker 或 Kubernetes,通过 Secret 注入环境变量;如果使用云函数,通过平台的密钥管理服务存储。
需要批量发送给多个国际用户时,建议:
internationalsms/batchsend 接口,单次请求支持最多10,000个号码| 步骤 | 要点 |
|---|---|
| 注册账号 | |
| 获取凭证 | AppID + AppKey |
| 安装依赖 | pip install requests |
| 发送接口 | https://api-v4.mysubmail.com/internationalsms/send |
| 认证方式 | 测试用 normal,生产用 MD5 |
| 号码格式 | 必须带+国际区号 |
SUBMAIL 的 REST API 设计简洁,Python 接入门槛极低,通常 20 分钟内即可完成第一条国际短信的发送。结合 OTP 验证码、订单通知、营销触达等场景,可以大幅提升用户触达效率。
了解更多:
微信公众号
赛邮微博