Resend for Developers: A Guide to Sending Email with Python
Resend is an email API built for developers. It offers a modern developer experience with official SDKs, a clean API, and first-class…
Resend for Developers: A Guide to Sending Email with Python

Resend is an email API built for developers. It offers a modern developer experience with official SDKs, a clean API, and first-class support for building emails with code. This post provides a technical overview of Resend, focusing on its Python SDK, operational considerations, and how it compares to other email delivery services.
This post covers:
- What Resend is (and what it’s not)
- How to send email using the Resend Python SDK
- Operational considerations (deliverability, tracking, webhooks)
- A feature and pricing comparison against common alternatives
What Resend is Good At
Resend’s core strengths include:
- Fast Integration: Official REST, SMTP, and SDK bindings simplify integration into existing codebases. The Send and Batch APIs are intentionally lightweight, allowing engineering teams to quickly implement transactional emails like password resets and receipts.
- Developer-Oriented Features: Primitives for scheduling, batch sending, open/link tracking, webhooks, and suppression handling are exposed as first-class API concepts. This allows you to build observability and automation without third-party middleware.
- Deliverability-Centric Controls: Resend provides DNS-based authentication (DKIM/SPF/DMARC), suppression lists, bounce/complaint feedback loops, and optional dedicated IPs for hardening deliverability as your email volume grows.
- Multi-Region Sending: You can route traffic through different geographies to reduce latency for a global user base while using a single Resend account.
Resend is not a full marketing automation suite like Mailchimp or HubSpot. While it has marketing and broadcast capabilities, it is optimized for engineering workflows rather than CRM-first campaign orchestration.
Quickstart: Sending Email with the Resend Python SDK
Resend provides a simple “send in minutes” flow for Python.
1) Install
pip install resend python-dotenv
2) Set Your API Key
Store your key in an environment variable:
import os
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
RESEND_API_KEY=os.getenv("RESEND_API_KEY")
from_email=os.getenv("FROM_EMAIL")
to_email=os.getenv("TO_EMAIL")
ATTACHMENT_PATH=os.getenv("ATTACHMENT_PATH")
IMAGE_PATH=os.getenv("IMAGE_PATH")
3) Send a Basic Email
The Resend SDK for Python is designed to automatically use the RESEND_API_KEY environment variable if it is set, so you don’t need to set it in your code explicitly.
Here is how you can send a basic email. Note that the "from" address should be a domain you have verified with Resend.
import os
import resend
from resend.errors import ResendError
try:
params = {
"from": from_email,
"to": to_email,
"subject": "Hello from Python",
"html": "<strong>It works!</strong>",
}
email = resend.emails.send(params)
print(email)
except ResendError as e:
print(f"Error sending email: {e}")
4) Sending Batch Emails
The batch method allows you to send multiple emails with a single API call.
import os
import resend
from resend.errors import ResendError
try:
params = [
{
"from": from_email,
"to": to_email,
"subject": "Hello User 1",
"html": "<strong>Welcome!</strong>",
},
{
"from": from_email,
"to": to_email,
"subject": "Hello User 2",
"html": "<strong>Welcome!</strong>",
},
]
emails = resend.Batch.send(params)
print(emails)
except ResendError as e:
print(f"Error sending batch emails: {e}")
5) Sending Attachments
You can send attachments by providing a list of attachments in the send method.
Attaching Local Files
To attach a file from your local filesystem, you need to read the file content and provide it as a base64-encoded string.
import os
import resend
import base64
from resend.errors import ResendError
try:
with open(ATTACHMENT_PATH, "rb") as f:
file_content = f.read()
params = {
"from": from_email,
"to": to_email,
"subject": "Email with Local Attachment",
"html": "<strong>Please see the attached file.</strong>",
"attachments": [
{
"filename": "README.md",
"content": base64.b64encode(file_content).decode("utf-8"),
}
],
}
email = resend.emails.send(params)
print(email)
except FileNotFoundError:
print(f"Error: The file '{file_path}' was not found.")
except ResendError as e:
print(f"Error sending email: {e}")
Attaching Remote Files
To attach a remote file, you can provide a public URL to the file in the path attribute.
import os
import resend
from resend.errors import ResendError
try:
params = {
"from": from_email,
"to": to_email,
"subject": "Email with Remote Attachment",
"html": "<strong>Please see the attached file.</strong>",
"attachments": [
{
"filename": "pdf-test.pdf",
"path": "https://www.orimi.com/pdf-test.pdf",
}
],
}
email = resend.Emails.send(params)
print(email)
except ResendError as e:
print(f"Error sending email: {e}")
6) Embedding Images
To embed images, you can use the attachments parameter with a Content-ID header.
Embedding Local Images
import os
import resend
import base64
from resend.errors import ResendError
# Note: Replace "path/to/logo.png" with the actual file path.
file_path = "path/to/logo.png"
try:
with open(IMAGE_PATH, "rb") as f:
image_content = f.read()
params = {
"from": from_email,
"to": to_email,
"subject": "Email with Embedded Local Image",
"html": "<img src=\"cid:logo.png\">",
"attachments": [
{
"filename": "logo.png",
"content": base64.b64encode(image_content).decode("utf-8"),
"cid": "logo.png",
}
],
}
email = resend.Emails.send(params)
print(email)
except FileNotFoundError:
print(f"Error: The file '{file_path}' was not found.")
except ResendError as e:
print(f"Error sending email: {e}")
Embedding Remote Images using CID
You can embed remote images by providing a public URL. By referencing the image with a Content ID (cid), you can ensure the image is displayed correctly in the email.
import os
import resend
from resend.errors import ResendError
try:
params = {
"from": from_email,
"to": to_email,
"subject": "Email with Embedded Remote Image",
"html": "<img src=\"cid:logo.png\">",
"attachments": [
{
"filename": "logo.png",
"path": "https://upload.wikimedia.org/wikipedia/commons/6/6a/PNG_Test.png",
"cid": "logo.png",
}
],
}
email = resend.Emails.send(params)
print(email)
except ResendError as e:
print(f"Error sending email: {e}")
Limitations of Attachments
While sending attachments is a powerful feature, there are a few limitations to keep in mind:
- Size Limit: The total size of an email, including attachments, cannot exceed 40MB. Keep in mind that attachments are base64 encoded, which increases their size by approximately 33%.
- File Types: Not all file types are supported. It’s recommended to check Resend’s documentation for the most up-to-date list of supported file types.
- Batch Sending: Emails with attachments cannot be sent using the batch sending endpoint. You must send them individually.
7) Scheduling Emails
You can schedule emails by providing a scheduled_at parameter.
from datetime import datetime, timedelta
import os
import resend
from resend.errors import ResendError
try:
scheduled_time = datetime.now() + timedelta(minutes=1)
params = {
"from": from_email,
"to": to_email,
"subject": "Scheduled Email 2",
"html": "<strong>This email was scheduled.</strong>",
"scheduled_at": scheduled_time.isoformat(),
}
email = resend.Emails.send(params)
print(email)
except ResendError as e:
print(f"Error sending email: {e}")
Production Patterns
1) Use a Verified Domain and Proper Authentication (SPF/DKIM/DMARC)
Resend provides support for DKIM, SPF, and DMARC. You must configure your DNS records correctly to ensure proper inbox placement. As a rule of thumb, do not judge deliverability from the first day of sending. Ramp up your volume gradually and monitor bounce and complaint rates.
2) Use Tags and Webhooks for Observability
Resend supports webhook endpoints and event delivery. In practice, you should:
- Tag emails by category (
password_reset,invoice,daily_digest) - Send webhook events to your analytics or logging pipeline
- Correlate message IDs with user actions
This provides better operational insight than simply tracking the number of emails sent.
3) Consider Scheduling and Batching for Digests
Resend includes primitives for scheduling and batch sending. For features like a “daily AI news digest,” batching can reduce API overhead and help manage throughput.
4) Use a Dedicated IP Only When Necessary
Resend offers a dedicated IP add-on for a monthly fee. Dedicated IPs are typically worth it when:
- You are a high-volume sender
- Your reputation needs isolation
- You have deliverability expertise or a provider that manages warmup
For low-volume senders, shared IP pools are usually simpler and safer.
Feature and Pricing Comparison
Here is a pragmatic comparison of developer email APIs based on their published pricing pages.
Pricing Baselines (Entry Tiers)
- Resend: Free tier covers 3,000 emails/month. The Pro tier costs $20/month for 50,000 emails, with overages at $0.90/1,000. The Scale tier is $90/month for 100,000 emails and includes Slack and urgent SLA support.
- Mailgun: Free tier includes 100 emails/day. The Basic plan starts at $15/month for 10,000 emails, with extra emails from $1.80/1,000.
- Postmark: Free tier includes 100 emails/month. The Basic plan is $15/month for 10,000 emails, with extra emails at $1.80/1,000.
- SendGrid: Marketing plans start at $15/month (Basic) and $60/month (Advanced), plus a free trial.
- Amazon SES: Pay-as-you-go with a free tier of 3,000 message charges/month for the first 12 months.
Feature and Developer Experience Highlights
Where Resend Tends to Win
- You want a modern developer experience with a clean, SDK-first integration.
- You value built-in primitives like scheduling, batching, tracking, webhooks, and multi-region sending.
- You are building product emails as part of your application and want a fast feedback loop.
Where SendGrid/Mailgun Can Win
- You need a broad, mature ecosystem with legacy integrations and enterprise-grade features.
- Your organization already uses Twilio tooling or has specific procurement and compliance workflows.
Where Postmark Often Wins
- You want a transactional-only provider with a strong focus on deliverability and simple, transparent pricing.
Where Amazon SES Wins
- You want the lowest infrastructure cost and are willing to take on more of the operational burden.
Which Scenarios is Resend Better For?
Choose Resend when:
- You are an engineering-led team shipping product emails (e.g., OTPs, login links, invoices, notifications).
- You want built-in workflow primitives without stitching together multiple tools.
- You are scaling from small to medium volume and want predictable pricing with an optional dedicated IP.
- You have a global audience and require multi-region sending.
Choose Postmark when you want a focused transactional provider with simple pricing and inbound processing.
Choose Mailgun when you need a widely-used email API with clear tiering and a long-standing deliverability product line.
Choose SendGrid when you need both marketing and API services from a single vendor.
Other Email Services to Consider
- MailerSend: A developer-friendly transactional email service with templates.
- Brevo: A platform that combines transactional email with marketing and CRM features.
- SparkPost / MessageBird Email, Elastic Email, SMTP2GO, Mailjet, Mandrill (Mailchimp Transactional)
Your best choice will depend on your sending volume, deliverability requirements, marketing automation needs, and how much operational load you are willing to carry.
Conclusion
Resend is an excellent choice for engineering-led teams that need a modern, developer-friendly email API. Its SDK-first approach, built-in primitives, and predictable pricing make it easy to scale from a free plan to a high-volume setup.
Next Steps
- Benchmark your expected monthly volume against Resend’s pricing tiers to determine when you might need to upgrade.
- Use tags, webhooks, and suppression controls to instrument your email delivery before scaling to higher volumes.
If you found this helpful, consider following my profile and signing up for the newsletter. Have thoughts or questions? Share them in the comments below.
References
메타데이터
- post_id
- 5210f706fef8
- slug
- resend-for-developers-a-guide-to-sending-email-with-python-5210f706fef8
- url
- https://blog1.neuralengineer.org/resend-for-developers-a-guide-to-sending-email-with-python-5210f706fef8
- canonical_url
- https://blog1.neuralengineer.org/resend-for-developers-a-guide-to-sending-email-with-python-5210f706fef8
- author_url
- https://medium.com/@pi45757
- status
- ok
- fetched_at
- 2026-06-13 00:08:42