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.1.tar.gz (77.3 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.1-py3-none-any.whl (11.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: py_mailnow-0.1.1.tar.gz
  • Upload date:
  • Size: 77.3 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.1.tar.gz
Algorithm Hash digest
SHA256 f529b12961222911d59eb48a9b06ff12dd22e49a6c6f4127179430dd5581022a
MD5 f424b896152805fc7f9ccb7c37935061
BLAKE2b-256 bbf03cd41a2415314fa895bd6c3ed20fcc9016e76207fe735eaf4f74da288cf6

See more details on using hashes here.

File details

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

File metadata

  • Download URL: py_mailnow-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 11.1 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 19fec350dea672ad56b88de9c10758c4c60c8995f679b513d356dd0c4b679797
MD5 bc5347f0bb3a0efd3b6e1464ab5f23a1
BLAKE2b-256 1e8f7f92ebdead5b24f5c436b56a926915e6630e4e9fd88eec71a31a030bd298

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