mailgun


Namemailgun JSON
Version 1.1.0 PyPI version JSON
download
home_pageNone
SummaryPython SDK for Mailgun
upload_time2025-07-12 05:11:12
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
keywords python sdk for mailgun mailgun api python wrapper wrapper email python-wrapper transactional-emails mailgun mailgun-api
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Mailgun Python SDK

Welcome to the official Python SDK for [Mailgun](http://www.mailgun.com/)!

Check out all the resources and Python code examples in the official [Mailgun Documentation](https://documentation.mailgun.com/docs/mailgun/).

## Table of contents

- [Mailgun Python SDK](#mailgun-python-sdk)
  - [Table of contents](#table-of-contents)
  - [Compatibility](#compatibility)
  - [Requirements](#requirements)
    - [Build backend dependencies](#build-backend-dependencies)
    - [Runtime dependencies](#runtime-dependencies)
    - [Test dependencies](#test-dependencies)
  - [Installation](#installation)
    - [pip install](#pip-install)
      - [git clone & pip install locally](#git-clone--pip-install-locally)
      - [conda & make](#conda--make)
    - [For development](#for-development)
      - [Using conda](#using-conda)
  - [Overview](#overview)
    - [Base URL](#base-url)
    - [Authentication](#authentication)
    - [API Response Codes](#api-response-codes)
  - [Request examples](#request-examples)
    - [Full list of supported endpoints](#full-list-of-supported-endpoints)
    - [Messages](#messages)
      - [Send an email](#send-an-email)
      - [Send an email with attachments](#send-an-email-with-attachments)
      - [Send a scheduled message](#send-a-scheduled-message)
    - [Domains](#domains)
      - [Get domains](#get-domains)
      - [Get domains details](#get-domains-details)
      - [Create a domain](#create-a-domain)
      - [Update a domain](#update-a-domain)
      - [Domain connections](#domain-connections)
      - [Domain keys](#domain-keys)
        - [Update DKIM authority](#update-dkim-authority)
      - [Domain Tracking](#domain-tracking)
        - [Get tracking settings](#get-tracking-settings)
    - [Webhooks](#webhooks)
      - [Get all webhooks](#get-all-webhooks)
      - [Create a webhook](#create-a-webhook)
      - [Delete a webhook](#delete-a-webhook)
    - [Events](#events)
      - [Retrieves a paginated list of events](#retrieves-a-paginated-list-of-events)
      - [Get events by recipient](#get-events-by-recipient)
    - [Metrics](#metrics)
      - [Get account metrics](#get-account-metrics)
      - [Get account usage metrics](#get-account-usage-metrics)
    - [Suppressions](#suppressions)
      - [Bounces](#bounces)
        - [Create bounces](#create-bounces)
      - [Unsubscribe](#unsubscribe)
        - [View all unsubscribes](#view-all-unsubscribes)
        - [Import list of unsubscribes](#import-list-of-unsubscribes)
      - [Complaints](#complaints)
        - [Add complaints](#add-complaints)
        - [Import list of complaints](#import-list-of-complaints)
      - [Whitelists](#whitelists)
        - [Delete all whitelists](#delete-all-whitelists)
    - [Routes](#routes)
      - [Create a route](#create-a-route)
      - [Get a route by id](#get-a-route-by-id)
    - [Mailing Lists](#mailing-lists)
      - [Create a mailing list](#create-a-mailing-list)
      - [Get mailing lists members](#get-mailing-lists-members)
      - [Delete mailing lists address](#delete-mailing-lists-address)
    - [Templates](#templates)
      - [Get templates](#get-templates)
      - [Update a template](#update-a-template)
      - [Create a new template version](#create-a-new-template-version)
      - [Get all template's versions](#get-all-templates-versions)
    - [IP Pools](#ip-pools)
      - [Edit DIPP](#edit-dipp)
      - [Link an IP pool](#link-an-ip-pool)
    - [IPs](#ips)
      - [List account IPs](#list-account-ips)
      - [Delete a domain's IP](#delete-a-domains-ip)
    - [Tags](#tags)
      - [Get tags](#get-tags)
      - [Get aggregate countries](#get-aggregate-countries)
    - [Email validation](#email-validation)
      - [Create a single validation](#create-a-single-validation)
    - [Inbox placement](#inbox-placement)
      - [Get all inbox](#get-all-inbox)
  - [License](#license)
  - [Contribute](#contribute)
  - [Contributors](#contributors)

## Compatibility

This library `mailgun` officially supports the following Python versions:

- python >=3.10,\<3.14

It's tested up to 3.13 (including).

## Requirements

### Build backend dependencies

To build the `mailgun` package from the sources you need `setuptools` (as a build backend), `wheel`, and `setuptools-scm`.

### Runtime dependencies

At runtime the package requires only `requests >=2.32.4`.

### Test dependencies

For running test you need `pytest >=7.0.0` at least.
Make sure to provide the environment variables from [Authentication](#authentication).

## Installation

### pip install

Use the below code to install the Mailgun SDK for Python:

```bash
pip install mailgun
```

#### git clone & pip install locally

Use the below code to install it locally by cloning this repository:

```bash
git clone https://github.com/mailgun/mailgun-python
cd mailgun-python
```

```bash
pip install .
```

#### conda & make

Use the below code to install it locally by `conda` and `make` on Unix platforms:

```bash
make install
```

### For development

#### Using conda

on Linux or macOS:

```bash
git clone https://github.com/mailgun/mailgun-python
cd mailgun-python
```

- A basic environment with a minimum number of dependencies:

```bash
make dev
conda activate mailgun
```

- A full dev environment:

```bash
make dev-full
conda activate mailgun-dev
```

## Overview

The Mailgun API is part of the Sinch family and enables you to send, track, and receive email effortlessly.

### Base URL

All API calls referenced in our documentation start with a base URL. Mailgun allows the ability to send and receive email in both US and EU regions. Be sure to use the appropriate base URL based on which region you have created for your domain.

It is also important to note that Mailgun uses URI versioning for our API endpoints, and some endpoints may have different versions than others. Please reference the version stated in the URL for each endpoint.

For domains created in our US region the base URL is:

```sh
https://api.mailgun.net/
```

For domains created in our EU region the base URL is:

```sh
https://api.eu.mailgun.net/
```

Your Mailgun account may contain multiple sending domains. To avoid passing the domain name as a query parameter, most API URLs must include the name of the domain you are interested in:

```sh
https://api.mailgun.net/v3/mydomain.com
```

### Authentication

The Mailgun Send API uses your API key for authentication. [Grab](https://app.mailgun.com/settings/api_security) and save your Mailgun API credentials.

To run tests and examples please use virtualenv or conda environment with next environment variables:

```bash
export APIKEY="API_KEY"
export DOMAIN="DOMAIN_NAME"
export MESSAGES_FROM="Name Surname <mailgun@domain_name>"
export MESSAGES_TO="Name Surname <username@gmail.com>"
export MESSAGES_CC="Name Surname <username2@gmail.com>"
export DOMAINS_DEDICATED_IP="127.0.0.1"
export MAILLIST_ADDRESS="everyone@mailgun.domain.com"
export VALIDATION_ADDRESS_1="test1@i.ua"
export VALIDATION_ADDRESS_2="test2@gmail.com"
```

Initialize your [Mailgun](http://www.mailgun.com/) client:

```python
from mailgun.client import Client
import os

auth = ("api", os.environ["APIKEY"])
client = Client(auth=auth)
```

### API Response Codes

All of Mailgun's HTTP response codes follow standard HTTP definitions. For some additional information and troubleshooting steps, please see below.

**400** - Will typically contain a JSON response with a "message" key which contains a human readable message / action to interpret.

**403** - Auth error or access denied. Please ensure your API key is correct and that you are part of a group that has access to the desired resource.

**404** - Resource not found. NOTE: this one can be temporal as our system is an eventually-consistent system but requires diligence. If a JSON response is missing for a 404 - that's usually a sign that there was a mistake in the API request, such as a non-existing endpoint.

**429** - Mailgun does have rate limits in place to protect our system. Please retry these requests as defined in the response. In the unlikely case you encounter them and need them raised, please reach out to our support team.

**500** - Internal Error on the Mailgun side. Retries are recommended with exponential or logarithmic retry intervals. If the issue persists, please reach out to our support team.

## Request examples

### Full list of supported endpoints

> [!IMPORTANT]\
> This is a full list of supported endpoints this SDK provides [mailgun/examples](mailgun/examples)

### Messages

#### Send an email

Pass the components of the messages such as To, From, Subject, HTML and text parts, attachments, etc. Mailgun will build a MIME representation of the message and send it. Note: In order to send you must provide one of the following parameters: 'text', 'html', 'amp-html' or 'template'

```python
import os
from mailgun.client import Client

key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]
client: Client = Client(auth=("api", key))


def post_message() -> None:
    # Messages
    # POST /<domain>/messages
    data = {
        "from": os.getenv("MESSAGES_FROM", "test@test.com"),
        "to": os.getenv("MESSAGES_TO", "recipient@example.com"),
        "subject": "Hello from python!",
        "text": "Hello world!",
        "o:tag": "Python test",
    }

    req = client.messages.create(data=data, domain=domain)
    print(req.json())
```

#### Send an email with attachments

```python
import os
from pathlib import Path
from mailgun.client import Client

key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]
client: Client = Client(auth=("api", key))


def post_message() -> None:
    # Messages
    # POST /<domain>/messages
    data = {
        "from": os.getenv("MESSAGES_FROM", "test@test.com"),
        "to": os.getenv("MESSAGES_TO", "recipient@example.com"),
        "subject": "Hello from python!",
        "text": "Hello world!",
        "o:tag": "Python test",
    }

    # It is strongly recommended that you open files in binary mode.
    # Because the Content-Length header may be provided for you,
    # and if it does this value will be set to the number of bytes in the file.
    # Errors may occur if you open the file in text mode.
    files = [
        (
            "attachment",
            ("test1.txt", Path("test1.txt").read_bytes()),
        )
    ]

    req = client.messages.create(data=data, files=files, domain=domain)
    print(req.json())
```

#### Send a scheduled message

```python
def post_scheduled() -> None:
    # Scheduled message
    data = {
        "from": os.environ["MESSAGES_FROM"],
        "to": os.environ["MESSAGES_TO"],
        "cc": os.environ["MESSAGES_CC"],
        "subject": "Hello Vasyl Bodaj",
        "html": html,
        "o:deliverytime": "Thu Jan 28 2021 14:00:03 EST",
    }

    req = client.messages.create(data=data, domain=domain)
    print(req.json())
```

### Domains

#### Get domains

```python
import os
from mailgun.client import Client

key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]
client: Client = Client(auth=("api", key))


def get_domains() -> None:
    """
    GET /domains
    :return:
    """
    data = client.domainlist.get()
    print(data.json())
```

#### Get domains with filters

```python
def get_domains_with_filters() -> None:
    """
    GET /domains
    :return:
    """
    params = {"skip": 0, "limit": 1}
    data = client.domainlist.get(filters=params)
    print(data.json())
```

#### Get domains details

```python
def get_simple_domain() -> None:
    """
    GET /domains/<domain>
    :return:
    """
    domain_name = "python.test.domain4"
    data = client.domains.get(domain_name=domain_name)
    print(data.json())
```

#### Create a domain

```python
def add_domain() -> None:
    """
    POST /domains
    :return:
    """
    # Post domain
    data = {
        "name": "python.test.domain5",
        # "smtp_password": "random123456"
    }

    request = client.domains.create(data=data)
    print(request.json())
    print(request.status_code)
```

#### Update a domain

```python
def update_simple_domain() -> None:
    """
    PUT /domains/<domain>
    :return:
    """
    domain_name = "python.test.domain5"
    data = {"name": domain_name, "spam_action": "disabled"}
    request = client.domains.put(data=data, domain=domain_name)
    print(request.json())
```

#### Domain connections

```python
def get_connections() -> None:
    """
    GET /domains/<domain>/connection
    :return:
    """
    request = client.domains_connection.get(domain=domain)
    print(request.json())
```

#### Domain keys

##### Update DKIM authority

```python
def put_dkim_authority() -> None:
    """
    PUT /domains/<domain>/dkim_authority
    :return:
    """
    data = {"self": "false"}
    request = client.domains_dkimauthority.put(domain=domain, data=data)
    print(request.json())
```

#### Domain Tracking

##### Get tracking settings

```python
def get_tracking() -> None:
    """
    GET /domains/<domain>/tracking
    :return:
    """
    request = client.domains_tracking.get(domain=domain)
    print(request.json())
```

### Webhooks

#### Get all webhooks

```python
import os

from mailgun.client import Client


key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]

client: Client = Client(auth=("api", key))


def get_webhooks() -> None:
    """
    GET /domains/<domain>/webhooks
    :return:
    """
    req = client.domains_webhooks.get(domain=domain)
    print(req.json())
```

#### Create a webhook

```python
def create_webhook() -> None:
    """
    POST /domains/<domain>/webhooks
    :return:
    """
    data = {"id": "clicked", "url": ["https://facebook.com"]}
    #
    req = client.domains_webhooks.create(domain=domain, data=data)
    print(req.json())
```

#### Delete a webhook

```python
def put_webhook() -> None:
    """
    PUT /domains/<domain>/webhooks/<webhookname>
    :return:
    """
    data = {"id": "clicked", "url": ["https://facebook.com", "https://google.com"]}

    req = client.domains_webhooks_clicked.put(domain=domain, data=data)
    print(req.json())
```

### Events

#### Retrieves a paginated list of events

```python
import os

from mailgun.client import Client


key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]

client: Client = Client(auth=("api", key))


def get_domain_events() -> None:
    """
    GET /<domain>/events
    :return:
    """
    req = client.events.get(domain=domain)
    print(req.json())
```

#### Get events by recipient

```python
def events_by_recipient() -> None:
    """
    GET /<domain>/events
    :return:
    """
    params = {
        "begin": "Tue, 24 Nov 2020 09:00:00 -0000",
        "ascending": "yes",
        "limit": 10,
        "pretty": "yes",
        "recipient": os.environ["VALIDATION_ADDRESS_1"],
    }
    req = client.events.get(domain=domain, filters=params)
    print(req.json())
```

### Metrics

Mailgun collects many different events and generates event metrics which are available in your Control Panel.
This data is also available via our analytics metrics [API endpoint](https://documentation.mailgun.com/docs/mailgun/api-reference/openapi-final/tag/Metrics/#tag/Metrics).

#### Get account metrics

Get filtered metrics for an account

```python
def post_analytics_metrics() -> None:
    """
    # Metrics
    # POST /analytics/metrics
    :return:
    """

    data = {
        "start": "Sun, 08 Jun 2025 00:00:00 +0000",
        "end": "Tue, 08 Jul 2025 00:00:00 +0000",
        "resolution": "day",
        "duration": "1m",
        "dimensions": ["time"],
        "metrics": ["accepted_count", "delivered_count", "clicked_rate", "opened_rate"],
        "filter": {
            "AND": [
                {
                    "attribute": "domain",
                    "comparator": "=",
                    "values": [{"label": domain, "value": domain}],
                }
            ]
        },
        "include_subaccounts": True,
        "include_aggregates": True,
    }

    req = client.analytics_metrics.create(data=data)
    print(req.json())
```

#### Get account usage metrics

```python
def post_analytics_usage_metrics() -> None:
    """
    # Usage Metrics
    # POST /analytics/usage/metrics
    :return:
    """
    data = {
        "start": "Sun, 08 Jun 2025 00:00:00 +0000",
        "end": "Tue, 08 Jul 2025 00:00:00 +0000",
        "resolution": "day",
        "duration": "1m",
        "dimensions": ["time"],
        "metrics": [
            "accessibility_count",
            "accessibility_failed_count",
            "domain_blocklist_monitoring_count",
            "email_preview_count",
            "email_preview_failed_count",
            "email_validation_bulk_count",
            "email_validation_count",
            "email_validation_list_count",
            "email_validation_mailgun_count",
            "email_validation_mailjet_count",
            "email_validation_public_count",
            "email_validation_single_count",
            "email_validation_valid_count",
            "image_validation_count",
            "image_validation_failed_count",
            "ip_blocklist_monitoring_count",
            "link_validation_count",
            "link_validation_failed_count",
            "processed_count",
            "seed_test_count",
        ],
        "include_subaccounts": True,
        "include_aggregates": True,
    }

    req = client.analytics_usage_metrics.create(data=data)
    print(req.json())
```

### Suppressions

#### Bounces

##### Create bounces

```python
import os

from mailgun.client import Client

key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]

client: Client = Client(auth=("api", key))

def post_bounces() -> None:
"""
POST /<domain>/bounces
:return:
"""
data = {"address": "test120@gmail.com", "code": 550, "error": "Test error"}
req = client.bounces.create(data=data, domain=domain)
print(req.json())
```

#### Unsubscribe

##### View all unsubscribes

```python
def get_unsubs() -> None:
    """
    GET /<domain>/unsubscribes
    :return:
    """
    req = client.unsubscribes.get(domain=domain)
    print(req.json())
```

##### Import list of unsubscribes

> [!IMPORTANT]
> It is strongly recommended that you open files in binary mode.
> Because the Content-Length header may be provided for you,
> and if it does this value will be set to the number of bytes in the file.
> Errors may occur if you open the file in text mode.

```python
def import_list_unsubs() -> None:
    """
    POST /<domain>/unsubscribes/import, Content-Type: multipart/form-data
    :return:
    """
    files = {
        "unsubscribe2_csv": Path(
            "mailgun/doc_tests/files/mailgun_unsubscribes.csv"
        ).read_bytes()
    }
    req = client.unsubscribes_import.create(domain=domain, files=files)
    print(req.json())
```

#### Complaints

##### Add complaints

```python
def add_complaints() -> None:
    """
    POST /<domain>/complaints
    :return:
    """
    data = {"address": "bob@gmail.com", "tag": "compl_test_tag"}
    req = client.complaints.create(data=data, domain=domain)
    print(req.json())
```

##### Import list of complaints

> [!IMPORTANT]
> It is strongly recommended that you open files in binary mode.
> Because the Content-Length header may be provided for you,
> and if it does this value will be set to the number of bytes in the file.
> Errors may occur if you open the file in text mode.

```python
def import_complaint_list() -> None:
    """
    POST /<domain>/complaints/import, Content-Type: multipart/form-data
    :return:
    """
    files = {
        "complaints_csv": Path(
            "mailgun/doc_tests/files/mailgun_complaints.csv"
        ).read_bytes()
    }
    req = client.complaints_import.create(domain=domain, files=files)
    print(req.json())
```

#### Whitelists

##### Delete all whitelists

```python
def delete_all_whitelists() -> None:
    """
    DELETE /<domain>/whitelists
    :return:
    """
    req = client.whitelists.delete(domain=domain)
    print(req.json())
```

### Routes

#### Create a route

```python
import os

from mailgun.client import Client


key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]

client: Client = Client(auth=("api", key))


def post_routes() -> None:
    """
    POST /routes
    :return:
    """
    data = {
        "priority": 0,
        "description": "Sample route",
        "expression": f"match_recipient('.*@{domain}')",
        "action": ["forward('http://myhost.com/messages/')", "stop()"],
    }
    req = client.routes.create(domain=domain, data=data)
    print(req.json())
```

#### Get a route by id

```python
def get_route_by_id() -> None:
    """
    GET /routes/<id>
    :return:
    """
    req = client.routes.get(domain=domain, route_id="6012d994e8d489e24a127e79")
    print(req.json())
```

### Mailing Lists

#### Create a mailing list

```python
import os

from mailgun.client import Client


key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]

client: Client = Client(auth=("api", key))


def post_lists() -> None:
    """
    POST /lists
    :return:
    """
    data = {
        "address": f"python_sdk2@{domain}",
        "description": "Mailgun developers list",
    }

    req = client.lists.create(domain=domain, data=data)
    print(req.json())
```

#### Get mailing lists members

```python
def get_lists_members() -> None:
    """
    GET /lists/<address>/members/pages
    :return:
    """
    req = client.lists_members_pages.get(domain=domain, address=mailing_list_address)
    print(req.json())
```

#### Delete mailing lists address

```python
def delete_lists_address() -> None:
    """
    DELETE /lists/<address>
    :return:
    """
    req = client.lists.delete(domain=domain, address=f"python_sdk2@{domain}")
    print(req.json())
```

### Templates

#### Get templates

```python
import os

from mailgun.client import Client


key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]

client: Client = Client(auth=("api", key))


def get_domain_templates() -> None:
    """
    GET /<domain>/templates
    :return:
    """
    params = {"limit": 1}
    req = client.templates.get(domain=domain, filters=params)
    print(req.json())
```

#### Update a template

```python
def update_template() -> None:
    """
    PUT /<domain>/templates/<name>
    :return:
    """
    data = {"description": "new template description"}

    req = client.templates.put(data=data, domain=domain, template_name="template.name1")
    print(req.json())
```

#### Create a new template version

```python
def create_new_template_version() -> None:
    """
    POST /<domain>/templates/<template>/versions
    :return:
    """
    data = {
        "tag": "v1",
        "template": "{{fname}} {{lname}}",
        "engine": "handlebars",
        "active": "yes",
    }

    req = client.templates.create(
        data=data, domain=domain, template_name="template.name1", versions=True
    )
    print(req.json())
```

#### Get all template's versions

```python
def get_all_versions() -> None:
    """
    GET /<domain>/templates/<template>/versions
    :return:
    """
    req = client.templates.get(
        domain=domain, template_name="template.name1", versions=True
    )
    print(req.json())
```

### IP Pools

#### Edit DIPP

```python
import os

from mailgun.client import Client


key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]

client: Client = Client(auth=("api", key))


def update_ippool() -> None:
    """
    PATCH /v1/ip_pools/{pool_id}
    :return:
    """
    data = {
        "name": "test_pool3",
        "description": "Test3",
    }
    req = client.ippools.patch(
        domain=domain, data=data, pool_id="60140bc1fee3e84dec5abeeb"
    )
    print(req.json())
```

#### Link an IP pool

```python
def link_ippool() -> None:
    """
    POST /v3/domains/{domain_name}/ips
    :return:
    """
    data = {"pool_id": "60140d220859fda7bab8bb6c"}
    req = client.domains_ips.create(domain=domain, data=data)
    print(req.json())
```

### IPs

#### List account IPs

```python
import os

from mailgun.client import Client


key: str = os.environ["APIKEY"]
domain: str = os.environ["DOMAIN"]

client: Client = Client(auth=("api", key))


def get_ips() -> None:
    """
    GET /ips
    :return:
    """
    req = client.ips.get(domain=domain, filters={"dedicated": "true"})
    print(req.json())
```

#### Delete a domain's IP

```python
def delete_domain_ip() -> None:
    """
    DELETE /domains/<domain>/ips/<ip>
    :return:
    """
    request = client.domains_ips.delete(domain=domain, ip="161.38.194.10")
    print(request.json())
```

### Tags

#### Get tags

```python
def get_tags() -> None:
    """
    GET /<domain>/tags
    :return:
    """
    req = client.tags.get(domain=domain)
    print(req.json())
```

#### Get aggregate countries

```python
def get_aggregate_countries() -> None:
    """
    GET /<domain>/tags/<tag>/stats/aggregates/countries
    :return:
    """
    req = client.tags_stats_aggregates_countries.get(
        domain=domain, tag_name="September newsletter"
    )
    print(req.json())
```

### Email validation

#### Create a single validation

```python
def post_single_validate() -> None:
    """
    POST /v4/address/validate
    :return:
    """
    data = {"address": "test2@gmail.com"}
    params = {"provider_lookup": "false"}
    req = client.addressvalidate.create(domain=domain, data=data, filters=params)
    print(req.json())
```

### Inbox placement

#### Get all inbox

```python
def get_all_inbox() -> None:
    """
    GET /v3/inbox/tests
    :return:
    """
    req = client.inbox_tests.get(domain=domain)
    print(req.json())
```

## License

[Apache-2.0](https://choosealicense.com/licenses/apache-2.0/)

## Contribute

Mailgun loves developers. You can be part of this project!

This Python SDK is a great introduction to the open source world, check out the code!

Feel free to ask anything, and contribute:

- Fork the project.
- Create a new branch.
- Implement your feature or bug fix.
- Add documentation to it.
- Commit, push, open a pull request and voila.

If you have suggestions on how to improve the guides, please submit an issue in our [Official API Documentation](https://documentation.mailgun.com).

## Contributors

- [@diskovod](https://github.com/diskovod)
- [@skupriienko](https://github.com/skupriienko)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "mailgun",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": "Serhii Kupriienko <kupriienko.serhii@gmail.com>",
    "keywords": "Python SDK for Mailgun, Mailgun API Python Wrapper, wrapper, email python-wrapper, transactional-emails, mailgun, mailgun-api",
    "author": null,
    "author_email": "diskovod <diskovodik@gmail.com>, Mailgun <api@mailgun.com>",
    "download_url": "https://files.pythonhosted.org/packages/44/a4/34aa18c3a88a366893bdee26161c1482bbd96f557dbb6fbc665828f1615b/mailgun-1.1.0.tar.gz",
    "platform": null,
    "description": "# Mailgun Python SDK\n\nWelcome to the official Python SDK for [Mailgun](http://www.mailgun.com/)!\n\nCheck out all the resources and Python code examples in the official [Mailgun Documentation](https://documentation.mailgun.com/docs/mailgun/).\n\n## Table of contents\n\n- [Mailgun Python SDK](#mailgun-python-sdk)\n  - [Table of contents](#table-of-contents)\n  - [Compatibility](#compatibility)\n  - [Requirements](#requirements)\n    - [Build backend dependencies](#build-backend-dependencies)\n    - [Runtime dependencies](#runtime-dependencies)\n    - [Test dependencies](#test-dependencies)\n  - [Installation](#installation)\n    - [pip install](#pip-install)\n      - [git clone & pip install locally](#git-clone--pip-install-locally)\n      - [conda & make](#conda--make)\n    - [For development](#for-development)\n      - [Using conda](#using-conda)\n  - [Overview](#overview)\n    - [Base URL](#base-url)\n    - [Authentication](#authentication)\n    - [API Response Codes](#api-response-codes)\n  - [Request examples](#request-examples)\n    - [Full list of supported endpoints](#full-list-of-supported-endpoints)\n    - [Messages](#messages)\n      - [Send an email](#send-an-email)\n      - [Send an email with attachments](#send-an-email-with-attachments)\n      - [Send a scheduled message](#send-a-scheduled-message)\n    - [Domains](#domains)\n      - [Get domains](#get-domains)\n      - [Get domains details](#get-domains-details)\n      - [Create a domain](#create-a-domain)\n      - [Update a domain](#update-a-domain)\n      - [Domain connections](#domain-connections)\n      - [Domain keys](#domain-keys)\n        - [Update DKIM authority](#update-dkim-authority)\n      - [Domain Tracking](#domain-tracking)\n        - [Get tracking settings](#get-tracking-settings)\n    - [Webhooks](#webhooks)\n      - [Get all webhooks](#get-all-webhooks)\n      - [Create a webhook](#create-a-webhook)\n      - [Delete a webhook](#delete-a-webhook)\n    - [Events](#events)\n      - [Retrieves a paginated list of events](#retrieves-a-paginated-list-of-events)\n      - [Get events by recipient](#get-events-by-recipient)\n    - [Metrics](#metrics)\n      - [Get account metrics](#get-account-metrics)\n      - [Get account usage metrics](#get-account-usage-metrics)\n    - [Suppressions](#suppressions)\n      - [Bounces](#bounces)\n        - [Create bounces](#create-bounces)\n      - [Unsubscribe](#unsubscribe)\n        - [View all unsubscribes](#view-all-unsubscribes)\n        - [Import list of unsubscribes](#import-list-of-unsubscribes)\n      - [Complaints](#complaints)\n        - [Add complaints](#add-complaints)\n        - [Import list of complaints](#import-list-of-complaints)\n      - [Whitelists](#whitelists)\n        - [Delete all whitelists](#delete-all-whitelists)\n    - [Routes](#routes)\n      - [Create a route](#create-a-route)\n      - [Get a route by id](#get-a-route-by-id)\n    - [Mailing Lists](#mailing-lists)\n      - [Create a mailing list](#create-a-mailing-list)\n      - [Get mailing lists members](#get-mailing-lists-members)\n      - [Delete mailing lists address](#delete-mailing-lists-address)\n    - [Templates](#templates)\n      - [Get templates](#get-templates)\n      - [Update a template](#update-a-template)\n      - [Create a new template version](#create-a-new-template-version)\n      - [Get all template's versions](#get-all-templates-versions)\n    - [IP Pools](#ip-pools)\n      - [Edit DIPP](#edit-dipp)\n      - [Link an IP pool](#link-an-ip-pool)\n    - [IPs](#ips)\n      - [List account IPs](#list-account-ips)\n      - [Delete a domain's IP](#delete-a-domains-ip)\n    - [Tags](#tags)\n      - [Get tags](#get-tags)\n      - [Get aggregate countries](#get-aggregate-countries)\n    - [Email validation](#email-validation)\n      - [Create a single validation](#create-a-single-validation)\n    - [Inbox placement](#inbox-placement)\n      - [Get all inbox](#get-all-inbox)\n  - [License](#license)\n  - [Contribute](#contribute)\n  - [Contributors](#contributors)\n\n## Compatibility\n\nThis library `mailgun` officially supports the following Python versions:\n\n- python >=3.10,\\<3.14\n\nIt's tested up to 3.13 (including).\n\n## Requirements\n\n### Build backend dependencies\n\nTo build the `mailgun` package from the sources you need `setuptools` (as a build backend), `wheel`, and `setuptools-scm`.\n\n### Runtime dependencies\n\nAt runtime the package requires only `requests >=2.32.4`.\n\n### Test dependencies\n\nFor running test you need `pytest >=7.0.0` at least.\nMake sure to provide the environment variables from [Authentication](#authentication).\n\n## Installation\n\n### pip install\n\nUse the below code to install the Mailgun SDK for Python:\n\n```bash\npip install mailgun\n```\n\n#### git clone & pip install locally\n\nUse the below code to install it locally by cloning this repository:\n\n```bash\ngit clone https://github.com/mailgun/mailgun-python\ncd mailgun-python\n```\n\n```bash\npip install .\n```\n\n#### conda & make\n\nUse the below code to install it locally by `conda` and `make` on Unix platforms:\n\n```bash\nmake install\n```\n\n### For development\n\n#### Using conda\n\non Linux or macOS:\n\n```bash\ngit clone https://github.com/mailgun/mailgun-python\ncd mailgun-python\n```\n\n- A basic environment with a minimum number of dependencies:\n\n```bash\nmake dev\nconda activate mailgun\n```\n\n- A full dev environment:\n\n```bash\nmake dev-full\nconda activate mailgun-dev\n```\n\n## Overview\n\nThe Mailgun API is part of the Sinch family and enables you to send, track, and receive email effortlessly.\n\n### Base URL\n\nAll API calls referenced in our documentation start with a base URL. Mailgun allows the ability to send and receive email in both US and EU regions. Be sure to use the appropriate base URL based on which region you have created for your domain.\n\nIt is also important to note that Mailgun uses URI versioning for our API endpoints, and some endpoints may have different versions than others. Please reference the version stated in the URL for each endpoint.\n\nFor domains created in our US region the base URL is:\n\n```sh\nhttps://api.mailgun.net/\n```\n\nFor domains created in our EU region the base URL is:\n\n```sh\nhttps://api.eu.mailgun.net/\n```\n\nYour Mailgun account may contain multiple sending domains. To avoid passing the domain name as a query parameter, most API URLs must include the name of the domain you are interested in:\n\n```sh\nhttps://api.mailgun.net/v3/mydomain.com\n```\n\n### Authentication\n\nThe Mailgun Send API uses your API key for authentication. [Grab](https://app.mailgun.com/settings/api_security) and save your Mailgun API credentials.\n\nTo run tests and examples please use virtualenv or conda environment with next environment variables:\n\n```bash\nexport APIKEY=\"API_KEY\"\nexport DOMAIN=\"DOMAIN_NAME\"\nexport MESSAGES_FROM=\"Name Surname <mailgun@domain_name>\"\nexport MESSAGES_TO=\"Name Surname <username@gmail.com>\"\nexport MESSAGES_CC=\"Name Surname <username2@gmail.com>\"\nexport DOMAINS_DEDICATED_IP=\"127.0.0.1\"\nexport MAILLIST_ADDRESS=\"everyone@mailgun.domain.com\"\nexport VALIDATION_ADDRESS_1=\"test1@i.ua\"\nexport VALIDATION_ADDRESS_2=\"test2@gmail.com\"\n```\n\nInitialize your [Mailgun](http://www.mailgun.com/) client:\n\n```python\nfrom mailgun.client import Client\nimport os\n\nauth = (\"api\", os.environ[\"APIKEY\"])\nclient = Client(auth=auth)\n```\n\n### API Response Codes\n\nAll of Mailgun's HTTP response codes follow standard HTTP definitions. For some additional information and troubleshooting steps, please see below.\n\n**400** - Will typically contain a JSON response with a \"message\" key which contains a human readable message / action to interpret.\n\n**403** - Auth error or access denied. Please ensure your API key is correct and that you are part of a group that has access to the desired resource.\n\n**404** - Resource not found. NOTE: this one can be temporal as our system is an eventually-consistent system but requires diligence. If a JSON response is missing for a 404 - that's usually a sign that there was a mistake in the API request, such as a non-existing endpoint.\n\n**429** - Mailgun does have rate limits in place to protect our system. Please retry these requests as defined in the response. In the unlikely case you encounter them and need them raised, please reach out to our support team.\n\n**500** - Internal Error on the Mailgun side. Retries are recommended with exponential or logarithmic retry intervals. If the issue persists, please reach out to our support team.\n\n## Request examples\n\n### Full list of supported endpoints\n\n> [!IMPORTANT]\\\n> This is a full list of supported endpoints this SDK provides [mailgun/examples](mailgun/examples)\n\n### Messages\n\n#### Send an email\n\nPass the components of the messages such as To, From, Subject, HTML and text parts, attachments, etc. Mailgun will build a MIME representation of the message and send it. Note: In order to send you must provide one of the following parameters: 'text', 'html', 'amp-html' or 'template'\n\n```python\nimport os\nfrom mailgun.client import Client\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef post_message() -> None:\n    # Messages\n    # POST /<domain>/messages\n    data = {\n        \"from\": os.getenv(\"MESSAGES_FROM\", \"test@test.com\"),\n        \"to\": os.getenv(\"MESSAGES_TO\", \"recipient@example.com\"),\n        \"subject\": \"Hello from python!\",\n        \"text\": \"Hello world!\",\n        \"o:tag\": \"Python test\",\n    }\n\n    req = client.messages.create(data=data, domain=domain)\n    print(req.json())\n```\n\n#### Send an email with attachments\n\n```python\nimport os\nfrom pathlib import Path\nfrom mailgun.client import Client\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef post_message() -> None:\n    # Messages\n    # POST /<domain>/messages\n    data = {\n        \"from\": os.getenv(\"MESSAGES_FROM\", \"test@test.com\"),\n        \"to\": os.getenv(\"MESSAGES_TO\", \"recipient@example.com\"),\n        \"subject\": \"Hello from python!\",\n        \"text\": \"Hello world!\",\n        \"o:tag\": \"Python test\",\n    }\n\n    # It is strongly recommended that you open files in binary mode.\n    # Because the Content-Length header may be provided for you,\n    # and if it does this value will be set to the number of bytes in the file.\n    # Errors may occur if you open the file in text mode.\n    files = [\n        (\n            \"attachment\",\n            (\"test1.txt\", Path(\"test1.txt\").read_bytes()),\n        )\n    ]\n\n    req = client.messages.create(data=data, files=files, domain=domain)\n    print(req.json())\n```\n\n#### Send a scheduled message\n\n```python\ndef post_scheduled() -> None:\n    # Scheduled message\n    data = {\n        \"from\": os.environ[\"MESSAGES_FROM\"],\n        \"to\": os.environ[\"MESSAGES_TO\"],\n        \"cc\": os.environ[\"MESSAGES_CC\"],\n        \"subject\": \"Hello Vasyl Bodaj\",\n        \"html\": html,\n        \"o:deliverytime\": \"Thu Jan 28 2021 14:00:03 EST\",\n    }\n\n    req = client.messages.create(data=data, domain=domain)\n    print(req.json())\n```\n\n### Domains\n\n#### Get domains\n\n```python\nimport os\nfrom mailgun.client import Client\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef get_domains() -> None:\n    \"\"\"\n    GET /domains\n    :return:\n    \"\"\"\n    data = client.domainlist.get()\n    print(data.json())\n```\n\n#### Get domains with filters\n\n```python\ndef get_domains_with_filters() -> None:\n    \"\"\"\n    GET /domains\n    :return:\n    \"\"\"\n    params = {\"skip\": 0, \"limit\": 1}\n    data = client.domainlist.get(filters=params)\n    print(data.json())\n```\n\n#### Get domains details\n\n```python\ndef get_simple_domain() -> None:\n    \"\"\"\n    GET /domains/<domain>\n    :return:\n    \"\"\"\n    domain_name = \"python.test.domain4\"\n    data = client.domains.get(domain_name=domain_name)\n    print(data.json())\n```\n\n#### Create a domain\n\n```python\ndef add_domain() -> None:\n    \"\"\"\n    POST /domains\n    :return:\n    \"\"\"\n    # Post domain\n    data = {\n        \"name\": \"python.test.domain5\",\n        # \"smtp_password\": \"random123456\"\n    }\n\n    request = client.domains.create(data=data)\n    print(request.json())\n    print(request.status_code)\n```\n\n#### Update a domain\n\n```python\ndef update_simple_domain() -> None:\n    \"\"\"\n    PUT /domains/<domain>\n    :return:\n    \"\"\"\n    domain_name = \"python.test.domain5\"\n    data = {\"name\": domain_name, \"spam_action\": \"disabled\"}\n    request = client.domains.put(data=data, domain=domain_name)\n    print(request.json())\n```\n\n#### Domain connections\n\n```python\ndef get_connections() -> None:\n    \"\"\"\n    GET /domains/<domain>/connection\n    :return:\n    \"\"\"\n    request = client.domains_connection.get(domain=domain)\n    print(request.json())\n```\n\n#### Domain keys\n\n##### Update DKIM authority\n\n```python\ndef put_dkim_authority() -> None:\n    \"\"\"\n    PUT /domains/<domain>/dkim_authority\n    :return:\n    \"\"\"\n    data = {\"self\": \"false\"}\n    request = client.domains_dkimauthority.put(domain=domain, data=data)\n    print(request.json())\n```\n\n#### Domain Tracking\n\n##### Get tracking settings\n\n```python\ndef get_tracking() -> None:\n    \"\"\"\n    GET /domains/<domain>/tracking\n    :return:\n    \"\"\"\n    request = client.domains_tracking.get(domain=domain)\n    print(request.json())\n```\n\n### Webhooks\n\n#### Get all webhooks\n\n```python\nimport os\n\nfrom mailgun.client import Client\n\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\n\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef get_webhooks() -> None:\n    \"\"\"\n    GET /domains/<domain>/webhooks\n    :return:\n    \"\"\"\n    req = client.domains_webhooks.get(domain=domain)\n    print(req.json())\n```\n\n#### Create a webhook\n\n```python\ndef create_webhook() -> None:\n    \"\"\"\n    POST /domains/<domain>/webhooks\n    :return:\n    \"\"\"\n    data = {\"id\": \"clicked\", \"url\": [\"https://facebook.com\"]}\n    #\n    req = client.domains_webhooks.create(domain=domain, data=data)\n    print(req.json())\n```\n\n#### Delete a webhook\n\n```python\ndef put_webhook() -> None:\n    \"\"\"\n    PUT /domains/<domain>/webhooks/<webhookname>\n    :return:\n    \"\"\"\n    data = {\"id\": \"clicked\", \"url\": [\"https://facebook.com\", \"https://google.com\"]}\n\n    req = client.domains_webhooks_clicked.put(domain=domain, data=data)\n    print(req.json())\n```\n\n### Events\n\n#### Retrieves a paginated list of events\n\n```python\nimport os\n\nfrom mailgun.client import Client\n\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\n\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef get_domain_events() -> None:\n    \"\"\"\n    GET /<domain>/events\n    :return:\n    \"\"\"\n    req = client.events.get(domain=domain)\n    print(req.json())\n```\n\n#### Get events by recipient\n\n```python\ndef events_by_recipient() -> None:\n    \"\"\"\n    GET /<domain>/events\n    :return:\n    \"\"\"\n    params = {\n        \"begin\": \"Tue, 24 Nov 2020 09:00:00 -0000\",\n        \"ascending\": \"yes\",\n        \"limit\": 10,\n        \"pretty\": \"yes\",\n        \"recipient\": os.environ[\"VALIDATION_ADDRESS_1\"],\n    }\n    req = client.events.get(domain=domain, filters=params)\n    print(req.json())\n```\n\n### Metrics\n\nMailgun collects many different events and generates event metrics which are available in your Control Panel.\nThis data is also available via our analytics metrics [API endpoint](https://documentation.mailgun.com/docs/mailgun/api-reference/openapi-final/tag/Metrics/#tag/Metrics).\n\n#### Get account metrics\n\nGet filtered metrics for an account\n\n```python\ndef post_analytics_metrics() -> None:\n    \"\"\"\n    # Metrics\n    # POST /analytics/metrics\n    :return:\n    \"\"\"\n\n    data = {\n        \"start\": \"Sun, 08 Jun 2025 00:00:00 +0000\",\n        \"end\": \"Tue, 08 Jul 2025 00:00:00 +0000\",\n        \"resolution\": \"day\",\n        \"duration\": \"1m\",\n        \"dimensions\": [\"time\"],\n        \"metrics\": [\"accepted_count\", \"delivered_count\", \"clicked_rate\", \"opened_rate\"],\n        \"filter\": {\n            \"AND\": [\n                {\n                    \"attribute\": \"domain\",\n                    \"comparator\": \"=\",\n                    \"values\": [{\"label\": domain, \"value\": domain}],\n                }\n            ]\n        },\n        \"include_subaccounts\": True,\n        \"include_aggregates\": True,\n    }\n\n    req = client.analytics_metrics.create(data=data)\n    print(req.json())\n```\n\n#### Get account usage metrics\n\n```python\ndef post_analytics_usage_metrics() -> None:\n    \"\"\"\n    # Usage Metrics\n    # POST /analytics/usage/metrics\n    :return:\n    \"\"\"\n    data = {\n        \"start\": \"Sun, 08 Jun 2025 00:00:00 +0000\",\n        \"end\": \"Tue, 08 Jul 2025 00:00:00 +0000\",\n        \"resolution\": \"day\",\n        \"duration\": \"1m\",\n        \"dimensions\": [\"time\"],\n        \"metrics\": [\n            \"accessibility_count\",\n            \"accessibility_failed_count\",\n            \"domain_blocklist_monitoring_count\",\n            \"email_preview_count\",\n            \"email_preview_failed_count\",\n            \"email_validation_bulk_count\",\n            \"email_validation_count\",\n            \"email_validation_list_count\",\n            \"email_validation_mailgun_count\",\n            \"email_validation_mailjet_count\",\n            \"email_validation_public_count\",\n            \"email_validation_single_count\",\n            \"email_validation_valid_count\",\n            \"image_validation_count\",\n            \"image_validation_failed_count\",\n            \"ip_blocklist_monitoring_count\",\n            \"link_validation_count\",\n            \"link_validation_failed_count\",\n            \"processed_count\",\n            \"seed_test_count\",\n        ],\n        \"include_subaccounts\": True,\n        \"include_aggregates\": True,\n    }\n\n    req = client.analytics_usage_metrics.create(data=data)\n    print(req.json())\n```\n\n### Suppressions\n\n#### Bounces\n\n##### Create bounces\n\n```python\nimport os\n\nfrom mailgun.client import Client\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\n\nclient: Client = Client(auth=(\"api\", key))\n\ndef post_bounces() -> None:\n\"\"\"\nPOST /<domain>/bounces\n:return:\n\"\"\"\ndata = {\"address\": \"test120@gmail.com\", \"code\": 550, \"error\": \"Test error\"}\nreq = client.bounces.create(data=data, domain=domain)\nprint(req.json())\n```\n\n#### Unsubscribe\n\n##### View all unsubscribes\n\n```python\ndef get_unsubs() -> None:\n    \"\"\"\n    GET /<domain>/unsubscribes\n    :return:\n    \"\"\"\n    req = client.unsubscribes.get(domain=domain)\n    print(req.json())\n```\n\n##### Import list of unsubscribes\n\n> [!IMPORTANT]\n> It is strongly recommended that you open files in binary mode.\n> Because the Content-Length header may be provided for you,\n> and if it does this value will be set to the number of bytes in the file.\n> Errors may occur if you open the file in text mode.\n\n```python\ndef import_list_unsubs() -> None:\n    \"\"\"\n    POST /<domain>/unsubscribes/import, Content-Type: multipart/form-data\n    :return:\n    \"\"\"\n    files = {\n        \"unsubscribe2_csv\": Path(\n            \"mailgun/doc_tests/files/mailgun_unsubscribes.csv\"\n        ).read_bytes()\n    }\n    req = client.unsubscribes_import.create(domain=domain, files=files)\n    print(req.json())\n```\n\n#### Complaints\n\n##### Add complaints\n\n```python\ndef add_complaints() -> None:\n    \"\"\"\n    POST /<domain>/complaints\n    :return:\n    \"\"\"\n    data = {\"address\": \"bob@gmail.com\", \"tag\": \"compl_test_tag\"}\n    req = client.complaints.create(data=data, domain=domain)\n    print(req.json())\n```\n\n##### Import list of complaints\n\n> [!IMPORTANT]\n> It is strongly recommended that you open files in binary mode.\n> Because the Content-Length header may be provided for you,\n> and if it does this value will be set to the number of bytes in the file.\n> Errors may occur if you open the file in text mode.\n\n```python\ndef import_complaint_list() -> None:\n    \"\"\"\n    POST /<domain>/complaints/import, Content-Type: multipart/form-data\n    :return:\n    \"\"\"\n    files = {\n        \"complaints_csv\": Path(\n            \"mailgun/doc_tests/files/mailgun_complaints.csv\"\n        ).read_bytes()\n    }\n    req = client.complaints_import.create(domain=domain, files=files)\n    print(req.json())\n```\n\n#### Whitelists\n\n##### Delete all whitelists\n\n```python\ndef delete_all_whitelists() -> None:\n    \"\"\"\n    DELETE /<domain>/whitelists\n    :return:\n    \"\"\"\n    req = client.whitelists.delete(domain=domain)\n    print(req.json())\n```\n\n### Routes\n\n#### Create a route\n\n```python\nimport os\n\nfrom mailgun.client import Client\n\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\n\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef post_routes() -> None:\n    \"\"\"\n    POST /routes\n    :return:\n    \"\"\"\n    data = {\n        \"priority\": 0,\n        \"description\": \"Sample route\",\n        \"expression\": f\"match_recipient('.*@{domain}')\",\n        \"action\": [\"forward('http://myhost.com/messages/')\", \"stop()\"],\n    }\n    req = client.routes.create(domain=domain, data=data)\n    print(req.json())\n```\n\n#### Get a route by id\n\n```python\ndef get_route_by_id() -> None:\n    \"\"\"\n    GET /routes/<id>\n    :return:\n    \"\"\"\n    req = client.routes.get(domain=domain, route_id=\"6012d994e8d489e24a127e79\")\n    print(req.json())\n```\n\n### Mailing Lists\n\n#### Create a mailing list\n\n```python\nimport os\n\nfrom mailgun.client import Client\n\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\n\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef post_lists() -> None:\n    \"\"\"\n    POST /lists\n    :return:\n    \"\"\"\n    data = {\n        \"address\": f\"python_sdk2@{domain}\",\n        \"description\": \"Mailgun developers list\",\n    }\n\n    req = client.lists.create(domain=domain, data=data)\n    print(req.json())\n```\n\n#### Get mailing lists members\n\n```python\ndef get_lists_members() -> None:\n    \"\"\"\n    GET /lists/<address>/members/pages\n    :return:\n    \"\"\"\n    req = client.lists_members_pages.get(domain=domain, address=mailing_list_address)\n    print(req.json())\n```\n\n#### Delete mailing lists address\n\n```python\ndef delete_lists_address() -> None:\n    \"\"\"\n    DELETE /lists/<address>\n    :return:\n    \"\"\"\n    req = client.lists.delete(domain=domain, address=f\"python_sdk2@{domain}\")\n    print(req.json())\n```\n\n### Templates\n\n#### Get templates\n\n```python\nimport os\n\nfrom mailgun.client import Client\n\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\n\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef get_domain_templates() -> None:\n    \"\"\"\n    GET /<domain>/templates\n    :return:\n    \"\"\"\n    params = {\"limit\": 1}\n    req = client.templates.get(domain=domain, filters=params)\n    print(req.json())\n```\n\n#### Update a template\n\n```python\ndef update_template() -> None:\n    \"\"\"\n    PUT /<domain>/templates/<name>\n    :return:\n    \"\"\"\n    data = {\"description\": \"new template description\"}\n\n    req = client.templates.put(data=data, domain=domain, template_name=\"template.name1\")\n    print(req.json())\n```\n\n#### Create a new template version\n\n```python\ndef create_new_template_version() -> None:\n    \"\"\"\n    POST /<domain>/templates/<template>/versions\n    :return:\n    \"\"\"\n    data = {\n        \"tag\": \"v1\",\n        \"template\": \"{{fname}} {{lname}}\",\n        \"engine\": \"handlebars\",\n        \"active\": \"yes\",\n    }\n\n    req = client.templates.create(\n        data=data, domain=domain, template_name=\"template.name1\", versions=True\n    )\n    print(req.json())\n```\n\n#### Get all template's versions\n\n```python\ndef get_all_versions() -> None:\n    \"\"\"\n    GET /<domain>/templates/<template>/versions\n    :return:\n    \"\"\"\n    req = client.templates.get(\n        domain=domain, template_name=\"template.name1\", versions=True\n    )\n    print(req.json())\n```\n\n### IP Pools\n\n#### Edit DIPP\n\n```python\nimport os\n\nfrom mailgun.client import Client\n\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\n\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef update_ippool() -> None:\n    \"\"\"\n    PATCH /v1/ip_pools/{pool_id}\n    :return:\n    \"\"\"\n    data = {\n        \"name\": \"test_pool3\",\n        \"description\": \"Test3\",\n    }\n    req = client.ippools.patch(\n        domain=domain, data=data, pool_id=\"60140bc1fee3e84dec5abeeb\"\n    )\n    print(req.json())\n```\n\n#### Link an IP pool\n\n```python\ndef link_ippool() -> None:\n    \"\"\"\n    POST /v3/domains/{domain_name}/ips\n    :return:\n    \"\"\"\n    data = {\"pool_id\": \"60140d220859fda7bab8bb6c\"}\n    req = client.domains_ips.create(domain=domain, data=data)\n    print(req.json())\n```\n\n### IPs\n\n#### List account IPs\n\n```python\nimport os\n\nfrom mailgun.client import Client\n\n\nkey: str = os.environ[\"APIKEY\"]\ndomain: str = os.environ[\"DOMAIN\"]\n\nclient: Client = Client(auth=(\"api\", key))\n\n\ndef get_ips() -> None:\n    \"\"\"\n    GET /ips\n    :return:\n    \"\"\"\n    req = client.ips.get(domain=domain, filters={\"dedicated\": \"true\"})\n    print(req.json())\n```\n\n#### Delete a domain's IP\n\n```python\ndef delete_domain_ip() -> None:\n    \"\"\"\n    DELETE /domains/<domain>/ips/<ip>\n    :return:\n    \"\"\"\n    request = client.domains_ips.delete(domain=domain, ip=\"161.38.194.10\")\n    print(request.json())\n```\n\n### Tags\n\n#### Get tags\n\n```python\ndef get_tags() -> None:\n    \"\"\"\n    GET /<domain>/tags\n    :return:\n    \"\"\"\n    req = client.tags.get(domain=domain)\n    print(req.json())\n```\n\n#### Get aggregate countries\n\n```python\ndef get_aggregate_countries() -> None:\n    \"\"\"\n    GET /<domain>/tags/<tag>/stats/aggregates/countries\n    :return:\n    \"\"\"\n    req = client.tags_stats_aggregates_countries.get(\n        domain=domain, tag_name=\"September newsletter\"\n    )\n    print(req.json())\n```\n\n### Email validation\n\n#### Create a single validation\n\n```python\ndef post_single_validate() -> None:\n    \"\"\"\n    POST /v4/address/validate\n    :return:\n    \"\"\"\n    data = {\"address\": \"test2@gmail.com\"}\n    params = {\"provider_lookup\": \"false\"}\n    req = client.addressvalidate.create(domain=domain, data=data, filters=params)\n    print(req.json())\n```\n\n### Inbox placement\n\n#### Get all inbox\n\n```python\ndef get_all_inbox() -> None:\n    \"\"\"\n    GET /v3/inbox/tests\n    :return:\n    \"\"\"\n    req = client.inbox_tests.get(domain=domain)\n    print(req.json())\n```\n\n## License\n\n[Apache-2.0](https://choosealicense.com/licenses/apache-2.0/)\n\n## Contribute\n\nMailgun loves developers. You can be part of this project!\n\nThis Python SDK is a great introduction to the open source world, check out the code!\n\nFeel free to ask anything, and contribute:\n\n- Fork the project.\n- Create a new branch.\n- Implement your feature or bug fix.\n- Add documentation to it.\n- Commit, push, open a pull request and voila.\n\nIf you have suggestions on how to improve the guides, please submit an issue in our [Official API Documentation](https://documentation.mailgun.com).\n\n## Contributors\n\n- [@diskovod](https://github.com/diskovod)\n- [@skupriienko](https://github.com/skupriienko)\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Python SDK for Mailgun",
    "version": "1.1.0",
    "project_urls": {
        "Documentation": "https://documentation.mailgun.com",
        "Homepage": "https://www.mailgun.com",
        "Issue Tracker": "https://github.com/mailgun/mailgun-python/issues",
        "Repository": "https://github.com/mailgun/mailgun-python"
    },
    "split_keywords": [
        "python sdk for mailgun",
        " mailgun api python wrapper",
        " wrapper",
        " email python-wrapper",
        " transactional-emails",
        " mailgun",
        " mailgun-api"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b3fa72e03e9581f05b4b17f96a81072f9f1a0a802077bee155b5a3490441c1ea",
                "md5": "0f312851cb2851db0d96cc81cea987da",
                "sha256": "e23dda2330cb7e4a84472b7c20a7abdc478f5d4406c8dd790dd74dd576172022"
            },
            "downloads": -1,
            "filename": "mailgun-1.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "0f312851cb2851db0d96cc81cea987da",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 49630,
            "upload_time": "2025-07-12T05:11:11",
            "upload_time_iso_8601": "2025-07-12T05:11:11.494206Z",
            "url": "https://files.pythonhosted.org/packages/b3/fa/72e03e9581f05b4b17f96a81072f9f1a0a802077bee155b5a3490441c1ea/mailgun-1.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "44a434aa18c3a88a366893bdee26161c1482bbd96f557dbb6fbc665828f1615b",
                "md5": "d49cae59c9d71ecfe65a438424fe5881",
                "sha256": "6fd2995be7e704e5c5628872fc978e659d0145d9d741f3d170e934266991a4f1"
            },
            "downloads": -1,
            "filename": "mailgun-1.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "d49cae59c9d71ecfe65a438424fe5881",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 60549,
            "upload_time": "2025-07-12T05:11:12",
            "upload_time_iso_8601": "2025-07-12T05:11:12.914533Z",
            "url": "https://files.pythonhosted.org/packages/44/a4/34aa18c3a88a366893bdee26161c1482bbd96f557dbb6fbc665828f1615b/mailgun-1.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-12 05:11:12",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "mailgun",
    "github_project": "mailgun-python",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "mailgun"
}
        
Elapsed time: 1.17337s