Introduction & Setup
Relevant source files
The following files were used as context for generating this wiki page:
The resend-rs crate is the official Rust SDK for the Resend API. It provides a structured interface for sending emails, managing contacts, handling webhooks, and automating email sequences. The SDK supports both asynchronous (default) and synchronous (via the blocking feature) execution modes and includes built-in rate limiting to comply with Resend API constraints.
Sources: README.md:1-10, Cargo.toml:1-20, src/lib.rs:1-15
Installation and Requirements
To use the SDK, add resend-rs and tokio to your Cargo.toml. The crate depends on reqwest for HTTP operations and serde for serialization.
cargo add resend-rs
cargo add tokio -F macros,rt-multi-thread
Sources: README.md:12-16, Cargo.toml:130-145
Feature Flags
The crate uses features to toggle between blocking operations and different TLS backends.
| Feature | Description |
|---|---|
blocking | Enables the synchronous client using reqwest/blocking. |
native-tls | Uses the system-native TLS implementation (Enabled by default). |
rustls-tls | Uses the rustls library for TLS. |
Sources: Cargo.toml:22-26, README.md:23-27
Configuration
The SDK requires a RESEND_API_KEY to authenticate requests. You can provide this key through environment variables or directly through the ConfigBuilder.
Environment Variables
The Resend client checks specific environment variables during initialization when using Resend::default().
| Variable | Description | Default |
|---|---|---|
RESEND_API_KEY | The API key required for authentication. | None (Required) |
RESEND_BASE_URL | Overrides the default API address (https://api.resend.com). | https://api.resend.com |
RESEND_RATE_LIMIT | Sets the maximum requests allowed per second. | 9 |
Sources: README.md:29-36, src/config.rs:114-135
Manual Configuration
You can use ConfigBuilder to programmatically configure the client, allowing custom HTTP clients or base URLs for proxying.
let config = ConfigBuilder::new("re_123...")
.base_url("https://proxy.example.com".parse().unwrap())
.build();
let resend = Resend::with_config(config);
Sources: src/config.rs:24-65, src/lib.rs:88-92
Client Architecture
The Resend client serves as the entry point for all API interactions. It holds an Arc<Config> to share configuration and rate limiters across different service modules.
Component Relationship
The following diagram shows how the Resend client aggregates various specialized services.
The Resend client is safe to clone and share across threads. Cloning the client does not create new rate limiters; it clones the underlying pointer to the shared configuration.
Sources: src/lib.rs:7-12, src/config.rs:80-95
Rate Limiting
Resend enforces a limit of 10 requests per second. The SDK implements an internal rate limit of 9 requests per 1.1 seconds by default to prevent 429 Too Many Requests errors.
Rate Limit Flow
The internal rate limiter operates during the send phase of any request.
Note: Rate limiting is only supported in the asynchronous version of the crate. If the server returns a rate limit error despite internal throttling, the SDK parses the ratelimit-reset and ratelimit-limit headers into a detailed Error::RateLimit variant.
Sources: src/lib.rs:1-15, src/config.rs:135-150, src/config.rs:180-205
Error Handling
Operations return a Result<T, Error>. The Error enum categorizes failures into HTTP errors, API-specific errors, or parsing failures.
| Error Variant | Cause |
|---|---|
Http | Network or connection issues via reqwest. |
Resend | API-side validation or authorization errors (e.g., invalid_permission). |
RateLimit | Server-side rate limit exhaustion. |
Parse | Inability to decode the API response (e.g., receiving HTML during an outage). |
Sources: src/lib.rs:215-245, src/error.rs:1-50
Summary
Setting up resend-rs involves adding the dependency, configuring a RESEND_API_KEY, and initializing the Resend client. The architecture promotes safe, concurrent usage through shared configuration and proactive rate limiting. For production environments, developers should use the default asynchronous client to benefit from the built-in throttling mechanisms.
Sources: README.md:1-10, src/lib.rs:35-55