MailBlock Python SDK
Official Python SDK for the MailBlock email service. Send emails with confidence using a clean, Pythonic interface with comprehensive error handling, logging, and validation.
🚀 Features
- Fluent Builder Pattern - Intuitive, chainable API for email construction
- Comprehensive Error Handling - Detailed error messages with helpful suggestions
- Async/Await Support - Both synchronous and asynchronous email sending
- Email Scheduling - Schedule emails for future delivery
- Robust Validation - Client-side validation with detailed feedback
- Advanced Logging - Built-in debugging and request tracking
- Type Hints - Full type safety with mypy support
- Context Manager - Proper resource management
- Retry Mechanism - Automatic retry with exponential backoff
MailBlock Python SDK
Official Python SDK for the MailBlock email service. Send emails with confidence using a clean, Pythonic interface with comprehensive error handling, logging, and validation.
🚀 Features
- Fluent Builder Pattern - Intuitive, chainable API for email construction
- Comprehensive Error Handling - Detailed error messages with helpful suggestions
- Async/Await Support - Both synchronous and asynchronous email sending
- Email Scheduling - Schedule emails for future delivery
- Robust Validation - Client-side validation with detailed feedback
- Advanced Logging - Built-in debugging and request tracking
- Type Hints - Full type safety with mypy support
- Context Manager - Proper resource management
- Retry Mechanism - Automatic retry with exponential backoff
📦 Installation
# Install from PyPI
pip install mailblock
# For async support
pip install mailblock[async]
# For development
pip install mailblock[dev]
🔧 Quick Start
from mailblock import MailBlock
# Initialize client
client = MailBlock("your-api-key")
# Send a simple email
response = client.email() \
.to("recipient@example.com") \
.from_email("sender@example.com") \
.subject("Hello from MailBlock!") \
.text("This is a test email from the MailBlock Python SDK.") \
.send_sync()
if response.success:
print(f"Email sent! ID: {response.data['id']}")
else:
print(f"Error: {response.error}")
📚 Documentation
Client Initialization
from mailblock import MailBlock
# Basic initialization
client = MailBlock("your-api-key")
# With custom configuration
client = MailBlock(
api_key="your-api-key",
base_url="https://api.mailblock.com", # Custom API endpoint
timeout=30, # Request timeout in seconds
max_retries=3, # Maximum retry attempts
retry_delay=1.0, # Base retry delay in seconds
debug=True # Enable debug logging
)
Basic Email Sending
Synchronous
# Simple text email
response = client.email() \
.to("recipient@example.com") \
.from_email("sender@example.com") \
.subject("Hello World") \
.text("This is a plain text email.") \
.send_sync()
# HTML email with fallback text
response = client.email() \
.to("user@example.com") \
.from_email("noreply@yourapp.com") \
.subject("Welcome!") \
.text("Welcome to our service!") \
.html("<h1>Welcome!</h1><p>Thanks for joining us.</p>") \
.send_sync()
Asynchronous
import asyncio
async def send_email():
response = await client.email() \
.to("recipient@example.com") \
.from_email("sender@example.com") \
.subject("Async Email") \
.text("This email was sent asynchronously!") \
.send()
return response
# Run async function
response = asyncio.run(send_email())
Email Scheduling
from datetime import datetime, timedelta
# Schedule for 1 hour from now
send_time = datetime.now() + timedelta(hours=1)
response = client.email() \
.to("recipient@example.com") \
.from_email("scheduler@example.com") \
.subject("Scheduled Email") \
.text("This email was scheduled for delivery.") \
.schedule_at(send_time) \
.send_sync()
# Schedule with date string
response = client.email() \
.to("recipient@example.com") \
.from_email("scheduler@example.com") \
.subject("Scheduled Email") \
.text("Scheduled via date string.") \
.schedule_at("2024-12-25T10:00:00") \
.send_sync()
Error Handling
from mailblock import ValidationError, AuthenticationError, RateLimitError
try:
response = client.email() \
.to("invalid-email") \
.from_email("sender@example.com") \
.subject("Test") \
.text("Test content") \
.send_sync()
except ValidationError as e:
print(f"Validation error: {e}")
print(f"Suggestion: {e.suggestion}")
except AuthenticationError as e:
print(f"Authentication failed: {e}")
print(f"Request ID: {e.request_id}")
except RateLimitError as e:
print(f"Rate limited: {e}")
print(f"Suggestion: {e.suggestion}")
except Exception as e:
print(f"Unexpected error: {e}")
Advanced Usage
Bulk Email Sending
import asyncio
async def send_bulk_emails():
recipients = [
"user1@example.com",
"user2@example.com",
"user3@example.com"
]
# Send emails concurrently
tasks = []
for recipient in recipients:
task = client.email() \
.to(recipient) \
.from_email("bulk@example.com") \
.subject("Bulk Email") \
.text(f"Personal email for {recipient}") \
.send()
tasks.append(task)
responses = await asyncio.gather(*tasks, return_exceptions=True)
for i, response in enumerate(responses):
if isinstance(response, Exception):
print(f"Email {i+1} failed: {response}")
elif response.success:
print(f"Email {i+1} sent successfully")
else:
print(f"Email {i+1} failed: {response.error}")
asyncio.run(send_bulk_emails())
Custom Logger
import logging
# Set up custom logger
logger = logging.getLogger("my_app.mailblock")
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler("email.log")
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
# Use custom logger
client = MailBlock("your-api-key", debug=True, logger=logger)
Context Manager
# Ensures proper cleanup of resources
with MailBlock("your-api-key") as client:
response = client.email() \
.to("recipient@example.com") \
.from_email("sender@example.com") \
.subject("Context Manager Test") \
.text("This uses proper resource management.") \
.send_sync()
Direct Email Data
from mailblock import EmailData
# Create email data directly
email_data = EmailData(
to="recipient@example.com",
from_email="sender@example.com",
subject="Direct Send",
text="Sent without builder pattern",
html="<p>Sent <strong>without</strong> builder pattern</p>"
)
# Send directly
response = client.send_email_sync(email_data)
🔍 API Response
All send methods return an APIResponse object with the following structure:
class APIResponse:
success: bool # Whether the request succeeded
request_id: str # Unique request identifier
timestamp: datetime # When the request was made
duration: int # Request duration in milliseconds
# On success
data: Dict[str, Any] # Response data (includes email ID)
message: str # Success message
# On error
error: str # Error message
error_type: str # Error category
suggestion: str # Helpful suggestion
status_code: int # HTTP status code
endpoint: str # API endpoint used
Success Response Example
if response.success:
print(f"Email ID: {response.data['id']}")
print(f"Status: {response.data['status']}")
print(f"Duration: {response.duration}ms")
print(f"Request ID: {response.request_id}")
Error Response Example
if not response.success:
print(f"Error: {response.error}")
print(f"Type: {response.error_type}")
print(f"Suggestion: {response.suggestion}")
print(f"Status Code: {response.status_code}")
print(f"Request ID: {response.request_id}")
🛡️ Exception Hierarchy
MailBlockError # Base exception
├── ValidationError # Client-side validation errors
├── AuthenticationError # Invalid API key (401)
├── AuthorizationError # Insufficient permissions (403)
├── RateLimitError # Rate limiting (429)
├── ServerError # Server errors (5xx)
├── NetworkError # Connection issues
└── TimeoutError # Request timeouts
⚙️ Configuration Options
| Parameter | Type | Default | Description |
|---|---|---|---|
api_key |
str |
Required | Your MailBlock API key |
base_url |
str |
https://sdk-backend-production-20e1.up.railway.app |
API base URL |
timeout |
int |
30 |
Request timeout in seconds |
max_retries |
int |
3 |
Maximum retry attempts |
retry_delay |
float |
1.0 |
Base retry delay in seconds |
debug |
bool |
False |
Enable debug logging |
logger |
Logger |
None |
Custom logger instance |
🧪 Testing
# Install development dependencies
pip install -e .[dev]
# Run tests
pytest
# Run tests with coverage
pytest --cov=mailblock
# Run specific test file
pytest tests/test_client.py
# Run with verbose output
pytest -v
🏗️ Development
# Clone repository
git clone https://github.com/5ysc4ll/mailblock-python.git
cd mailblock-python
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode
pip install -e .[dev]
# Run linting
flake8 mailblock tests
black mailblock tests
isort mailblock tests
# Type checking
mypy mailblock
📋 Examples
Check out the examples/ directory for comprehensive usage examples:
basic_usage.py- Basic email sending patternsadvanced_usage.py- Advanced features and async usage
🤝 Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add tests for new functionality
- Run the test suite (
pytest) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🐛 Issues & Support
- Bug Reports: GitHub Issues
- Feature Requests: GitHub Issues
- Documentation: MailBlock Docs
- Support: support@mailblock.com
🔗 Links
- GitHub: https://github.com/5ysc4ll/python-sdk
- PyPI: https://pypi.org/project/mailblock/
- Documentation: https://docs.mailblock.com
- MailBlock Website: https://mailblock.com
📊 Changelog
v1.0.0 (Initial Release)
- ✨ Fluent builder pattern for email construction
- 🔄 Both sync and async email sending
- ⏰ Email scheduling support
- 🛡️ Comprehensive error handling and validation
- 📝 Advanced logging and debugging
- 🔁 Automatic retry with exponential backoff
- 📚 Complete type hints and mypy support
- ✅ Comprehensive test suite
- 📖 Full documentation and examples
🆕 Enhanced Features (v1.1.0)
Multiple Recipients & CC/BCC
Send emails to multiple recipients with carbon copy and blind carbon copy support:
# Multiple recipients with CC and BCC
response = client.email() \
.to(["user1@example.com", "user2@example.com"]) \
.cc("manager@example.com") \
.bcc(["archive@example.com", "backup@example.com"]) \
.from_email("sender@example.com") \
.subject("Team Update") \
.text("This email goes to multiple recipients") \
.send_sync()
Email Cancellation
Cancel scheduled emails before they are sent:
# Cancel a single email
response = client.cancel_email_sync("email_id_123")
if response.success:
print(f"Email cancelled: {response.data['current_status']}")
# Cancel multiple emails in bulk
email_ids = ["email_1", "email_2", "email_3"]
response = client.cancel_emails_sync(email_ids)
print(f"Cancelled {response.data['success_count']} emails")
Update Scheduled Emails
Modify scheduled emails before they are sent:
from mailblock import UpdateEmailData
from datetime import datetime, timedelta
# Create update data
updates = UpdateEmailData(
subject="Updated Subject",
body_text="Updated text content",
body_html="<h1>Updated HTML</h1>",
scheduled_at=datetime.now() + timedelta(hours=2) # Reschedule
)
# Update the email
response = client.update_scheduled_email_sync("email_id_123", updates)
if response.success:
print("Email updated successfully")
Async Support
All new methods support async operations:
import asyncio
async def manage_emails():
# Async email cancellation
response = await client.cancel_email("email_id_123")
# Async bulk cancellation
response = await client.cancel_emails(["email_1", "email_2"])
# Async email updates
updates = UpdateEmailData(subject="New Subject")
response = await client.update_scheduled_email("email_id_123", updates)
asyncio.run(manage_emails())
Enhanced Validation
Comprehensive validation for all email operations:
# Validates email formats in arrays
try:
client.email().to(["valid@example.com", "invalid-email"])
except ValidationError as e:
print(f"Validation failed: {e}")
# Validates email IDs
try:
client.cancel_emails_sync([]) # Empty array
except ValidationError as e:
print(f"Validation failed: {e}")
Built with ❤️ by the MailBlock Team
Release files for mailblock 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| mailblock-1.1.0.tar.gz | 24.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mailblock-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 46.1 kB
Release files / mailblock-1.1.0.tar.gz
| Download URL | mailblock-1.1.0.tar.gz |
|---|---|
| Size | 24.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
91f5cc713b28c1c23258f8b2ff9c88fafc3037d574a1018bc63fcd69ec4b8614
|
|
BLAKE2b-256 checksum How to use checksums |
b7c97daeb28ddcbdf349c47f634ed04af55e78c41adbd72f8f78fdef95a24f3d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.4
|
Release files / mailblock-1.1.0-py3-none-any.whl
| Download URL | mailblock-1.1.0-py3-none-any.whl |
|---|---|
| Size | 21.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b8903f392e8831f61c040f1a64f5472e9d45256a280920c7121560f76d4bdeef
|
|
BLAKE2b-256 checksum How to use checksums |
dcefb30b6422029b3ab7e04eaa487135720f2dd927dc1d3972c7dd2dca158228
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.4
|