MailerSend Python SDK
- Table of Contents
- Installation
- SDK Architecture
- Response Data Access
- Logging
- Usage
- Activity
- Analytics
- Domains
- Sender Identities
- Inbound Routes
- Messages
- Scheduled messages
- Recipients
- Get a list of recipients
- Get a single recipient
- Delete a recipient
- Get recipients from a blocklist
- Get recipients from hard bounces
- Get recipients from spam complaints
- Get recipients from unsubscribes
- Add recipients to blocklist
- Add hard bounced recipients
- Add spam complaints
- Add recipients to unsubscribe list
- Delete recipients from blocklist
- Delete hard bounced recipients
- Delete spam complaints
- Delete recipients from unsubscribe list
- Templates
- Webhooks
- Email Verification
- Webhooks
- Email Verification
- SMS
- SMS Activity
- SMS Phone Numbers
- SMS Recipients
- SMS Messages
- SMS Webhooks
- SMS Inbound Routing
- Tokens
- SMTP Users
- Users
- Other Endpoints
- Error Handling
- Testing
- Available endpoints
- Support and Feedback
- License
pip install mailersend
- Python 3.7+
- An API Key from mailersend.com
The SDK supports multiple authentication methods:
Set your API key as a system environment variable:
export MAILERSEND_API_KEY="your-api-key"
Then initialize the client:
from mailersend import MailerSendClient
# Automatically uses MAILERSEND_API_KEY environment variable
ms = MailerSendClient()
For development, you can use a .env
file. First install python-dotenv
:
pip install python-dotenv
Create a .env
file in your project root:
# .env
MAILERSEND_API_KEY=your-api-key
Then load it in your Python code:
from mailersend import MailerSendClient
from dotenv import load_dotenv
# Load environment variables from .env file
load_dotenv()
# Client automatically uses the loaded MAILERSEND_API_KEY
ms = MailerSendClient()
from mailersend import MailerSendClient
ms = MailerSendClient(api_key="your-api-key")
The MailerSend Python SDK v2 introduces a modern, clean architecture that follows industry best practices:
The SDK uses the builder pattern for constructing API requests. This provides a fluent, readable interface for setting parameters:
from mailersend import MailerSendClient
from mailersend import SmsRecipientsBuilder
ms = MailerSendClient()
# Build a request using the fluent builder pattern
request = (SmsRecipientsBuilder()
.sms_number_id("sms123")
.status("active")
.page(1)
.limit(25)
.build_list_request())
# Execute the request
response = ms.sms_recipients.list_sms_recipients(request)
Each API endpoint group has its own resource class that provides clean method interfaces:
# Access different API resources
ms.sms_recipients # SMS Recipients operations
ms.sms_webhooks # SMS Webhooks operations
ms.sms_inbounds # SMS Inbound Routing operations
ms.email # Email operations
ms.domains # Domain operations
# ... and more
All data is validated using Pydantic models ensuring type safety and data integrity:
# All responses are strongly typed
response = ms.sms_recipients.get_sms_recipient(request)
print(response.id) # Validated string
print(response.number) # Validated phone number
print(response.created_at) # Validated datetime object
The MailerSend SDK provides flexible ways to access and work with API response data. All API calls return a unified APIResponse
object that supports multiple access patterns and data formats.
Access response data using dictionary-style syntax:
from mailersend import MailerSendClient
from mailersend import SmsRecipientsBuilder
ms = MailerSendClient()
request = SmsRecipientsBuilder().sms_recipient_id("recipient-123").build_get_request()
response = ms.sms_recipients.get_sms_recipient(request)
# Dict-style access
recipient_id = response["data"]["id"]
phone_number = response["data"]["number"]
status = response["data"]["status"]
# Nested access
if "sms" in response["data"]:
latest_sms = response["data"]["sms"][0]["text"]
# Check if key exists
if "error" in response:
error_message = response['error']
Access data using dot notation for cleaner code:
# Attribute-style access (most convenient)
recipient_id = response.id
phone_number = response.number
status = response.status
# Nested attribute access for complex data
if hasattr(response, 'sms') and response.sms:
latest_sms = response.sms[0].text
Use the get()
method for safe access with fallback values:
# Safe access with defaults
recipient_id = response.get("data", {}).get("id", "unknown")
error_message = response.get("error", "No error")
# Safe nested access
meta_info = response.get("meta", {})
total_count = meta_info.get("total", 0)
current_page = meta_info.get("page", 1)
When response data contains fields that conflict with built-in methods, use the data_
prefix:
# If response contains fields like 'items', 'keys', 'values', etc.
response_data = {
"items": [{"id": 1, "name": "Item 1"}],
"keys": ["key1", "key2"],
"values": [100, 200]
}
# Use dict access (recommended for conflicts)
items_list = response["items"]
key_list = response["keys"]
# Or use data_ prefix for attribute access
items_list = response.data_items
key_list = response.data_keys
value_list = response.data_values
Get the complete response as a dictionary:
# Convert entire response to dict
response_dict = response.to_dict()
# Returns:
# {
# "data": {"id": "123", "number": "+1234567890", ...},
# "headers": {"x-request-id": "req-456", ...},
# "status_code": 200,
# "request_id": "req-456",
# "rate_limit_remaining": 1000,
# "success": True
# }
# Or use dict() constructor
response_dict = dict(response)
# Access specific parts
data_only = response_dict["data"]
headers_only = response_dict["headers"]
Get JSON string representation with various formatting options:
# Compact JSON
json_string = response.to_json()
# Pretty-printed JSON with indentation
pretty_json = response.to_json(indent=2)
# Custom JSON options
unicode_json = response.to_json(ensure_ascii=False, indent=4)
# Direct json.dumps() also works
import json
json_string = json.dumps(response)
Access just the API response data without metadata:
# Get raw response data
raw_data = response.data
# For paginated responses
if isinstance(raw_data, dict) and "data" in raw_data:
items = raw_data["data"] # List of items
meta = raw_data.get("meta", {}) # Pagination info
links = raw_data.get("links", {}) # Pagination links
else:
# Single item response
item_data = raw_data
Headers can be accessed in multiple ways with automatic case handling:
# Dictionary-style access (case-sensitive)
request_id = response.headers["x-request-id"]
content_type = response.headers["content-type"]
# Attribute-style access (dashes become underscores)
request_id = response.headers.x_request_id
content_type = response.headers.content_type
rate_limit = response.headers.x_rate_limit_remaining
# Nested dictionary access
request_id = response["headers"]["x-request-id"]
# Safe access with defaults
retry_after = response.headers.get("retry-after", "0")
Access useful metadata about the API response:
# HTTP status information
status_code = response.status_code
is_successful = response.success # True for 2xx status codes
# Rate limiting information
remaining_requests = response.rate_limit_remaining
retry_delay = response.retry_after # Seconds to wait before retry
# Request tracking
request_id = response.request_id
# Pagination (for list responses)
if "meta" in response.data:
total_items = response.data["meta"]["total"]
current_page = response.data["meta"]["current_page"]
per_page = response.data["meta"]["per_page"]
Always check if the response was successful:
from mailersend import MailerSendClient, EmailBuilder
ms = MailerSendClient()
try:
email = EmailBuilder().from_email("[email protected]").build()
response = ms.emails.send(email)
if response.success:
email_id = response.id
remaining_quota = response.rate_limit_remaining
else:
status_code = response.status_code
error_details = response.data
# Handle rate limiting
if response.status_code == 429 and response.retry_after:
retry_seconds = response.retry_after
except Exception as e:
# Handle exception
When requests fail, error details are available in the response:
if not response.success:
error_data = response.data
# API error response structure
error_message = error_data.get("message", "Unknown error")
error_code = error_data.get("code")
# Validation errors (422 responses)
if "errors" in error_data:
for field, messages in error_data["errors"].items():
validation_errors = {field: messages}
# Single item responses (get operations)
user_response = ms.users.get_user(request)
if user_response.success:
user_name = user_response.name
user_email = user_response.email
# List responses (paginated)
users_response = ms.users.list_users(request)
if users_response.success:
users = users_response.data["data"] # Array of users
total_count = users_response.data["meta"]["total"]
for user in users:
user_name = user['name']
user_email = user['email']
# Empty responses (delete operations)
delete_response = ms.users.delete_user(request)
if delete_response.success:
# delete_response.data is typically empty or contains confirmation
deletion_confirmed = True
The SDK includes comprehensive logging to help with debugging and monitoring:
import logging
from mailersend import MailerSendClient
# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
ms = MailerSendClient()
# All API calls will now be logged with detailed information
import logging
from mailersend import MailerSendClient
# Configure logging with custom format
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('mailersend.log'),
logging.StreamHandler()
]
)
ms = MailerSendClient()
# Logs will include:
# - API request details
# - Response status codes
# - Parameter information
# - Error details
from mailersend import MailerSendClient, EmailBuilder
ms = MailerSendClient()
email = (EmailBuilder()
.from_email("[email protected]", "Your Name")
.to_many([{"email": "[email protected]", "name": "Recipient"}])
.subject("Hello from MailerSend!")
.html("<h1>Hello World!</h1>")
.text("Hello World!")
.build())
response = ms.emails.send(email)
print(f"Email sent: {response.message_id}")
from mailersend import MailerSendClient, EmailBuilder
ms = MailerSendClient()
email = (EmailBuilder()
.from_email("[email protected]", "Your Name")
.to_many([{"email": "[email protected]", "name": "Recipient"}])
.cc([
{"email": "[email protected]", "name": "CC User 1"},
{"email": "[email protected]", "name": "CC User 2"}
])
.bcc([
{"email": "[email protected]", "name": "BCC User 1"},
{"email": "[email protected]"}
])
.subject("Hello with CC/BCC!")
.html("<h1>Hello World!</h1>")
.build())
response = ms.emails.send(email)
from mailersend import MailerSendClient, EmailBuilder
ms = MailerSendClient()
email = (EmailBuilder()
.from_email("[email protected]", "Your Name")
.to_many([{"email": "[email protected]", "name": "Recipient"}])
.template("template-id")
.personalize_many([{
"email": "[email protected]",
"data": {
"name": "John",
"company": "MailerSend"
}
}])
.build())
response = ms.emails.send(email)
from mailersend import MailerSendClient, EmailBuilder
ms = MailerSendClient()
email = (EmailBuilder()
.from_email("[email protected]", "Your Name")
.to_many([{"email": "[email protected]", "name": "Recipient"}])
.subject("Hello {$name}!")
.html("<h1>Hello {$name} from {$company}!</h1>")
.personalize_many([{
"email": "[email protected]",
"data": {
"name": "John",
"company": "MailerSend",
"items": ["item1", "item2"],
"total": 99.99
}
}])
.build())
response = ms.emails.send(email)
from mailersend import MailerSendClient, EmailBuilder
ms = MailerSendClient()
email = (EmailBuilder()
.from_email("[email protected]", "Your Name")
.to_many([{"email": "[email protected]", "name": "Recipient"}])
.subject("Email with attachment")
.html("<h1>Please find attached document</h1>")
.attach_file("document.pdf")
.build())
response = ms.emails.send(email)
from mailersend import MailerSendClient, EmailBuilder
ms = MailerSendClient()
# Create individual EmailRequest objects
emails = [
EmailBuilder()
.from_email("[email protected]", "Sender")
.to_many([{"email": "[email protected]", "name": "Recipient 1"}])
.subject("Bulk email 1")
.html("<h1>Hello from bulk email 1</h1>")
.text("Hello from bulk email 1")
.build(),
EmailBuilder()
.from_email("[email protected]", "Sender")
.to_many([{"email": "[email protected]", "name": "Recipient 2"}])
.subject("Bulk email 2")
.html("<h1>Hello from bulk email 2</h1>")
.text("Hello from bulk email 2")
.build()
]
response = ms.emails.send_bulk(emails)
print(f"Bulk email ID: {response.bulk_email_id}")
from mailersend import MailerSendClient
ms = MailerSendClient()
response = ms.emails.get_bulk_status("bulk-email-id")
print(f"Status: {response.state}")
from mailersend import MailerSendClient, ActivityBuilder
from datetime import datetime, timedelta
ms = MailerSendClient()
# Get activities from last 7 days (maximum allowed timeframe)
date_from = int((datetime.now() - timedelta(days=7)).timestamp())
date_to = int(datetime.now().timestamp())
request = (ActivityBuilder()
.domain_id("domain-id")
.date_from(date_from)
.date_to(date_to)
.page(1)
.limit(25)
.build_list_request())
response = ms.activities.get(request)
from mailersend import MailerSendClient, ActivityBuilder
from datetime import datetime, timedelta
ms = MailerSendClient()
# Get activities from last 7 days
date_from = int((datetime.now() - timedelta(days=7)).timestamp())
date_to = int(datetime.now().timestamp())
request = (ActivityBuilder()
.domain_id("domain-id")
.date_from(date_from)
.date_to(date_to)
.events(["sent", "delivered", "opened"])
.page(1)
.limit(50)
.build_list_request())
response = ms.activities.get(request)
from mailersend import MailerSendClient, SingleActivityBuilder
ms = MailerSendClient()
request = (SingleActivityBuilder()
.activity_id("activity-id")
.build_get_request())
response = ms.activities.get_single(request)
from mailersend import MailerSendClient, AnalyticsBuilder
from datetime import datetime, timedelta
ms = MailerSendClient()
date_from = int((datetime.now() - timedelta(days=30)).timestamp())
date_to = int(datetime.now().timestamp())
request = (AnalyticsBuilder()
.date_from(date_from)
.date_to(date_to)
.events("sent", "delivered", "opened")
.domain_id("domain-id")
.group_by("days")
.build())
response = ms.analytics.get_activity_by_date(request)
for stat in response.data:
print(f"Date: {stat.date}, Sent: {stat.sent}, Delivered: {stat.delivered}")
from mailersend import MailerSendClient, AnalyticsBuilder
ms = MailerSendClient()
request = (AnalyticsBuilder()
.date_from(date_from)
.date_to(date_to)
.domain_id("domain-id")
.build())
response = ms.analytics.get_opens_by_country(request)
from mailersend import MailerSendClient, AnalyticsBuilder
ms = MailerSendClient()
request = (AnalyticsBuilder()
.date_from(date_from)
.date_to(date_to)
.domain_id("domain-id")
.build())
response = ms.analytics.get_opens_by_user_agent(request)
from mailersend import MailerSendClient, AnalyticsBuilder
ms = MailerSendClient()
request = (AnalyticsBuilder()
.date_from(date_from)
.date_to(date_to)
.domain_id("domain-id")
.build())
response = ms.analytics.get_opens_by_reading_environment(request)
from mailersend import MailerSendClient, DomainsBuilder
ms = MailerSendClient()
request = (DomainsBuilder()
.page(1)
.limit(25)
.build_list_request())
response = ms.domains.list_domains(request)
from mailersend import MailerSendClient, DomainsBuilder
ms = MailerSendClient()
request = (DomainsBuilder()
.domain_id("domain-id")
.build_get_request())
response = ms.domains.get_domain(request)
print(f"Domain: {response.name}")
from mailersend import MailerSendClient, DomainsBuilder
ms = MailerSendClient()
request = (DomainsBuilder()
.domain_name("mydomain.com")
.return_path_subdomain("rp")
.custom_tracking_subdomain("ct")
.inbound_routing_subdomain("ir")
.build_create_request())
response = ms.domains.create_domain(request)
print(f"Created domain with ID: {response.id}")
from mailersend import MailerSendClient, DomainsBuilder
ms = MailerSendClient()
request = (DomainsBuilder()
.domain_id("domain-id")
.build_delete_request())
response = ms.domains.delete_domain(request)
from mailersend import MailerSendClient, DomainsBuilder
ms = MailerSendClient()
request = (DomainsBuilder()
.domain_id("domain-id")
.page(1)
.limit(25)
.build_recipients_request())
response = ms.domains.get_domain_recipients(request)
from mailersend import MailerSendClient, DomainsBuilder
ms = MailerSendClient()
request = (DomainsBuilder()
.domain_id("domain-id")
.send_paused(False)
.track_clicks(True)
.track_opens(True)
.track_unsubscribe(True)
.track_content(True)
.custom_tracking_enabled(True)
.custom_tracking_subdomain("email")
.precedence_bulk(False)
.build_update_settings_request())
response = ms.domains.update_domain_settings(request)
from mailersend import MailerSendClient, DomainsBuilder
ms = MailerSendClient()
request = (DomainsBuilder()
.domain_id("domain-id")
.build_dns_records_request())
response = ms.domains.get_domain_dns_records(request)
from mailersend import MailerSendClient
from mailersend import DomainsBuilder
ms = MailerSendClient()
request = (DomainsBuilder()
.domain_id("domain-id")
.build_verification_request())
response = ms.domains.get_domain_verification_status(request)
from mailersend import MailerSendClient, IdentityBuilder
ms = MailerSendClient()
request = (IdentityBuilder()
.domain_id("domain-id")
.build_list_request())
response = ms.identities.list_identities(request)
from mailersend import MailerSendClient, IdentityBuilder
ms = MailerSendClient()
request = (IdentityBuilder()
.identity_id("identity-id")
.build_get_request())
response = ms.identities.get_identity(request)
from mailersend import MailerSendClient, IdentityBuilder
ms = MailerSendClient()
request = (IdentityBuilder()
.domain_id("domain-id")
.name("John Doe")
.email("[email protected]")
.reply_to_email("[email protected]")
.reply_to_name("Support Team")
.add_note(True)
.build_create_request())
response = ms.identities.create_identity(request)
from mailersend import MailerSendClient, IdentityBuilder
ms = MailerSendClient()
request = (IdentityBuilder()
.identity_id("identity-id")
.name("Jane Doe")
.reply_to_email("[email protected]")
.reply_to_name("Support Team")
.add_note(True)
.build_update_request())
response = ms.identities.update_identity(request)
from mailersend import MailerSendClient, IdentityBuilder
ms = MailerSendClient()
request = (IdentityBuilder()
.email("[email protected]")
.name("Doe Jane")
.reply_to_email("[email protected]")
.reply_to_name("Support Team")
.add_note(True)
.build_update_by_email_request())
response = ms.identities.update_identity(request)
from mailersend import MailerSendClient, IdentityBuilder
ms = MailerSendClient()
request = (IdentityBuilder()
.identity_id("identity-id")
.build_delete_request())
response = ms.identities.delete_identity(request)
from mailersend import MailerSendClient, IdentityBuilder
ms = MailerSendClient()
request = (IdentityBuilder()
.email("[email protected]")
.build_delete_by_email_request())
response = ms.identities.delete_identity_by_email(request)
from mailersend import MailerSendClient, InboundBuilder
ms = MailerSendClient()
request = (InboundBuilder()
.domain_id("domain-id")
.build_list_request())
response = ms.inbound.list(request)
from mailersend import MailerSendClient, InboundBuilder
ms = MailerSendClient()
request = (InboundBuilder()
.inbound_id("inbound-id")
.build_get_request())
response = ms.inbound.get(request)
from mailersend import MailerSendClient, InboundBuilder
ms = MailerSendClient()
request = (InboundBuilder()
.domain_id("domain-id")
.name("My Inbound Route")
.domain_enabled(False)
.inbound_priority(1)
.catch_type("all")
.match_type("all")
.add_forward("email", "[email protected]")
.catch_recipient([{"comparer": "equal", "value": "support"}])
.add_match_filter("match_sender", [{"comparer": "equal", "value": "support"}])
.add_webhook_forward("https://mycompany.com/webhook")
.build_create_request())
response = ms.inbound.create_inbound_route(request)
from mailersend import MailerSendClient, InboundBuilder
ms = MailerSendClient()
request = (InboundBuilder()
.inbound_id("inbound-id")
.name("Updated Route Name")
.enabled(False)
.build_update_request())
response = ms.inbound.update_inbound_route(request)
from mailersend import MailerSendClient, InboundBuilder
ms = MailerSendClient()
request = (InboundBuilder()
.inbound_id("inbound-id")
.build_delete_request())
response = ms.inbound.delete_inbound_route(request)
from mailersend import MailerSendClient, MessagesBuilder
ms = MailerSendClient()
request = (MessagesBuilder()
.build_list_request())
response = ms.messages.list_messages(request)
from mailersend import MailerSendClient, MessagesBuilder
ms = MailerSendClient()
request = (MessagesBuilder()
.message_id("message-id")
.build_get_request())
response = ms.messages.get_message(request)
from mailersend import MailerSendClient, SchedulesBuilder
ms = MailerSendClient()
request = (SchedulesBuilder()
.domain_id("domain-id")
.build_list_request())
response = ms.schedules.list_schedules(request)
from mailersend import MailerSendClient, SchedulesBuilder
ms = MailerSendClient()
request = (SchedulesBuilder()
.message_id("scheduled-id")
.build_get_request())
response = ms.schedules.get_schedule(request)
from mailersend import MailerSendClient, SchedulesBuilder
ms = MailerSendClient()
request = (SchedulesBuilder()
.message_id("scheduled-id")
.build_delete_request())
response = ms.schedules.delete_schedule(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.domain_id("domain-id")
.build_recipients_list_request())
response = ms.recipients.list_recipients(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.recipient_id("recipient-id")
.build_recipient_get_request())
response = ms.recipients.get_recipient(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.recipient_id("recipient-id")
.build_recipient_delete_request())
response = ms.recipients.delete_recipient(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.domain_id("domain-id")
.build_suppression_list_request())
response = ms.recipients.list_blocklist(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.domain_id("domain-id")
.build_suppression_list_request())
response = ms.recipients.list_hard_bounces(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.domain_id("domain-id")
.build_suppression_list_request())
response = ms.recipients.list_spam_complaints(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.domain_id("domain-id")
.build_suppression_list_request())
response = ms.recipients.list_unsubscribes(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
# Using specific emails
request = (RecipientsBuilder()
.domain_id("domain-id")
.recipients(["[email protected]", "[email protected]"])
.build_suppression_add_request())
response = ms.recipients.add_to_blocklist(request)
# Using patterns
request = (RecipientsBuilder()
.domain_id("domain-id")
.patterns(["*@spammer.com", "*@blocked-domain.com"])
.build_suppression_add_request())
response = ms.recipients.add_to_blocklist(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.domain_id("domain-id")
.recipients(["[email protected]"])
.build_suppression_add_request())
response = ms.recipients.add_hard_bounces(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.domain_id("domain-id")
.recipients(["[email protected]"])
.build_suppression_add_request())
response = ms.recipients.add_spam_complaints(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
request = (RecipientsBuilder()
.domain_id("domain-id")
.recipients(["[email protected]"])
.build_suppression_add_request())
response = ms.recipients.add_unsubscribes(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
# Delete specific entries by IDs
request = (RecipientsBuilder()
.domain_id("domain-id")
.ids(["recipient-id-1", "recipient-id-2"])
.build_suppression_delete_request())
response = ms.recipients.delete_from_blocklist(request)
# Or delete all entries
request = (RecipientsBuilder()
.domain_id("domain-id")
.all(True)
.build_suppression_delete_request())
response = ms.recipients.delete_from_blocklist(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
# Delete specific entries by IDs
request = (RecipientsBuilder()
.domain_id("domain-id")
.ids(["recipient-id"])
.build_suppression_delete_request())
response = ms.recipients.delete_hard_bounces(request)
# Or delete all entries
request = (RecipientsBuilder()
.domain_id("domain-id")
.all(True)
.build_suppression_delete_request())
response = ms.recipients.delete_hard_bounces(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
# Delete specific entries by IDs
request = (RecipientsBuilder()
.domain_id("domain-id")
.ids(["recipient-id"])
.build_suppression_delete_request())
response = ms.recipients.delete_spam_complaints(request)
# Or delete all entries
request = (RecipientsBuilder()
.domain_id("domain-id")
.all(True)
.build_suppression_delete_request())
response = ms.recipients.delete_spam_complaints(request)
from mailersend import MailerSendClient, RecipientsBuilder
ms = MailerSendClient()
# Delete specific entries by IDs
request = (RecipientsBuilder()
.domain_id("domain-id")
.ids(["recipient-id"])
.build_suppression_delete_request())
response = ms.recipients.delete_unsubscribes(request)
# Or delete all entries
request = (RecipientsBuilder()
.domain_id("domain-id")
.all(True)
.build_suppression_delete_request())
response = ms.recipients.delete_unsubscribes(request)
from mailersend import MailerSendClient, TemplatesBuilder
ms = MailerSendClient()
request = (TemplatesBuilder()
.domain_id("domain-id")
.page(1)
.limit(25)
.build_templates_list_request())
response = ms.templates.list_templates(request)
from mailersend import MailerSendClient, TemplatesBuilder
ms = MailerSendClient()
request = (TemplatesBuilder()
.template("template-id")
.build_template_get_request())
response = ms.templates.get_template(request)
from mailersend import MailerSendClient, TemplatesBuilder
ms = MailerSendClient()
request = (TemplatesBuilder()
.template("template-id")
.build_delete_request())
response = ms.templates.delete_template(request)
from mailersend import MailerSendClient, WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.domain_id("domain-id")
.build_webhooks_list_request())
response = ms.webhooks.list_webhooks(request)
from mailersend import MailerSendClient, WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.build_webhook_get_request())
response = ms.webhooks.get_webhook(request)
from mailersend import MailerSendClient, WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.domain_id("domain-id")
.url("https://yourdomain.com/webhook")
.name("My webhook")
.events(["activity.sent", "activity.delivered"])
.enabled(True)
.build_webhook_create_request())
response = ms.webhooks.create_webhook(request)
from mailersend import MailerSendClient, WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.domain_id("domain-id")
.url("https://yourdomain.com/webhook")
.name("My disabled webhook")
.events(["activity.sent", "activity.delivered"])
.enabled(False)
.build_webhook_create_request())
response = ms.webhooks.create_webhook(request)
from mailersend import MailerSendClient, WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.url("https://yourdomain.com/webhook-updated")
.name("My updated webhook")
.events(["activity.sent"])
.enabled(True)
.build_webhook_update_request())
response = ms.webhooks.update_webhook(request)
from mailersend import MailerSendClient, WebhooksBuilder
ms = MailerSendClient()
# Disable webhook
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.enabled(False)
.build_webhook_update_request())
response = ms.webhooks.update_webhook(request)
# Enable webhook
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.enabled(True)
.build_webhook_update_request())
response = ms.webhooks.update_webhook(request)
from mailersend import MailerSendClient, WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.build_webhook_delete_request())
response = ms.webhooks.delete_webhook(request)
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = EmailVerificationBuilder().build_lists()
response = ms.email_verification.list_verifications(request)
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = (EmailVerificationBuilder()
.email_verification_id("list-id")
.build_get())
response = ms.email_verification.get_verification(request)
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = (EmailVerificationBuilder()
.name("My Verification List")
.emails(["[email protected]", "[email protected]"])
.build_create())
response = ms.email_verification.create_verification(request)
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = (EmailVerificationBuilder()
.email_verification_id("list-id")
.build_verify_list())
response = ms.email_verification.verify_list(request)
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = (EmailVerificationBuilder()
.email_verification_id("list-id")
.build_results())
response = ms.email_verification.get_results(request)
from mailersend import MailerSendClient
from mailersend import WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.domain_id("domain-id")
.build_webhooks_list_request())
response = ms.webhooks.list_webhooks(request)
for webhook in response.data:
print(f"Webhook: {webhook.name} - {webhook.url}")
from mailersend import MailerSendClient
from mailersend import WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.build_webhook_get_request())
response = ms.webhooks.get_webhook(request)
print(f"Webhook: {response.name}")
from mailersend import MailerSendClient
from mailersend import WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.domain_id("domain-id")
.url("https://webhook.example.com")
.name("My Webhook")
.events(["activity.sent", "activity.delivered", "activity.opened"])
.enabled(True)
.build_webhook_create_request())
response = ms.webhooks.create_webhook(request)
print(f"Created webhook with ID: {response.id}")
from mailersend import MailerSendClient
from mailersend import WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.domain_id("domain-id")
.url("https://webhook.example.com")
.name("Disabled Webhook")
.events(["activity.sent", "activity.delivered"])
.enabled(False) # Create disabled
.build_webhook_create_request())
response = ms.webhooks.create_webhook(request)
from mailersend import MailerSendClient
from mailersend import WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.name("Updated Webhook Name")
.url("https://new-webhook.example.com")
.enabled(True)
.build_webhook_update_request())
response = ms.webhooks.update_webhook(request)
from mailersend import MailerSendClient
from mailersend import WebhooksBuilder
ms = MailerSendClient()
# Disable webhook
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.enabled(False)
.build_webhook_update_request())
response = ms.webhooks.update_webhook(request)
# Enable webhook
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.enabled(True)
.build_webhook_update_request())
response = ms.webhooks.update_webhook(request)
from mailersend import MailerSendClient
from mailersend import WebhooksBuilder
ms = MailerSendClient()
request = (WebhooksBuilder()
.webhook_id("webhook-id")
.build_webhook_delete_request())
response = ms.webhooks.delete_webhook(request)
print("Webhook deleted")
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = EmailVerificationBuilder().build_list_request()
response = ms.email_verification.list_verification_lists(request)
for verification_list in response.data:
print(f"List: {verification_list.name}, Status: {verification_list.status}")
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = (EmailVerificationBuilder()
.verification_list_id("list-id")
.build_get_request())
response = ms.email_verification.get_verification_list(request)
print(f"List name: {response.name}")
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = (EmailVerificationBuilder()
.name("My Verification List")
.emails(["[email protected]", "[email protected]"])
.build_create_request())
response = ms.email_verification.create_verification_list(request)
print(f"Created list with ID: {response.id}")
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = (EmailVerificationBuilder()
.verification_list_id("list-id")
.build_verify_request())
response = ms.email_verification.verify_list(request)
print(f"Verification started: {response.message}")
from mailersend import MailerSendClient, EmailVerificationBuilder
ms = MailerSendClient()
request = (EmailVerificationBuilder()
.verification_list_id("list-id")
.build_results_request())
response = ms.email_verification.get_verification_results(request)
for result in response.data:
print(f"Email: {result.email}, Status: {result.status}")
from mailersend import MailerSendClient, SmsSendingBuilder
ms = MailerSendClient()
# Simple SMS
request = (SmsSendingBuilder()
.from_number("sms-number")
.to(["+1234567890", "+1234567891"])
.text("Hello from MailerSend SMS!")
.build())
response = ms.sms_sending.send(request)
# SMS with personalization
request = (SmsSendingBuilder()
.from_number("sms-number")
.to(["+1234567890", "+1234567891"])
.text("Hello {{name}}, your order {{order_id}} is ready!")
.personalization([
{
"phone_number": "+1234567890",
"data": {"name": "John", "order_id": "12345"}
},
{
"phone_number": "+1234567891",
"data": {"name": "Jane", "order_id": "12346"}
}
])
.build())
response = ms.sms_sending.send(request)
from mailersend import MailerSendClient, SmsActivityBuilder
from datetime import datetime, timedelta
ms = MailerSendClient()
# Get activities from last 7 days
date_from = int((datetime.now() - timedelta(days=7)).timestamp())
date_to = int(datetime.now().timestamp())
request = (SmsActivityBuilder()
.sms_number_id("sms-number-id")
.date_from(date_from)
.date_to(date_to)
.status(["sent", "delivered", "failed"])
.page(1)
.limit(25)
.build_list_request())
response = ms.sms_activity.list(request)
from mailersend import MailerSendClient, SmsActivityBuilder
ms = MailerSendClient()
request = (SmsActivityBuilder()
.sms_message_id("sms-message-id")
.build_get_request())
response = ms.sms_activity.get(request)
from mailersend import MailerSendClient, SmsNumbersBuilder
ms = MailerSendClient()
request = (SmsNumbersBuilder()
.paused(False)
.page(1)
.limit(25)
.build_list_request())
response = ms.sms_numbers.list(request)
from mailersend import MailerSendClient, SmsNumbersBuilder
ms = MailerSendClient()
request = (SmsNumbersBuilder()
.sms_number_id("sms-number-id")
.build_get_request())
response = ms.sms_numbers.get(request)
from mailersend import MailerSendClient, SmsNumbersBuilder
ms = MailerSendClient()
request = (SmsNumbersBuilder()
.sms_number_id("sms-number-id")
.paused(True)
.build_update_request())
response = ms.sms_numbers.update(request)
from mailersend import MailerSendClient, SmsNumbersBuilder
ms = MailerSendClient()
request = (SmsNumbersBuilder()
.sms_number_id("sms-number-id")
.build_delete_request())
response = ms.sms_numbers.delete(request)
from mailersend import MailerSendClient, SmsRecipientsBuilder
from mailersend.models.sms_recipients import SmsRecipientStatus
ms = MailerSendClient()
request = (SmsRecipientsBuilder()
.sms_number_id("sms-number-id")
.status(SmsRecipientStatus.ACTIVE)
.page(1)
.limit(25)
.build_list_request())
response = ms.sms_recipients.list_sms_recipients(request)
from mailersend import MailerSendClient, SmsRecipientsBuilder
ms = MailerSendClient()
request = (SmsRecipientsBuilder()
.sms_recipient_id("recipient-id")
.build_get_request())
response = ms.sms_recipients.get_sms_recipient(request)
from mailersend import MailerSendClient, SmsRecipientsBuilder
from mailersend.models.sms_recipients import SmsRecipientStatus
ms = MailerSendClient()
request = (SmsRecipientsBuilder()
.sms_recipient_id("recipient-id")
.build_update_request(SmsRecipientStatus.OPT_OUT))
response = ms.sms_recipients.update_sms_recipient(request)
from mailersend import MailerSendClient, SmsMessagesBuilder
ms = MailerSendClient()
request = (SmsMessagesBuilder()
.page(1)
.limit(25)
.build_sms_messages_list())
response = ms.sms_messages.list_sms_messages(request)
from mailersend import MailerSendClient, SmsMessagesBuilder
ms = MailerSendClient()
request = (SmsMessagesBuilder()
.sms_message_id("message-id")
.build_sms_message_get())
response = ms.sms_messages.get_sms_message(request)
from mailersend import MailerSendClient, SmsWebhooksBuilder
ms = MailerSendClient()
request = (SmsWebhooksBuilder()
.sms_number_id("sms-number-id")
.build_list_request())
response = ms.sms_webhooks.list_sms_webhooks(request)
from mailersend import MailerSendClient, SmsWebhooksBuilder
ms = MailerSendClient()
request = (SmsWebhooksBuilder()
.sms_webhook_id("webhook-id")
.build_get_request())
response = ms.sms_webhooks.get_sms_webhook(request)
from mailersend import MailerSendClient, SmsWebhooksBuilder
from mailersend.models.sms_webhooks import SmsWebhookEvent
ms = MailerSendClient()
request = (SmsWebhooksBuilder()
.from_number("sms-number-id")
.url("https://webhook.example.com/sms")
.name("SMS Webhook")
.add_event(SmsWebhookEvent.SMS_SENT)
.add_event(SmsWebhookEvent.SMS_DELIVERED)
.add_event(SmsWebhookEvent.SMS_FAILED)
.enabled(True)
.build_create_request())
response = ms.sms_webhooks.create_sms_webhook(request)
from mailersend import MailerSendClient, SmsWebhooksBuilder
from mailersend.models.sms_webhooks import SmsWebhookEvent
ms = MailerSendClient()
request = (SmsWebhooksBuilder()
.sms_webhook_id("webhook-id")
.name("Updated SMS Webhook")
.url("https://new-webhook.example.com/sms")
.events([SmsWebhookEvent.SMS_DELIVERED, SmsWebhookEvent.SMS_FAILED])
.enabled(False)
.build_update_request())
response = ms.sms_webhooks.update_sms_webhook(request)
from mailersend import MailerSendClient, SmsWebhooksBuilder
ms = MailerSendClient()
request = (SmsWebhooksBuilder()
.sms_webhook_id("webhook-id")
.build_delete_request())
response = ms.sms_webhooks.delete_sms_webhook(request)
from mailersend import MailerSendClient, SmsInboundsBuilder
ms = MailerSendClient()
request = (SmsInboundsBuilder()
.sms_number_id("sms-number-id")
.enabled(True)
.build_list_request())
response = ms.sms_inbounds.list_sms_inbounds(request)
from mailersend import MailerSendClient, SmsInboundsBuilder
ms = MailerSendClient()
request = (SmsInboundsBuilder()
.sms_inbound_id("inbound-id")
.build_get_request())
response = ms.sms_inbounds.get_sms_inbound(request)
from mailersend import MailerSendClient, SmsInboundsBuilder
from mailersend.models.sms_inbounds import FilterComparer
ms = MailerSendClient()
request = (SmsInboundsBuilder()
.sms_number_id("sms-number-id")
.name("Support Route")
.forward_url("https://api.example.com/sms/support")
.filter(FilterComparer.STARTS_WITH, "SUPPORT")
.enabled(True)
.build_create_request())
response = ms.sms_inbounds.create_sms_inbound(request)
from mailersend import MailerSendClient, SmsInboundsBuilder
from mailersend.models.sms_inbounds import FilterComparer
ms = MailerSendClient()
request = (SmsInboundsBuilder()
.sms_number_id("inbound-id")
.name("Updated Support Route")
.forward_url("https://api.example.com/sms/new-support")
.filter(FilterComparer.CONTAINS, "HELP")
.enabled(False)
.build_update_request())
response = ms.sms_inbounds.update_sms_inbound(request)
from mailersend import MailerSendClient, SmsInboundsBuilder
ms = MailerSendClient()
request = (SmsInboundsBuilder()
.sms_inbound_id("inbound-id")
.build_delete_request())
response = ms.sms_inbounds.delete_sms_inbound(request)
from mailersend import MailerSendClient, TokensBuilder
ms = MailerSendClient()
request = (TokensBuilder()
.name("My API Token")
.scopes(["email_full", "analytics_read"])
.domain_id("domain-id")
.build_token_create())
response = ms.tokens.create_token(request)
from mailersend import MailerSendClient, TokensBuilder
ms = MailerSendClient()
# Pause token
request = (TokensBuilder()
.token_id("token-id")
.status("pause")
.build_token_update())
response = ms.tokens.update_token(request)
# Unpause token
request = (TokensBuilder()
.token_id("token-id")
.status("unpause")
.build_token_update())
response = ms.tokens.update_token(request)
from mailersend import MailerSendClient, TokensBuilder
ms = MailerSendClient()
request = (TokensBuilder()
.token_id("token-id")
.build_token_delete())
response = ms.tokens.delete_token(request)
from mailersend import MailerSendClient, SmtpUsersBuilder
ms = MailerSendClient()
request = (SmtpUsersBuilder()
.domain_id("domain-id")
.build_smtp_users_list())
response = ms.smtp_users.list_smtp_users(request)
from mailersend import MailerSendClient, SmtpUsersBuilder
ms = MailerSendClient()
request = (SmtpUsersBuilder()
.domain_id("domain-id")
.smtp_user_id("smtp-user-id")
.build_smtp_user_get())
response = ms.smtp_users.get_smtp_user(request)
from mailersend import MailerSendClient, SmtpUsersBuilder
ms = MailerSendClient()
request = (SmtpUsersBuilder()
.domain_id("domain-id")
.name("SMTP User Name")
.enabled(True)
.build_smtp_user_create())
response = ms.smtp_users.create_smtp_user(request)
from mailersend import MailerSendClient, SmtpUsersBuilder
ms = MailerSendClient()
request = (SmtpUsersBuilder()
.domain_id("domain-id")
.smtp_user_id("smtp-user-id")
.name("Updated SMTP User Name")
.enabled(False)
.build_smtp_user_update())
response = ms.smtp_users.update_smtp_user(request)
from mailersend import MailerSendClient, SmtpUsersBuilder
ms = MailerSendClient()
request = (SmtpUsersBuilder()
.domain_id("domain-id")
.smtp_user_id("smtp-user-id")
.build_smtp_user_delete())
response = ms.smtp_users.delete_smtp_user(request)
from mailersend import MailerSendClient, UsersBuilder
ms = MailerSendClient()
request = (UsersBuilder()
.page(1)
.limit(25)
.build_users_list())
response = ms.users.list_users(request)
from mailersend import MailerSendClient, UsersBuilder
ms = MailerSendClient()
request = (UsersBuilder()
.user_id("user-id")
.build_user_get())
response = ms.users.get_user(request)
from mailersend import MailerSendClient, UsersBuilder
ms = MailerSendClient()
# Basic invite with admin role
request = (UsersBuilder()
.email("[email protected]")
.admin_role()
.build_user_invite())
response = ms.users.invite_user(request)
# Custom invite with specific permissions and access
request = (UsersBuilder()
.email("[email protected]")
.designer_role()
.add_permission("read-all-templates")
.add_permission("manage-template")
.add_template("template-id")
.add_domain("domain-id")
.requires_periodic_password_change(True)
.build_user_invite())
response = ms.users.invite_user(request)
from mailersend import MailerSendClient, UsersBuilder
ms = MailerSendClient()
request = (UsersBuilder()
.user_id("user-id")
.manager_role()
.add_permission("read-analytics")
.add_permission("read-activity")
.add_domain("domain-id")
.build_user_update())
response = ms.users.update_user(request)
from mailersend import MailerSendClient, UsersBuilder
ms = MailerSendClient()
request = (UsersBuilder()
.user_id("user-id")
.build_user_delete())
response = ms.users.delete_user(request)
from mailersend import MailerSendClient, UsersBuilder
ms = MailerSendClient()
request = (UsersBuilder()
.page(1)
.limit(25)
.build_invites_list())
response = ms.users.list_invites(request)
from mailersend import MailerSendClient, UsersBuilder
ms = MailerSendClient()
request = (UsersBuilder()
.invite_id("invite-id")
.build_invite_get())
response = ms.users.get_invite(request)
from mailersend import MailerSendClient, UsersBuilder
ms = MailerSendClient()
request = (UsersBuilder()
.invite_id("invite-id")
.build_invite_resend())
response = ms.users.resend_invite(request)
from mailersend import MailerSendClient, UsersBuilder
ms = MailerSendClient()
request = (UsersBuilder()
.invite_id("invite-id")
.build_invite_cancel())
response = ms.users.cancel_invite(request)
from mailersend import MailerSendClient
ms = MailerSendClient()
response = ms.api_quota.get_quota()
The SDK provides comprehensive error handling with detailed error information:
from mailersend import MailerSendClient
from mailersend.exceptions import MailerSendError
from mailersend import EmailBuilder
ms = MailerSendClient()
try:
email = (EmailBuilder()
.from_email("invalid-email", "Sender") # Invalid email
.to_many([{"email": "[email protected]", "name": "Recipient"}])
.subject("Test")
.html("<h1>Test</h1>")
.build())
response = ms.emails.send(email)
except MailerSendError as e:
print(f"MailerSend API Error: {e}")
print(f"Status Code: {e.status_code}")
print(f"Error Details: {e.details}")
except Exception as e:
print(f"Unexpected error: {e}")
Common error types:
- ValidationError: Invalid data in request models (handled by Pydantic)
- AuthenticationError: Invalid or missing API key
- RateLimitError: API rate limit exceeded
- APIError: General API errors (4xx, 5xx responses)
- NetworkError: Network connectivity issues
# Install development dependencies
pip install -e ".[dev]"
# Run all tests
pytest
# Run specific test module
pytest tests/unit/test_sms_recipients_*.py
# Run with coverage
pytest --cov=mailersend --cov-report=html
The SDK uses VCR.py for integration tests to record and replay API responses:
import pytest
from mailersend import MailerSendClient
from mailersend import SmsRecipientsBuilder
@pytest.mark.vcr
def test_list_sms_recipients():
ms = MailerSendClient()
request = SmsRecipientsBuilder().build_list_request()
response = ms.sms_recipients.list_sms_recipients(request)
assert response.data is not None
Feature group | Endpoint | Available |
---|---|---|
Activity | GET activity |
✅ |
Analytics | GET analytics |
✅ |
Domains | {GET, POST, PUT, DELETE} domains |
✅ |
POST send |
✅ | |
Email Verification | {GET, POST, PUT} email-verification |
✅ |
Bulk Email | POST bulk-email |
✅ |
Inbound Routes | {GET, POST, PUT, DELETE} inbound |
✅ |
Messages | GET messages |
✅ |
Scheduled Messages | {GET, DELETE} scheduled-messages |
✅ |
Recipients | {GET, POST, DELETE} recipients |
✅ |
Templates | {GET, DELETE} templates |
✅ |
Tokens | {POST, PUT, DELETE} tokens |
✅ |
SMTP Users | {GET, POST, PUT, DELETE} smtp-users |
✅ |
Users | {GET, POST, PUT, DELETE} users |
✅ |
User Invites | {GET, POST, DELETE} invites |
✅ |
Webhooks | {GET, POST, PUT, DELETE} webhooks |
✅ |
SMS Sending | POST sms |
✅ |
SMS Activity | GET sms-activity |
✅ |
SMS Phone Numbers | {GET, PUT, DELETE} sms-numbers |
✅ |
SMS Recipients | {GET, PUT} sms-recipients |
✅ |
SMS Messages | GET sms-messages |
✅ |
SMS Webhooks | {GET, POST, PUT, DELETE} sms-webhooks |
✅ |
SMS Inbound Routing | {GET, POST, PUT, DELETE} sms-inbounds |
✅ |
Sender Identities | {GET, POST, PUT, DELETE} identities |
✅ |
API Quota | GET api-quota |
✅ |
All endpoints are available and fully tested. Refer to official API docs for the most up-to-date API specifications.
In case you find any bugs, submit an issue directly here in GitHub.
If you have any troubles using our API or SDK free to contact our support by email [email protected]
The official documentation is at https://developers.mailersend.com