Skip to main content

Official MailerMine SDK for Python.

Project description

MailerMine Python SDK

Official MailerMine SDK for Python — send transactional email, run campaigns, manage contacts, and read analytics with a clean, typed API.

PyPI Python License

Parity with @mailermine/node and mailermine/mailermine across all 18 resources.


Installation

pip install mailermine
poetry add mailermine
uv add mailermine

Requirements: Python 3.10+


Quick Start

from mailermine import MailerMine

client = MailerMine(
    api_key="relay_live_xxx"
)

response = client.emails.send(
    from_="info@example.com",
    to=["john@example.com"],
    subject="Hello",
    html="<h1>Hello</h1>",
)

print(response.data)

Or load credentials from the environment:

import os
from mailermine import MailerMine

client = MailerMine(api_key=os.environ["MAILERMINE_API_KEY"])

Configuration

from mailermine import MailerMine, Configuration

client = MailerMine(
    api_key="relay_live_xxx",
    base_url="https://mailermine.com/api/v1",
    timeout=30.0,
)

# Or build configuration explicitly:
config = Configuration.create(
    api_key="relay_live_xxx",
    base_url="https://mailermine.com/api/v1",
    timeout=30.0,
)
client = MailerMine(configuration=config)

Environment variables

Variable Purpose
MAILERMINE_API_KEY Bearer API key (used when api_key is omitted)
MAILERMINE_BASE_URL API base URL (default https://mailermine.com/api/v1)
MAILERMINE_TIMEOUT Request timeout in seconds (default 30)
# Reads MAILERMINE_API_KEY / MAILERMINE_BASE_URL / MAILERMINE_TIMEOUT
client = MailerMine()
Option Type Default Description
api_key str Required MailerMine API key
base_url str https://mailermine.com/api/v1 API base URL
timeout float 30.0 Request timeout in seconds
user_agent str mailermine-python/1.0.0 User-Agent header

Resources

Projects

client.projects.create(name="Production", environment="production")
client.projects.list()
client.projects.get(project_id)
client.projects.update(project_id, name="Prod")
client.projects.delete(project_id)

API Keys

client.api_keys.create(project_id, name="CI", scopes=["send"])
client.api_keys.list(project_id)
client.api_keys.get(project_id, api_key_id)
client.api_keys.update(project_id, api_key_id, name="CI Bot")
client.api_keys.rotate(project_id, api_key_id)
client.api_keys.reveal(project_id, api_key_id)
client.api_keys.delete(project_id, api_key_id)

Emails

client.emails.send(
    from_="MailerMine <hello@example.com>",
    to=["user@example.com"],
    subject="Invoice ready",
    html="<p>Your invoice is ready.</p>",
    text="Your invoice is ready.",
    reply_to="support@example.com",
    tags=["invoice"],
    metadata={"order_id": "123"},
)

client.emails.list(status="delivered", per_page=25)
client.emails.get(message_id)
client.emails.events(message_id)

Use from_ as a keyword argument (or pass "from" inside a dict) because from is reserved in Python.

Domains

created = client.domains.create(domain="mail.example.com")
domain_id = created.data["id"]

client.domains.list()
client.domains.get(domain_id)
client.domains.dns_records(domain_id)
client.domains.status(domain_id)
client.domains.verify(domain_id)
client.domains.delete(domain_id)

Templates

client.templates.create(
    name="Welcome",
    subject="Welcome {{first_name}}",
    html="<h1>Welcome {{first_name}}</h1>",
)
client.templates.list(search="welcome")
client.templates.get(template_id)
client.templates.update(template_id, subject="Hey {{first_name}}")
client.templates.preview(template_id, variables={"first_name": "John"})
client.templates.duplicate(template_id, name="Welcome (copy)")
client.templates.test(template_id, to="you@example.com")
client.templates.delete(template_id)

Contacts

client.contacts.create(email="john@example.com", first_name="John")
client.contacts.upsert(email="john@example.com", first_name="Johnny")
client.contacts.list(page=1, per_page=25)
client.contacts.get(contact_id)
client.contacts.identify("john@example.com")
client.contacts.search("john")
client.contacts.update(contact_id, last_name="Doe")
client.contacts.subscribe(contact_id)
client.contacts.unsubscribe(contact_id)
client.contacts.delete(contact_id)

Lists

client.lists.create(name="Newsletter")
client.lists.list()
client.lists.get(list_id)
client.lists.update(list_id, name="Weekly")
client.lists.add_contact(list_id, contact_ids)
client.lists.remove_contact(list_id, contact_ids)
client.lists.delete(list_id)

Segments

client.segments.create(name="Active users", rules={...})
client.segments.list()
client.segments.get(segment_id)
client.segments.update(segment_id, name="Engaged")
client.segments.preview(segment_id)
client.segments.delete(segment_id)

Tags

client.tags.create(name="vip")
client.tags.list()
client.tags.get(tag_id)
client.tags.update(tag_id, name="VIP")
client.tags.assign(contact_ids=[...], tag_ids=[...])
client.tags.remove(contact_ids=[...], tag_ids=[...])
client.tags.delete(tag_id)

Audiences

client.audiences.list()
client.audiences.get("list", audience_id)
client.audiences.create(source="list", name="Launch list")
client.audiences.contacts("list", audience_id)
client.audiences.add_contacts(audience_id, contact_ids)
client.audiences.remove_contacts(audience_id, contact_ids)

Campaigns

client.campaigns.create(name="Spring launch")
client.campaigns.list(status="draft")
client.campaigns.get(campaign_id)
client.campaigns.update(campaign_id, subject="Hello")
client.campaigns.set_template(campaign_id, template_id)
client.campaigns.set_subject(campaign_id, "Spring sale")
client.campaigns.set_sender(campaign_id, from_email="hello@example.com", from_name="Team")
client.campaigns.set_reply_to(campaign_id, "support@example.com")
client.campaigns.set_preheader(campaign_id, "Don't miss it")
client.campaigns.preview(campaign_id)
client.campaigns.render(campaign_id)
client.campaigns.validate(campaign_id)
client.campaigns.mark_ready(campaign_id)
client.campaigns.send(campaign_id)
client.campaigns.schedule(campaign_id, scheduled_at="2026-07-20T10:00:00Z")
client.campaigns.pause(campaign_id)
client.campaigns.resume(campaign_id)
client.campaigns.cancel(campaign_id)
client.campaigns.analytics(campaign_id)
client.campaigns.events(campaign_id)
client.campaigns.timeline(campaign_id)
client.campaigns.activity(campaign_id)
client.campaigns.progress(campaign_id)
client.campaigns.status(campaign_id)

Analytics

client.analytics.overview()
client.analytics.usage()
client.analytics.messages()
client.analytics.engagement()
client.analytics.campaigns()
client.analytics.domains()
client.analytics.projects()
client.analytics.providers()
client.analytics.activity()
client.analytics.opens()
client.analytics.clicks()
client.analytics.deliveries()
client.analytics.bounces()
client.analytics.complaints()
client.analytics.unsubscribes()

Events

client.events.list(event_type="delivered")
client.events.get(event_id)
client.events.timeline(message_id)
client.events.history(message_id)
client.events.message(message_id)

Messages

client.messages.list(status="delivered")
client.messages.search("invoice")
client.messages.filter(status="bounced")
client.messages.get(message_id)
client.messages.events(message_id)
client.messages.timeline(message_id)

Webhooks

client.webhooks.create(url="https://example.com/hooks/mailermine", events=["email.delivered"])
client.webhooks.list()
client.webhooks.get(webhook_id)
client.webhooks.update(webhook_id, url="https://example.com/hooks/v2")
client.webhooks.enable(webhook_id)
client.webhooks.disable(webhook_id)
client.webhooks.rotate_secret(webhook_id)
client.webhooks.test(webhook_id)
client.webhooks.deliveries(webhook_id)
client.webhooks.delivery(delivery_id)
client.webhooks.logs(webhook_id)
client.webhooks.failures(webhook_id)
client.webhooks.replay(webhook_id)
client.webhooks.retry(delivery_id)
client.webhooks.delete(webhook_id)

# Local signature verification (no network):
from mailermine import Webhooks

Webhooks.verify(raw_body, signature_header, signing_secret)

Suppressions

client.suppressions.add(email="bounce@example.com", reason="hard_bounce")
client.suppressions.list()
client.suppressions.get(suppression_id)
client.suppressions.check("bounce@example.com")
client.suppressions.restore(suppression_id)
client.suppressions.remove(suppression_id)

Imports

client.imports.create(...)
client.imports.list()
client.imports.status(import_id)
client.imports.configure(import_id, ...)
client.imports.start(import_id)

Exports

job = client.exports.create()
client.exports.status(job.data["id"])
csv_body = client.exports.download(job.data["id"])

Response Objects

Successful calls return Response or Collection — never generated OpenAPI models.

Response

response = client.emails.send(...)

response.success   # bool
response.message   # str
response.data      # primary payload (dict / list / scalar)
response.meta      # optional metadata
response.to_dict() # JSON-serializable envelope

Collection

page = client.contacts.list(page=1, per_page=25)

page.items                 # list of items on this page
page.pagination            # Pagination
len(page)                  # page size
page[0]                    # index access
for contact in page:       # iterable
    print(contact["email"])

Pagination

meta = page.pagination
meta.current_page
meta.per_page
meta.total
meta.last_page
meta.has_next_page
meta.has_previous_page

Exception Handling

from mailermine import (
    MailerMine,
    AuthenticationError,
    ValidationError,
    NotFoundError,
    PlanError,
    RateLimitError,
    ApiError,
)

client = MailerMine(api_key="relay_live_xxx")

try:
    client.emails.send(from_="hello@example.com", to="user@example.com", subject="Hi", html="<p>Hi</p>")
except ValidationError as e:
    print(e.errors)          # field -> messages
except AuthenticationError:
    print("Check your API key")
except PlanError as e:
    print(e.upgrade_url)
except NotFoundError:
    print("Missing resource")
except RateLimitError as e:
    print(e.retry_after)     # seconds, or None
except ApiError as e:
    print(e.status, e.request_id, e.body)
Exception Typical cause
AuthenticationError Invalid / missing API key (401)
PlanError Plan or scope restriction (403)
NotFoundError Missing object (404)
ValidationError Invalid payload (422)
RateLimitError Too many requests (429)
ApiError Other HTTP / transport failures
MailerMineError Base type for all SDK errors

Generated OpenAPI exceptions are never exposed.


Examples

Runnable scripts live in examples/:

File Topic
send_email.py Transactional send
campaign.py Campaign lifecycle
contacts.py Contacts + lists
analytics.py Account analytics
domains.py Domains + DNS
templates.py Templates
webhooks.py Webhooks + verify
messages.py Message history
events.py Event stream
imports.py Contact imports
exports.py Contact exports
export MAILERMINE_API_KEY=relay_live_xxx
python examples/send_email.py

Development

python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
ruff check mailermine tests
mypy mailermine
pytest
python -m build

OpenAPI client code is generated into generated/ and must not be edited by hand. See ARCHITECTURE.md, GENERATION_REPORT.md, WRAPPER_REPORT.md, and PARITY_REPORT.md.


Support

License

MIT — see LICENSE.

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

mailermine-1.0.0.tar.gz (163.1 kB view details)

Uploaded Source

Built Distribution

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

mailermine-1.0.0-py3-none-any.whl (498.0 kB view details)

Uploaded Python 3

File details

Details for the file mailermine-1.0.0.tar.gz.

File metadata

  • Download URL: mailermine-1.0.0.tar.gz
  • Upload date:
  • Size: 163.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for mailermine-1.0.0.tar.gz
Algorithm Hash digest
SHA256 ae03e936d16dd1480f5eb6e13ecc0a5564fa9abe4bed3f64544ad5871bdbb150
MD5 e2e7502c97d643ee055bab51d4777778
BLAKE2b-256 82406a2603e296a47a19ea280127a17169a829e6ed0b6204dd77aea485708487

See more details on using hashes here.

File details

Details for the file mailermine-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: mailermine-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 498.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for mailermine-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0ac5b0e4c0a276b395b72579adae88f7a3c747410338d17e9f1592c551b03add
MD5 be550cefcb5049a2686cfd175bdff883
BLAKE2b-256 06988b429677af35cee576acda7ed88688513b7b1b216c83cd097cc9887ef1c4

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