Skip to content

Provider Configuration

This guide covers all configuration options for MailgunClient and TwilioSmsClient, along with the error hierarchy for each provider.

Mailgun

MailgunClient sends email via the Mailgun HTTP API.

Parameters

Parameter Type Required Description
domain str Yes Mailgun sending domain (e.g. mg.example.com).
sender_email str Yes Email address used in the From header.
sender_display_name str Yes Display name used in the From header.
api_key str \| None Conditionally Mailgun API key. Required unless http_client is pre-authenticated.
http_client httpx.AsyncClient \| None Conditionally Pre-configured async HTTP client. Use instead of api_key for custom auth or transport.
base_url str No Mailgun API base URL. Defaults to the EU endpoint (https://api.eu.mailgun.net/v3).
default_subject str \| None No Fallback subject for emails where NotificationContent.subject is not set.

Minimal example

from notificator.mail import MailgunClient

client = MailgunClient(
    domain="mg.example.com",
    api_key="key-...",
    sender_email="no-reply@example.com",
    sender_display_name="My Service",
)

US region

Mailgun hosts US customers on a different API endpoint. Override base_url if your domain is registered in the US region:

client = MailgunClient(
    domain="mg.example.com",
    api_key="key-...",
    sender_email="no-reply@example.com",
    sender_display_name="My Service",
    base_url="https://api.mailgun.net/v3",  # US region
)

Custom HTTP client

Pass a pre-configured httpx.AsyncClient to control timeouts, proxies, or connection pool settings. When using this option, either include auth in the client or also pass api_key:

import httpx
from notificator.mail import MailgunClient

http_client = httpx.AsyncClient(
    auth=("api", "key-..."),
    timeout=httpx.Timeout(10.0),
)

client = MailgunClient(
    domain="mg.example.com",
    sender_email="no-reply@example.com",
    sender_display_name="My Service",
    http_client=http_client,
)

Error hierarchy

NotificationError
└── MailNotificationError
    ├── MissingClientAuthError      — neither api_key nor authenticated http_client provided
    ├── MalformedClientUrlError     — base_url is not a valid URL
    ├── MalformedRecipientEmailError — recipient is not a valid email address
    ├── EmailNotificationMissingSubjectError — no subject on content and no default_subject
    └── MailAPIError                — Mailgun API returned an HTTP error

Import exceptions from notificator.mail or from the unified notificator.exceptions facade:

from notificator.mail import (
    MailAPIError,
    MalformedRecipientEmailError,
    EmailNotificationMissingSubjectError,
    MissingClientAuthError,
)

Twilio

TwilioSmsClient sends SMS via the Twilio REST API.

Parameters

Parameter Type Required Description
account_sid str Yes Twilio account SID.
token str Yes Twilio auth token.
sender_phone_number PhoneNumber \| None Conditionally Sender phone number in E.164 format. Required unless messaging_service_sid is provided.
messaging_service_sid str \| None Conditionally Twilio Messaging Service SID. Use instead of sender_phone_number for number pools.
templates list[TwilioSmsTemplate \| str] \| None No Templates available to this client instance. Plain strings are treated as Content SIDs.
twilio_http_client AsyncHttpClient \| None No Custom Twilio async HTTP client for advanced transport control.

Minimal example (phone number sender)

from notificator import PhoneNumber
from notificator.sms import TwilioSmsClient

client = TwilioSmsClient(
    account_sid="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    token="your_auth_token",
    sender_phone_number=PhoneNumber("+15551234567"),
)

Messaging Service SID

Use a Messaging Service SID instead of a phone number to enable number pools, sticky sender, and other Twilio features:

client = TwilioSmsClient(
    account_sid="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    token="your_auth_token",
    messaging_service_sid="MGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
)

Registering templates

Templates must be registered when constructing the client. Pass plain Content SIDs or TwilioSmsTemplate objects:

from notificator.sms import TwilioSmsClient, TwilioSmsTemplate

client = TwilioSmsClient(
    account_sid="ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    token="your_auth_token",
    sender_phone_number=PhoneNumber("+15551234567"),
    templates=[
        "HXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",        # plain SID — template id == SID
        TwilioSmsTemplate(                           # named template with version aliases
            id="order_shipped",
            version_registry={
                "en": "HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                "pl": "HXbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
            },
        ),
    ],
)

See Templates for full details on versioned templates.

Error hierarchy

NotificationError
└── SmsNotificationError
    ├── TwilioMissingSenderIdError       — neither sender_phone_number nor messaging_service_sid provided
    ├── InvalidPhoneNumberFormatError    — phone number is not valid E.164
    ├── TemplateNotProvidedError         — template name not registered on this client instance
    ├── TemplateVersionNotAvailableError — version alias not found in the template's version_registry
    └── SmsAPIError                      — Twilio API returned an error

Import exceptions from notificator.sms or from the unified notificator.exceptions facade:

from notificator.sms import (
    SmsAPIError,
    InvalidPhoneNumberFormatError,
    TemplateNotProvidedError,
    TemplateVersionNotAvailableError,
    TwilioMissingSenderIdError,
)

Credentials management

Never hard-code API keys or auth tokens in source code. Retrieve them at runtime from your environment or secret manager:

import os
from notificator.mail import MailgunClient

client = MailgunClient(
    domain=os.environ["MAILGUN_DOMAIN"],
    api_key=os.environ["MAILGUN_API_KEY"],
    sender_email=os.environ["MAILGUN_SENDER_EMAIL"],
    sender_display_name="My Service",
)

For containerised deployments, inject secrets via environment variables or a secrets manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, etc.) rather than mounting secret files directly into the image.