Skip to main content

Python SDK for the Mailnow email API - send emails programmatically with a simple, type-safe interface

Project description

Mailnow Python SDK

A simple, type-safe Python SDK for the Mailnow email API. Send emails programmatically with just a few lines of code.

Python Version Type Checked License: MIT

Features

  • 🚀 Simple, intuitive API
  • 🔒 Type-safe with full type hints
  • ✅ Comprehensive input validation
  • 🎯 Detailed error handling
  • 📝 Extensive documentation
  • 🧪 Thoroughly tested

Installation

Install the SDK using pip:

pip install py-mailnow

Quick Start

from mailnow import MailnowClient

# Initialize the client with your API key
client = MailnowClient(api_key="mn_live_7e59df7ce4a14545b443837804ec9722")

# Send an email
response = client.send_email(
    from_email="sender@example.com",
    to_email="recipient@example.com",
    subject="Hello from Mailnow!",
    html="<h1>Welcome!</h1><p>This is your first email.</p>"
)

print(f"Email sent! Message ID: {response['message_id']}")

API Key Format

Your Mailnow API key must be in one of the following formats:

  • Production: mn_live_ followed by your unique key (e.g., mn_live_7e59df7ce4a14545b443837804ec9722)
  • Testing: mn_test_ followed by your unique key (e.g., mn_test_abc123def456)

You can find your API key in your Mailnow dashboard.

Usage Examples

Basic Email Sending

from mailnow import MailnowClient

client = MailnowClient(api_key="mn_live_7e59df7ce4a14545b443837804ec9722")

response = client.send_email(
    from_email="noreply@yourcompany.com",
    to_email="customer@example.com",
    subject="Welcome to Our Service",
    html="<h1>Welcome!</h1><p>Thanks for signing up.</p>"
)

print(response)
# Output: {'success': True, 'message_id': 'msg_abc123', 'status': 'queued'}

With Error Handling

from mailnow import (
    MailnowClient,
    MailnowError,
    MailnowValidationError,
    MailnowAuthError,
    MailnowRateLimitError,
    MailnowServerError,
    MailnowConnectionError
)

client = MailnowClient(api_key="mn_live_7e59df7ce4a14545b443837804ec9722")

try:
    response = client.send_email(
        from_email="sender@example.com",
        to_email="recipient@example.com",
        subject="Important Update",
        html="<p>Your account has been updated.</p>"
    )
    print(f"✓ Email sent successfully: {response['message_id']}")
    
except MailnowValidationError as e:
    print(f"✗ Validation error: {e}")
    # Handle invalid input (missing fields, invalid email format, etc.)
    
except MailnowAuthError as e:
    print(f"✗ Authentication error: {e}")
    # Handle invalid or expired API key
    
except MailnowRateLimitError as e:
    print(f"✗ Rate limit exceeded: {e}")
    # Implement exponential backoff or retry logic
    
except MailnowServerError as e:
    print(f"✗ Server error: {e}")
    # Retry the request after a delay
    
except MailnowConnectionError as e:
    print(f"✗ Connection error: {e}")
    # Check network connectivity
    
except MailnowError as e:
    print(f"✗ Unexpected error: {e}")
    # Catch any other SDK errors

Sending HTML Emails

from mailnow import MailnowClient

client = MailnowClient(api_key="mn_live_7e59df7ce4a14545b443837804ec9722")

html_content = """
<!DOCTYPE html>
<html>
<head>
    <style>
        body { font-family: Arial, sans-serif; }
        .header { background-color: #4CAF50; color: white; padding: 20px; }
        .content { padding: 20px; }
    </style>
</head>
<body>
    <div class="header">
        <h1>Welcome to Our Newsletter</h1>
    </div>
    <div class="content">
        <p>Hello,</p>
        <p>Thank you for subscribing to our newsletter!</p>
        <p>Best regards,<br>The Team</p>
    </div>
</body>
</html>
"""

response = client.send_email(
    from_email="newsletter@yourcompany.com",
    to_email="subscriber@example.com",
    subject="Welcome to Our Newsletter",
    html=html_content
)

Handling Multiple Recipients

from mailnow import MailnowClient, MailnowError

client = MailnowClient(api_key="mn_live_7e59df7ce4a14545b443837804ec9722")

recipients = [
    "user1@example.com",
    "user2@example.com",
    "user3@example.com"
]

for recipient in recipients:
    try:
        response = client.send_email(
            from_email="notifications@yourcompany.com",
            to_email=recipient,
            subject="System Notification",
            html="<p>This is an automated notification.</p>"
        )
        print(f"✓ Sent to {recipient}: {response['message_id']}")
    except MailnowError as e:
        print(f"✗ Failed to send to {recipient}: {e}")
        continue

Exception Types

The SDK provides detailed exception types for different error scenarios:

MailnowError

Base exception for all Mailnow SDK errors. Catch this to handle any SDK-related error.

try:
    client.send_email(...)
except MailnowError as e:
    print(f"SDK error: {e}")

MailnowValidationError

Raised when input validation fails. This includes:

  • Missing or empty required parameters (from_email, to_email, subject, html)
  • Invalid email address format
  • Invalid API key format
  • API returns 400 Bad Request
