批量发送
POST /v1/email/batches 在一个请求中接受最多 100 个完整的发送载荷。每个条目是一条独立消息,拥有自己的发件人、收件人和内容。使用批量发送可以用更少的 API 请求提交收据、提醒或其他按收件人区分的消息。如果只发送一条消息,请参阅发送邮件。
何时使用哪种方式
- 手头已有的独立消息。 使用批量发送,一个请求全部提交。
- 持续的大批量消息流。 在循环中调用单条发送端点是一种合理的架构,批量发送不会降低单条消息的投递成本,也不会加快投递速度。它改变的是吞吐量,因为批量请求使用 email_batch 请求速率限制策略,而非 email_send 策略,且每个请求最多可包含 100 条消息。
- 向已存储的受众发送一封邮件。 这属于广播,它会将受众解析为收件人,并按联系人进行个性化。
批量发送
请求体是一个 JSON 对象,其 messages 数组包含 1 到 100 个消息对象。每个条目是一个完整、独立的发送请求,拥有自己的 from、to、subject、内容,以及可选的 category、ip_pool_id、标签和元数据。条目的 schema 与单条发送的载荷完全相同,因此发送邮件中的所有内容均按条目适用,包括 category 默认值 marketing 以及通过模板发送。
这包括 scheduled_at,因此一个批次可以混合立即发送和稍后发送的消息,每条消息按各自的时间发出。定时发送中的规则和配额按条目适用,定时条目通过其自身的 ID 取消,与其他定时消息一样。
const batch = await bird.email.sendBatch({
messages: [
{
from: { email: "onboarding@messagebird.dev", name: "Bird" },
to: ["alice@example.com"],
subject: "Your receipt",
html: "<p>Thanks, Alice.</p>",
},
{
from: { email: "onboarding@messagebird.dev", name: "Bird" },
to: ["bob@example.com"],
subject: "Your receipt",
html: "<p>Thanks, Bob.</p>",
},
],
});
for (const item of batch.data) console.log(item.id, item.status);batch = client.email.send_batch(
messages=[
{
"from_": {"email": "onboarding@messagebird.dev", "name": "Bird"},
"to": ["delivered@messagebird.dev"],
"subject": "Hello from Bird",
"html": "<p>My first Bird email.</p>",
},
{
"from_": {"email": "onboarding@messagebird.dev", "name": "Bird"},
"to": ["someone-else@messagebird.dev"],
"subject": "Hello again from Bird",
"text": "My second Bird email.",
},
],
)
for item in batch.data:
print(item.id, item.status)package main
import (
"context"
"fmt"
"log"
"os"
bird "github.com/messagebird/bird-sdk-go"
"github.com/messagebird/bird-sdk-go/option"
)
func main() {
client, err := bird.NewClient(option.WithAPIKey(os.Getenv("BIRD_API_KEY")))
if err != nil {
log.Fatal(err)
}
batch, err := client.Email.SendBatch(context.Background(), bird.EmailSendBatchParams{
Messages: []bird.EmailSendParams{
{
From: "onboarding@messagebird.dev",
To: []string{"alice@example.com"},
Subject: "Hello, Alice",
HTML: "<p>Welcome!</p>",
},
{
From: "onboarding@messagebird.dev",
To: []string{"bob@example.com"},
Subject: "Hello, Bob",
HTML: "<p>Welcome!</p>",
},
},
})
if err != nil {
log.Fatal(err)
}
for _, item := range batch.Data {
fmt.Println(item.Id)
}
}$batch = $bird->email->sendBatch(messages: [
(new EmailMessageSendRequest())
->setFrom((new EmailAddress())->setEmail('onboarding@messagebird.dev')->setName('Bird'))
->setTo([(new EmailAddress())->setEmail('delivered@messagebird.dev')])
->setSubject('Hello from Bird')
->setHtml('<p>My first Bird email.</p>'),
(new EmailMessageSendRequest())
->setFrom((new EmailAddress())->setEmail('onboarding@messagebird.dev')->setName('Bird'))
->setTo([(new EmailAddress())->setEmail('someone-else@messagebird.dev')])
->setSubject('Hello again from Bird')
->setText('My second Bird email.'),
]);
foreach ($batch->getData() ?? [] as $item) {
echo $item->getId(), ' ', $item->getStatus(), "\n";
}bird email send-batch --body-file - <<'JSON'
{
"messages": [
{
"from": {
"email": "noreply@acme.com",
"name": "Acme Support"
},
"to": [
{
"email": "delivered@messagebird.dev",
"name": "Jane Doe"
}
],
"subject": "Your receipt for order #1234",
"text": "Thanks for your purchase! Your receipt is attached."
},
{
"from": {
"email": "noreply@acme.com",
"name": "Acme Support"
},
"to": [
{
"email": "delivered@messagebird.dev",
"name": "John Roe"
}
],
"subject": "Your receipt for order #1235",
"text": "Thanks for your purchase! Your receipt is attached."
}
]
}
JSONcurl -X POST https://us1.platform.bird.com/v1/email/batches \
-H "Authorization: Bearer bk_us1_..." \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"from": "hello@yourdomain.com",
"to": ["delivered@messagebird.dev"],
"subject": "Your receipt",
"html": "<p>Thanks for your order.</p>",
"category": "transactional"
},
{
"from": "newsletter@yourdomain.com",
"to": ["delivered@messagebird.dev"],
"subject": "June product news",
"html": "<p>What shipped this month.</p>",
"category": "marketing"
},
{
"from": "alerts@yourdomain.com",
"to": ["delivered@messagebird.dev"],
"subject": "Usage threshold reached",
"text": "You have used 80% of your quota.",
"category": "transactional"
}
]
}'全有或全无的验证
所有条目在任何条目入队之前都会被验证。如果某条消息未通过验证(字段级验证错误或未验证的发件人域),整个批次将被拒绝并返回 422,不会发送任何消息:修复该条目后重新提交批次。
处理 202 响应
成功的批量请求返回 202 Accepted,按提交顺序每条消息对应一个条目:
代码示例
{
"data": [
{ "id": "em_01ky7q1vmkerwa7fxyycfe5ks1", "status": "accepted", "category": "transactional" },
{ "id": "em_01ky7q1vmkesr9h1y52tkqng9f", "status": "accepted", "category": "marketing" },
{ "id": "em_01ky7q1vmkesyr1z1h4s48jjxm", "status": "accepted", "category": "transactional" }
]
}每个子消息都是一条普通消息:通过其 em_ ID 在 GET /v1/email/messages/{message_id}、收件人和事件端点以及 webhook 中跟踪它,与单独发送时完全一样。同样的异步模型适用,因此 202 表示已被持久接受,按收件人的结果随后送达。
幂等重试
幂等性是可选的。SDK 会为自动重试生成键。对于不同调用之间的重试,或直接使用 HTTP 的情况,请参阅幂等性指南,了解键的复用方式和重放限制。
附件与请求体上限
每个批次条目可以有自己的 attachments,字段约定和单条消息大小预算与单条发送相同(参见附件)。批次整体还有一个额外限制:序列化后的 JSON 请求体上限为 20 MB,超出此大小的请求体将被拒绝并返回 413。Base64 编码的附件计入该上限,因此附件较多的批次会很快达到上限。将它们拆分到多个批次中,或逐条发送。
广播
广播向已存储的受众发送一封邮件。我们在发送开始时将受众的当前成员(排除抑制的部分)解析为收件人列表,每个收件人的联系人属性会填充模板的变量。可以从控制面板、/v1/email/broadcasts 或通过 bird email broadcasts 命令驱动广播。广播提供了完整的操作指南。
后续步骤
- 发送邮件:完整的条目载荷,包括字段、限制以及标签与元数据的区别
- 广播:向已存储的受众发送一封邮件,按联系人个性化
- 类别:marketing 和 transactional,以及各自对抑制策略的影响
- 幂等性:键格式、保留时间和重放语义
- API 参考:完整的批量请求和响应 schema
- 一次 API 调用发送 100 封邮件:一段视频,展示批量发送的过程以及每条消息如何报告状态