Python client library for the Laneful API
Project description
Laneful Python Client
A Python client library for the Laneful API, providing easy email sending capabilities with support for templates, attachments, tracking, and webhooks.
Installation
The library supports flexible installation options:
# Default installation (sync client only)
pip install laneful
# Add async support to existing sync installation
pip install laneful[async]
# Async-only (no sync dependencies)
pip install laneful[async-only]
# Explicit sync support (same as default)
pip install laneful[sync]
# Full support (both sync and async)
pip install laneful[all]
Quick Start
Synchronous Usage
pip install laneful # Default installation
from laneful import LanefulClient, Email, Address
# Initialize the sync client
client = LanefulClient(
base_url="https://custom-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 test email.",
html_content="<h1>This is a test email.</h1>",
)
# Send the email
response = client.send_email(email)
print(f"Email sent successfully: {response.status}")
Asynchronous Usage
pip install laneful[async] # Add async to sync
# OR
pip install laneful[async-only] # Pure async, no sync deps
import asyncio
from laneful import AsyncLanefulClient, Email, Address
async def send_email_async():
# Initialize the async client
async with AsyncLanefulClient(
base_url="https://custom-endpoint.send.laneful.net",
auth_token="your-auth-token"
) as client:
# 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 (Async)",
text_content="This is an async test email.",
html_content="<h1>This is an async test email.</h1>",
)
# Send the email
response = await client.send_email(email)
print(f"Email sent successfully: {response.status}")
# Run the async function
asyncio.run(send_email_async())
Features
- ✅ Send single or multiple emails
- ✅ Support for plain text and HTML content
- ✅ Email templates with dynamic data
- ✅ File attachments
- ✅ Email tracking (opens, clicks, unsubscribes)
- ✅ Custom headers
- ✅ Scheduled sending
- ✅ Webhook handling
- ✅ Reply-to addresses
- ✅ Context manager support
- ✅ Type hints and mypy support
- ✅ Comprehensive error handling
API Reference
Creating Clients
Synchronous Client
from laneful import LanefulClient
client = LanefulClient(
base_url="https://custom-endpoint.laneful.net",
auth_token="your-auth-token",
timeout=30.0, # Optional: request timeout in seconds
verify_ssl=True # Optional: SSL verification
)
Asynchronous Client
from laneful import AsyncLanefulClient
# Method 1: Using async context manager (recommended)
async with AsyncLanefulClient(
base_url="https://custom-endpoint.laneful.net",
auth_token="your-auth-token",
timeout=30.0, # Optional: request timeout in seconds
verify_ssl=True # Optional: SSL verification
) as client:
# Use client here
pass
# Method 2: Manual session management
client = AsyncLanefulClient(base_url, auth_token)
try:
# Use client here
pass
finally:
await client.close()
from laneful import Email, Address, Attachment, TrackingSettings
email = Email(
from_address=Address(email="sender@example.com", name="Sender"),
to=[Address(email="recipient@example.com", name="Recipient")],
subject="Email Subject",
text_content="Plain text content", # Optional
html_content="<h1>HTML content</h1>", # Optional
cc=[Address(email="cc@example.com")], # Optional
bcc=[Address(email="bcc@example.com")], # Optional
reply_to=Address(email="reply@example.com"), # Optional
attachments=[], # Optional: List of Attachment objects
headers={"X-Custom": "value"}, # Optional
template_id="template-123", # Optional: for template emails
template_data={"name": "John"}, # Optional: template variables
send_time=1640995200, # Optional: Unix timestamp for scheduling
tracking=TrackingSettings(opens=True, clicks=True), # Optional
webhook_data={"user_id": "123"} # Optional: custom webhook data
)
Sending Emails
Single Email (Sync)
response = client.send_email(email)
print(f"Status: {response.status}")
print(f"Message ID: {response.message_id}")
Single Email (Async)
response = await client.send_email(email)
print(f"Status: {response.status}")
print(f"Message ID: {response.message_id}")
Multiple Emails (Sync)
emails = [email1, email2, email3]
responses = client.send_emails(emails)
for i, response in enumerate(responses):
print(f"Email {i+1} status: {response.status}")
Multiple Emails (Async)
emails = [email1, email2, email3]
responses = await client.send_emails(emails)
for i, response in enumerate(responses):
print(f"Email {i+1} status: {response.status}")
Concurrent Email Sending (Async Only)
import asyncio
async with AsyncLanefulClient(base_url, auth_token) as client:
# Send multiple emails concurrently
tasks = [client.send_email(email) for email in emails]
responses = await asyncio.gather(*tasks)
print(f"Sent {len(responses)} emails concurrently!")
Context Managers
# Sync context manager
with LanefulClient(base_url, auth_token) as client:
response = client.send_email(email)
print(f"Email sent: {response.status}")
# Client session automatically closed
# Async context manager
async with AsyncLanefulClient(base_url, auth_token) as client:
response = await client.send_email(email)
print(f"Email sent: {response.status}")
# Client session automatically closed
Examples
Template Email
from laneful import Email, Address, LanefulClient
client = LanefulClient("https://custom-endpoint.send.laneful.net", "your-auth-token")
email = Email(
from_address=Address(email="sender@example.com"),
to=[Address(email="user@example.com")],
subject="Welcome!",
template_id="11",
template_data={
"name": "John Doe",
"company": "Acme Corp",
"activation_link": "https://example.com/activate?token=abc123"
},
)
response = client.send_email(email)
Email with Attachments
import base64
from laneful import Attachment, Email, Address, LanefulClient
client = LanefulClient("https://custom-endpoint.send.laneful.net", "your-auth-token")
# Prepare attachment (base64 encoded content)
with open("document.pdf", "rb") as f:
content = base64.b64encode(f.read()).decode()
email = Email(
from_address=Address(email="sender@example.com"),
to=[Address(email="user@example.com")],
subject="Document Attached",
text_content="Please find the document attached.",
attachments=[
Attachment(
file_name="document.pdf",
content=content,
content_type="application/pdf",
inline_id="123",
)
],
)
response = client.send_email(email)
Scheduled Email
import time
from laneful import Email, Address, LanefulClient
client = LanefulClient("https://custom-endpoint.send.laneful.net", "your-auth-token")
# Schedule email to be sent 1 hour from now
send_time = int(time.time()) + 3600
email = Email(
from_address=Address(email="sender@example.com"),
to=[Address(email="user@example.com")],
subject="Scheduled Email",
text_content="This email was scheduled.",
send_time=send_time,
)
response = client.send_email(email)
Email with Tracking
from laneful import TrackingSettings, Address, LanefulClient, Email
client = LanefulClient("https://custom-endpoint.send.laneful.net", "your-auth-token")
email = Email(
from_address=Address(email="sender@example.com"),
to=[Address(email="user@example.com")],
subject="Tracked Email",
html_content='<h1>Tracked Email</h1><a href="https://example.com">Click me</a>',
tracking=TrackingSettings(
opens=True,
clicks=True,
unsubscribes=True
),
)
# Sync
response = client.send_email(email)
AsyncIO support
import asyncio
from laneful import AsyncLanefulClient
async def send_emails_async(emails):
async with AsyncLanefulClient("https://custom-endpoint.send.laneful.net", "your-auth-token") as client:
tasks = [client.send_email(email) for email in emails]
return await asyncio.gather(*tasks)
Webhook Handling
The library provides comprehensive webhook handling for email events:
from laneful.webhooks import WebhookHandler, WebhookEvent
webhook_payload = dict()
# Initialize webhook handler
handler = WebhookHandler(webhook_secret="your-webhook-secret")
# Register event handlers
@handler.on("email.delivered")
def handle_delivered(event: WebhookEvent):
print(f"Email {event.message_id} delivered to {event.email}")
@handler.on("email.opened")
def handle_opened(event: WebhookEvent):
print(f"Email {event.message_id} opened by {event.email}")
@handler.on("email.clicked")
def handle_clicked(event: WebhookEvent):
url = event.data.get("url")
print(f"Link clicked: {url}")
# Process webhook payload
handler.process_webhook(webhook_payload)
Error Handling
The library provides specific exception types:
from laneful.exceptions import LanefulError, LanefulAPIError, LanefulAuthError
try:
response = client.send_email(email)
except LanefulAuthError:
print("Authentication failed - check your 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}")
Development
Running Tests
# Run tests
pytest
# Run tests with coverage
pytest --cov=laneful
# Run type checking
mypy laneful/
# Run linting
ruff check laneful/
black --check laneful/
Code Formatting
# Format code
black laneful/ tests/
isort laneful/ tests/
# Check formatting
ruff check laneful/
Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Support
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file laneful-1.0.0.tar.gz.
File metadata
- Download URL: laneful-1.0.0.tar.gz
- Upload date:
- Size: 93.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c15d31750c866b2d7f4aa3d7ce424ffc53c5c63c25d854563087301a8ed9555a
|
|
| MD5 |
1f303b41622a0ffcacf5bc67fafe0723
|
|
| BLAKE2b-256 |
24bd15a52de67fd0e9b315c66913c5a94be0017074043435a55c6adcde6a7081
|
Provenance
The following attestation bundles were made for laneful-1.0.0.tar.gz:
Publisher:
release.yml on lanefulhq/laneful-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
laneful-1.0.0.tar.gz -
Subject digest:
c15d31750c866b2d7f4aa3d7ce424ffc53c5c63c25d854563087301a8ed9555a - Sigstore transparency entry: 440107449
- Sigstore integration time:
-
Permalink:
lanefulhq/laneful-python@cd2b44787d14a25948cd34a60f940918e55cea8b -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/lanefulhq
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cd2b44787d14a25948cd34a60f940918e55cea8b -
Trigger Event:
push
-
Statement type:
File details
Details for the file laneful-1.0.0-py3-none-any.whl.
File metadata
- Download URL: laneful-1.0.0-py3-none-any.whl
- Upload date:
- Size: 15.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8a0f3fc685c1092d12d72250b60161a193f99171d8a85de63556a636a52470f3
|
|
| MD5 |
ba75592dfb86a36bae816725622fb5b9
|
|
| BLAKE2b-256 |
007d9a3787a72112ee417ee68a0f884cb2192aba69c3b34ebf12cff9ca985b0f
|
Provenance
The following attestation bundles were made for laneful-1.0.0-py3-none-any.whl:
Publisher:
release.yml on lanefulhq/laneful-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
laneful-1.0.0-py3-none-any.whl -
Subject digest:
8a0f3fc685c1092d12d72250b60161a193f99171d8a85de63556a636a52470f3 - Sigstore transparency entry: 440107453
- Sigstore integration time:
-
Permalink:
lanefulhq/laneful-python@cd2b44787d14a25948cd34a60f940918e55cea8b -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/lanefulhq
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cd2b44787d14a25948cd34a60f940918e55cea8b -
Trigger Event:
push
-
Statement type: