Batch Email Sending
Relevant source files
The following files were used as context for generating this wiki page:
Batch Email Sending allows you to send multiple emails in a single API request. This feature improves efficiency by reducing the number of HTTP calls required to distribute high volumes of messages.
The Resend Python SDK provides the Batch class to handle these operations. It supports both synchronous and asynchronous execution modes. You can send a list of email objects, each containing its own recipients, subject, and content.
Architecture and Data Flow
The batch sending system processes a list of SendParams objects. Each object represents a single email within the batch. The SDK serializes this list and transmits it to the /emails/batch endpoint via a POST request.
The following sequence diagram illustrates the flow of a batch send request between the application and the Resend API.
Input Parameters
The Batch.send method accepts a list of email parameters and an optional configuration object.
| Parameter | Type | Required | Description |
|---|---|---|---|
params | List[resend.Emails.SendParams] | Yes | A list of email objects containing from, to, subject, and content (html or text). |
options | resend.Batch.SendOptions | No | Optional settings such as idempotency_key or batch_validation mode. |
Sources: resend/emails/_batch.py:27-51, resend/emails/_emails.py:246-271
Validation Modes
The batch system supports different validation behaviors through the batch_validation option. This determines how the API handles individual failures within a large request.
- Strict Mode: The API validates all emails in the batch. If any email fails validation, the entire batch request fails.
- Permissive Mode: The API processes valid emails and identifies invalid ones in an
errorsarray. This allows successful delivery of most messages even if some contain errors.
The following flowchart demonstrates the decision logic for permissive validation.
Implementation Examples
Synchronous Batch Sending
You use resend.Batch.send() to transmit a list of emails. Each email can have unique attachments, headers, or tags.
params = [
{
"from": "onboarding@resend.dev",
"to": ["user1@example.com"],
"subject": "First Message",
"html": "<strong>Content 1</strong>",
},
{
"from": "onboarding@resend.dev",
"to": ["user2@example.com"],
"subject": "Second Message",
"text": "Content 2",
}
]
response = resend.Batch.send(params)
for email in response["data"]:
print(f"Sent email ID: {email['id']}")
Sources: examples/batch_email_send.py:11-37, tests/batch_emails_test.py:16-36
Asynchronous Batch Sending
The SDK provides send_async for non-blocking operations. This is useful for applications using asyncio.
import asyncio
import resend
async def main():
params = [{"from": "src@dev.com", "to": "dst@dev.com", "subject": "Async", "html": "hi"}]
response = await resend.Batch.send_async(params)
print(response)
asyncio.run(main())
Sources: resend/emails/_batch.py:75-92, examples/async/batch_email_send_async.py:11-38
Data Structures
The system uses specific TypedDict classes to ensure type safety.
SendOptions
Configures the behavior of the batch request.
idempotency_key(Optional[str]): A unique string to prevent duplicate processing of the same request.batch_validation(Optional[Literal["strict", "permissive"]]): Defines how the API handles malformed emails in the batch.
SendResponse
Contains the result of the batch operation.
data(List[BatchEmailResponse]): A list of objects containing theidfor each successfully processed email.errors(NotRequired[List[BatchError]]): A list of errors encountered during permissive validation, including theindexof the failed email and amessage.
Sources: resend/emails/_batch.py:12-25, tests/batch_emails_test.py:120-145
Summary
Batch Email Sending in the Resend Python SDK provides a structured way to handle bulk deliveries. By using the Batch module, you can optimize network performance and choose between strict or permissive validation strategies. The SDK handles the mapping of individual email parameters to a unified batch payload, supporting both standard and asynchronous Python workflows.