Python SDK
Python 3.10+
pip install
Send emails with Python using the official Laneful Python SDK. Built for modern Python applications with async support and comprehensive features.
Full Feature Support
Templates, attachments, tracking, webhooks
Async Support
Both sync and async operations
Modern Python
Python 3.10+ with type hints
On this page
Prerequisites
To get the most out of this guide, you'll need:
- • Python 3.10 or higher
- • pip package manager
- • A Laneful account with API key
- • Verified domain for sending emails
Installation
pip
Install the Laneful Python SDK using pip:
# Basic installation pip install laneful # With async support pip install laneful[async]
Quick Start
Send your first email in minutes:
Send Simple Text Email
from laneful import LanefulClient, Email, Address # Initialize the client client = LanefulClient( base_url="https://your-endpoint.send.laneful.net", auth_token="your-auth-token" ) # Create an email email = Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="recipient@example.com", name="Recipient Name")], subject="Hello from Laneful!", text_content="This is a simple test email sent using the Laneful Python SDK.", html_content="<h1>Hello from Laneful!</h1><p>This is a simple test email sent using the Laneful Python SDK.</p>" ) # Send the email try: response = client.send_email(email) print("✓ Email sent successfully!") print(f"Response status: {response.status}") except Exception as e: print(f"✗ Error: {e}")
Examples
Common use cases and patterns:
HTML Email with Tracking
from laneful import LanefulClient, Email, Address, TrackingSettings email = Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="recipient@example.com", name="Recipient Name")], subject="HTML Email with Tracking", html_content="<h1>Welcome!</h1><p>This is an <strong>HTML email</strong> with tracking enabled.</p>", text_content="Welcome! This is an HTML email with tracking enabled.", tag="welcome-email", tracking=TrackingSettings( opens=True, clicks=True, unsubscribes=True ) ) response = client.send_email(email)
Template Email
email = Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="user@example.com", name="User")], template_id="welcome-template", template_data={ "name": "John Doe", "company": "Acme Corporation", "activation_link": "https://example.com/activate" } ) response = client.send_email(email)
Email with Attachments
import base64 from laneful import LanefulClient, Email, Address, Attachment # Create attachment from file with open("/path/to/document.pdf", "rb") as f: attachment_data = base64.b64encode(f.read()).decode() email = Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="user@example.com", name="User")], subject="Document Attached", text_content="Please find the document attached.", attachments=[ Attachment( file_name="document.pdf", content=attachment_data, content_type="application/pdf" ) ] ) response = client.send_email(email)
Multiple Recipients with Reply-To
email = Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[ Address(email="user1@example.com", name="User One"), Address(email="user2@example.com", name="User Two") ], cc=[Address(email="cc@example.com", name="CC Recipient")], bcc=[Address(email="bcc@example.com", name="BCC Recipient")], reply_to=Address(email="reply@example.com", name="Reply To"), subject="Email to Multiple Recipients", text_content="This email is being sent to multiple recipients." ) response = client.send_email(email)
Scheduled Email
import time # Schedule for 24 hours from now send_time = int(time.time()) + (24 * 60 * 60) email = Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="user@example.com", name="User")], subject="Scheduled Email", text_content="This email was scheduled.", send_time=send_time ) response = client.send_email(email)
Async Email Sending
import asyncio from laneful import AsyncLanefulClient, Email, Address async def send_async_email(): async with AsyncLanefulClient( base_url="https://your-endpoint.send.laneful.net", auth_token="your-auth-token" ) as client: email = Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="user@example.com", name="User")], subject="Async Email", text_content="This email was sent asynchronously.", html_content="<h1>Async Email</h1><p>This email was sent asynchronously.</p>" ) # Send email try: response = await client.send_email(email) print("✓ Email sent successfully!") print(f"Response status: {response.status}") return response except Exception as e: print(f"✗ Error: {e}") raise # Run async function asyncio.run(send_async_email())
Batch Email Sending
emails = [ Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="user1@example.com", name="User One")], subject="Email 1", text_content="First email content." ), Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="user2@example.com", name="User Two")], subject="Email 2", text_content="Second email content." ) ] response = client.send_emails(emails)
Context Manager Usage
# Sync context manager - automatic resource cleanup with LanefulClient( base_url="https://your-endpoint.send.laneful.net", auth_token="your-auth-token" ) as client: email = Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="user@example.com", name="User")], subject="Context Manager Email", text_content="This email was sent using a context manager." ) response = client.send_email(email) print(f"Email sent: {response.status}") # Client session automatically closed # Async context manager async with AsyncLanefulClient( base_url="https://your-endpoint.send.laneful.net", auth_token="your-auth-token" ) as client: email = Email( from_address=Address(email="sender@example.com", name="Your Name"), to=[Address(email="user@example.com", name="User")], subject="Async Context Manager Email", text_content="This email was sent using an async context manager." ) response = await client.send_email(email) print(f"Email sent: {response.status}") # Client session automatically closed
Webhook Handler Example
from flask import Flask, request, jsonify from laneful.webhooks import WebhookHandler, WebhookEvent import json app = Flask(__name__) # Initialize webhook handler webhook_handler = WebhookHandler(webhook_secret="your-webhook-secret") # Register event handlers @webhook_handler.on("email.delivered") def handle_delivered(event: WebhookEvent): print(f"Email {event.message_id} delivered to {event.email}") @webhook_handler.on("email.opened") def handle_opened(event: WebhookEvent): print(f"Email {event.message_id} opened by {event.email}") @webhook_handler.on("email.clicked") def handle_clicked(event: WebhookEvent): url = event.data.get("url") print(f"Link clicked by {event.email}: {url}") @webhook_handler.on("email.bounced") def handle_bounced(event: WebhookEvent): is_hard = event.data.get("is_hard") print(f"Email bounced ({'hard' if is_hard else 'soft'}) for: {event.email}") @app.route('/webhook', methods=['POST']) def handle_webhook(): try: # Get raw payload payload = request.get_data(as_text=True) # Extract signature from headers signature = request.headers.get('x-webhook-signature') if not signature: return jsonify({'error': 'Missing signature'}), 401 # Verify signature and process webhook if webhook_handler.verify_signature(payload, signature): webhook_handler.process_webhook(payload) return jsonify({'status': 'success'}) else: return jsonify({'error': 'Invalid signature'}), 401 except Exception as e: return jsonify({'error': str(e)}), 400 if __name__ == '__main__': app.run(debug=True)
API Reference
LanefulClient
Constructors
- •
LanefulClient(base_url: str, auth_token: str)
- Initialize client with endpoint and auth token
Methods
- •
send_email(email: Email) → Response
- Send single email - •
send_emails(emails: List[Email]) → Response
- Send multiple emails
Required Fields
- •
from_address: Address
- Sender address
Optional Fields
- •
to: List[Address]
- Recipient addresses - •
cc: List[Address]
- CC recipient addresses - •
bcc: List[Address]
- BCC recipient addresses - •
reply_to: Address
- Reply-to address - •
subject: str
- Email subject - •
text_content: str
- Plain text content - •
html_content: str
- HTML content - •
template_id: str
- Template ID - •
template_data: dict
- Template data - •
attachments: List[dict]
- File attachments - •
send_time: int
- Scheduled send time (Unix timestamp) - •
tag: str
- Email tag for categorization
Utility Classes
- •
Address(email: str, name: str = None)
- Email address with optional name - •
Attachment(file_name: str, content: str, content_type: str)
- Email attachment with base64 encoded content - •
TrackingSettings(opens: bool, clicks: bool, unsubscribes: bool)
- Email tracking configuration - •
AsyncLanefulClient
- Async version of the client for async/await operations
WebhookHandler
Initialization
- •
WebhookHandler(webhook_secret: str = None)
- Initialize webhook handler with optional secret
Signature Verification
- •
verify_signature(payload: str, signature: str) → bool
- Verifies webhook signature (supports sha256= prefix)
Event Handling
- •
on(event_type: str)
- Decorator to register event handlers - •
register_handler(event_type: str, handler: Callable)
- Register event handler function - •
process_webhook(payload: str)
- Process webhook payload and call appropriate handlers
WebhookEvent
- •
event_type: str
- Type of webhook event - •
message_id: str
- Message ID of the email - •
email: str
- Email address of the recipient - •
timestamp: int
- Unix timestamp of the event - •
data: Dict[str, Any]
- Additional event data
Error Handling
Comprehensive error handling with specific exception types:
from laneful.exceptions import LanefulError, LanefulAPIError, LanefulAuthError try: response = client.send_email(email) print("✓ Email sent successfully!") print(f"Response status: {response.status}") except LanefulAuthError: print("✗ Authentication failed - check your API token") except LanefulAPIError as e: print(f"✗ API error: {e.message} (status: {e.status_code})") except LanefulError as e: print(f"✗ Client error: {e.message}") except Exception as e: print(f"✗ Unexpected error: {e}")
Error Handling
- •
LanefulAuthError
- Authentication failures - •
LanefulAPIError
- API request failures - •
LanefulError
- General client errors - •
Exception
- Unexpected errors
Best Practices
- • Always wrap API calls in try-except
- • Handle specific exception types first
- • Log errors with context information
- • Implement retry logic for transient failures
Webhook Handling
Comprehensive webhook handling with signature verification, payload parsing, and validation:
Basic Signature Verification
from laneful.webhooks import WebhookHandler # Initialize webhook handler webhook_handler = WebhookHandler(webhook_secret="your-webhook-secret") # In your webhook handler payload = request.get_data(as_text=True) # Get the raw request body signature = request.headers.get('x-webhook-signature') if webhook_handler.verify_signature(payload, signature): # Process webhook data webhook_handler.process_webhook(payload) # Handle webhook events else: # Invalid signature return jsonify({'error': 'Invalid signature'}), 401
Advanced Webhook Processing
from laneful.webhooks import WebhookHandler, WebhookEvent # Initialize webhook handler with event handlers webhook_handler = WebhookHandler(webhook_secret="your-webhook-secret") # Register event handlers @webhook_handler.on("email.delivered") def handle_delivery_event(event: WebhookEvent): print(f"Email {event.message_id} delivered to {event.email}") @webhook_handler.on("email.opened") def handle_open_event(event: WebhookEvent): print(f"Email {event.message_id} opened by {event.email}") @webhook_handler.on("email.clicked") def handle_click_event(event: WebhookEvent): url = event.data.get("url") print(f"Link clicked by {event.email}: {url}") @webhook_handler.on("email.bounced") def handle_bounce_event(event: WebhookEvent): is_hard = event.data.get("is_hard") print(f"Email bounced ({'hard' if is_hard else 'soft'}) for: {event.email}") @webhook_handler.on("email.complained") def handle_spam_complaint_event(event: WebhookEvent): print(f"Spam complaint from {event.email}") @webhook_handler.on("email.unsubscribed") def handle_unsubscribe_event(event: WebhookEvent): print(f"Unsubscribe from {event.email}") # Complete webhook verification and processing workflow try: # Step 1: Get raw payload payload = request.get_data(as_text=True) # Step 2: Extract signature from headers signature = request.headers.get('x-webhook-signature') if not signature: raise ValueError("Missing webhook signature") # Step 3: Verify signature and process webhook if webhook_handler.verify_signature(payload, signature): webhook_handler.process_webhook(payload) return jsonify({'status': 'success'}) else: return jsonify({'error': 'Invalid signature'}), 401 except ValueError as e: # Payload validation error return jsonify({'error': str(e)}), 400 except Exception as e: # Other errors return jsonify({'error': str(e)}), 401
Batch Mode Support
# The WebhookHandler automatically processes both single events and batches # No need to check for batch mode - the handler manages this internally # Single event payload single_payload = '{"event_type": "email.delivered", "message_id": "123", ...}' webhook_handler.process_webhook(single_payload) # Batch event payload (multiple events in one webhook) batch_payload = '{"events": [{"event_type": "email.delivered", ...}, {"event_type": "email.opened", ...}]}' webhook_handler.process_webhook(batch_payload) # All registered event handlers will be called for each event automatically
Supported Webhook Events
Delivery Events
- •
email.delivered
- Email delivered successfully - •
email.bounced
- Email bounced (hard or soft) - •
email.failed
- Email failed to send - •
email.complained
- Recipient marked email as spam
Engagement Events
- •
email.opened
- Email opened by recipient - •
email.clicked
- Link clicked in email - •
email.unsubscribed
- Recipient unsubscribed
Webhook Features
Security
- • HMAC-SHA256 signature verification
- • Support for
sha256=
prefix - • Constant-time comparison (timing attack protection)
- • Multiple header format support
Validation
- • JSON payload structure validation
- • Required field validation
- • Event type validation
- • Email format validation
- • UUID format validation for lane_id
Ready to Get Started?
Start sending emails with Python in minutes. Check out the examples and integrate with your application.