try:
    client.send_email(
        from_email="invalid-email",  # Invalid format
        to_email="user@example.com",
        subject="Test",
        html="<p>Test</p>"
    )
except MailnowValidationError as e:
    print(f"Validation error: {e}")

MailnowAuthError

Raised when authentication fails. This includes:

  • Missing or None API key
  • Empty API key
  • Invalid API key format (doesn't start with mn_live_ or mn_test_)
  • API returns 401 Unauthorized
try:
    client = MailnowClient(api_key="invalid_key")
except MailnowAuthError as e:
    print(f"Authentication error: {e}")

MailnowRateLimitError

Raised when rate limit is exceeded (API returns 429 Too Many Requests). Consider implementing exponential backoff retry logic.

import time

try:
    client.send_email(...)
except MailnowRateLimitError as e:
    print(f"Rate limit exceeded: {e}")
    time.sleep(60)  # Wait before retrying

MailnowServerError

Raised when the Mailnow API experiences an internal error (5xx status codes). Consider retrying the request after a delay.

import time

max_retries = 3
for attempt in range(max_retries):
    try:
        response = client.send_email(...)
        break
    except MailnowServerError as e:
        if attempt < max_retries - 1:
            time.sleep(2 ** attempt)  # Exponential backoff
            continue
        raise

MailnowConnectionError

Raised when network connection fails. This includes:

  • Network connection cannot be established
  • Request times out
  • DNS resolution fails
  • Any other network-level error
try:
    client.send_email(...)
except MailnowConnectionError as e:
    print(f"Connection error: {e}")
    # Check network connectivity or retry

Type Hints and mypy Compatibility

The Mailnow SDK is fully type-annotated and compatible with mypy for static type checking. All public APIs include comprehensive type hints.

Running Type Checks

# Install mypy
pip install mypy

# Run type checking on your code
mypy your_script.py

Example with Type Hints

from typing import Dict, Any
from mailnow import MailnowClient

def send_welcome_email(client: MailnowClient, user_email: str) -> Dict[str, Any]:
    """Send a welcome email to a new user."""
    return client.send_email(
        from_email="welcome@yourcompany.com",
        to_email=user_email,
        subject="Welcome!",
        html="<h1>Welcome to our platform!</h1>"
    )

# mypy will catch type errors
client: MailnowClient = MailnowClient(api_key="mn_live_abc123")
response: Dict[str, Any] = send_welcome_email(client, "user@example.com")

API Reference

MailnowClient

Main client class for interacting with the Mailnow API.

__init__(api_key: str) -> None

Initialize the Mailnow client.

Parameters:

  • api_key (str): Your Mailnow API key (format: mn_live_* or mn_test_*)

Raises:

  • MailnowAuthError: If API key is invalid or missing

send_email(from_email: str, to_email: str, subject: str, html: str) -> Dict[str, Any]

Send an email via the Mailnow API.

Parameters:

  • from_email (str): Sender email address (must be valid format)
  • to_email (str): Recipient email address (must be valid format)
  • subject (str): Email subject line (cannot be empty)
  • html (str): HTML content of the email (cannot be empty)

Returns:

  • Dict[str, Any]: Response dictionary containing:
    • success (bool): Whether the email was successfully queued
    • message_id (str): Unique identifier for the message
    • status (str): Current status (e.g., "queued")

Raises:

  • MailnowValidationError: Invalid input parameters
  • MailnowAuthError: Authentication failure
  • MailnowRateLimitError: Rate limit exceeded
  • MailnowServerError: Server error (5xx)
  • MailnowConnectionError: Network connection error

Requirements

  • Python 3.12 or higher
  • httpx >= 0.27.0

Development

Installing Development Dependencies

pip install py-mailnow[dev]

Running Tests

pytest

Running Type Checks

mypy mailnow

Code Formatting

black mailnow tests
ruff check mailnow tests

License

This project is licensed under the MIT License.

Support

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

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

py_mailnow-0.1.0.tar.gz (40.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

py_mailnow-0.1.0-py3-none-any.whl (10.8 kB view details)

Uploaded Python 3

File details

Details for the file py_mailnow-0.1.0.tar.gz.

File metadata

  • Download URL: py_mailnow-0.1.0.tar.gz
  • Upload date:
  • Size: 40.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for py_mailnow-0.1.0.tar.gz
Algorithm Hash digest
SHA256 ab1471356299a4d2028d4e86a7267607e82b618e7ab07fa62dd69cb6669384d3
MD5 256ab62f2b7969ff8a039c27c32f9313
BLAKE2b-256 fd46ba4075d4b1cfcd60d1181b8dca2f7fa5c93972cd927ce57dfbebdbaaff92

See more details on using hashes here.

File details

Details for the file py_mailnow-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: py_mailnow-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for py_mailnow-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0c857c76a5c26af786a47bd46122f4776a44ae52f42007c08e7aafbcdfd1692c
MD5 df7a31a8c0a0ccef3ab57eea14029d8d
BLAKE2b-256 377e303a492a646a437dcb03d28b726b36c32cfaab92fb0f00c33f348e35690f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page