Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export MAILTRAP_ACCOUNT_ID="op://Mailtrap Dev/Mailtrap SDK Dev API Key/account_id"
export MAILTRAP_ORGANIZATION_ID="op://Mailtrap Dev/Mailtrap SDK Dev API Key/organization_id"
export MAILTRAP_API_KEY="op://Mailtrap Dev/Mailtrap SDK Dev API Key/account_api_token"
export MAILTRAP_ORGANIZATION_API_KEY="op://Mailtrap Dev/Mailtrap SDK Dev API Key/organization_api_token"
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
python 3.9.18
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ The same situation applies to both `client.batch_send()` and `client.sending_api
### Sending Domains API:
- Sending Domains – [`sending_domains/sending_domains.py`](examples/sending_domains/sending_domains.py)

### Webhooks API:
- Webhooks management – [`webhooks/webhooks.py`](examples/webhooks/webhooks.py)

### Suppressions API:
- Suppressions (find & delete) – [`suppressions/suppressions.py`](examples/suppressions/suppressions.py)

Expand All @@ -256,9 +259,13 @@ The same situation applies to both `client.batch_send()` and `client.sending_api
### General API:
- Account Accesses management – [`general/account_accesses.py`](examples/general/account_accesses.py)
- Accounts info – [`general/accounts.py`](examples/general/accounts.py)
- API Tokens management – [`general/api_tokens.py`](examples/general/api_tokens.py)
- Billing info – [`general/billing.py`](examples/general/billing.py)
- Permissions listing – [`general/permissions.py`](examples/general/permissions.py)

### Organizations API:
- Sub-Accounts management – [`organizations/sub_accounts.py`](examples/organizations/sub_accounts.py)

## Contributing

Bug reports and pull requests are welcome on [GitHub](https://github.com/mailtrap/mailtrap-python). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](CODE_OF_CONDUCT.md).
Expand Down
67 changes: 67 additions & 0 deletions examples/general/api_tokens.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import mailtrap as mt
from mailtrap.models.api_tokens import ApiToken
from mailtrap.models.api_tokens import ApiTokenWithToken
from mailtrap.models.common import DeletedObject

API_TOKEN = "YOUR_API_TOKEN"
ACCOUNT_ID = "YOUR_ACCOUNT_ID"

client = mt.MailtrapClient(token=API_TOKEN)
api_tokens_api = client.general_api.api_tokens


def list_api_tokens(account_id: int) -> list[ApiToken]:
return api_tokens_api.get_list(account_id=account_id)


def get_api_token(account_id: int, api_token_id: int) -> ApiToken:
return api_tokens_api.get_by_id(
account_id=account_id, api_token_id=api_token_id
)


def create_api_token(account_id: int) -> ApiTokenWithToken:
# The full token value is only returned once on the response — store it securely.
return api_tokens_api.create(
account_id=account_id,
token_params=mt.CreateApiTokenParams(
name="My API Token",
resources=[
mt.ApiTokenResource(
resource_type="account",
resource_id=account_id,
access_level=100,
)
],
),
)


def reset_api_token(account_id: int, api_token_id: int) -> ApiTokenWithToken:
# The reset response includes the new full token value once — store it securely.
return api_tokens_api.reset(
account_id=account_id, api_token_id=api_token_id
)


def delete_api_token(account_id: int, api_token_id: int) -> DeletedObject:
return api_tokens_api.delete(
account_id=account_id, api_token_id=api_token_id
)


if __name__ == "__main__":
tokens = list_api_tokens(ACCOUNT_ID)
print(tokens)

created = create_api_token(ACCOUNT_ID)
print(created)

fetched = get_api_token(ACCOUNT_ID, created.id)
print(fetched)

reset = reset_api_token(ACCOUNT_ID, created.id)
print(reset)

deleted = delete_api_token(ACCOUNT_ID, reset.id)
print(deleted)
Empty file.
24 changes: 24 additions & 0 deletions examples/organizations/sub_accounts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import mailtrap as mt
from mailtrap.models.organizations import SubAccount

API_TOKEN = "YOUR_API_TOKEN"
ORGANIZATION_ID = "YOUR_ORGANIZATION_ID"

client = mt.MailtrapClient(token=API_TOKEN, organization_id=ORGANIZATION_ID)
sub_accounts_api = client.organizations_api.sub_accounts


def list_sub_accounts() -> list[SubAccount]:
return sub_accounts_api.get_list()


def create_sub_account(name: str) -> SubAccount:
return sub_accounts_api.create(mt.CreateSubAccountParams(name=name))


if __name__ == "__main__":
sub_accounts = list_sub_accounts()
print(sub_accounts)

created = create_sub_account("New Team Account")
print(created)
Empty file added examples/webhooks/__init__.py
Empty file.
59 changes: 59 additions & 0 deletions examples/webhooks/webhooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import mailtrap as mt
from mailtrap.models.common import DeletedObject
from mailtrap.models.webhooks import Webhook
from mailtrap.models.webhooks import WebhookWithSecret

API_TOKEN = "YOUR_API_TOKEN"
ACCOUNT_ID = "YOUR_ACCOUNT_ID"

client = mt.MailtrapClient(token=API_TOKEN, account_id=ACCOUNT_ID)
webhooks_api = client.webhooks_api.webhooks


def list_webhooks() -> list[Webhook]:
return webhooks_api.get_list()


def get_webhook(webhook_id: int) -> Webhook:
return webhooks_api.get_by_id(webhook_id=webhook_id)


def create_webhook() -> WebhookWithSecret:
# The signing_secret is only returned once on creation — store it
# securely and use it to verify webhook signatures (HMAC SHA-256).
return webhooks_api.create(
mt.CreateWebhookParams(
url="https://example.com/mailtrap/webhooks",
webhook_type="email_sending",
sending_stream="transactional",
event_types=["delivery", "bounce"],
)
)


def update_webhook(webhook_id: int) -> Webhook:
return webhooks_api.update(
webhook_id=webhook_id,
webhook_params=mt.UpdateWebhookParams(active=False),
)


def delete_webhook(webhook_id: int) -> DeletedObject:
return webhooks_api.delete(webhook_id=webhook_id)


if __name__ == "__main__":
webhooks = list_webhooks()
print(webhooks)

created = create_webhook()
print(created)

fetched = get_webhook(created.id)
print(fetched)

updated = update_webhook(created.id)
print(updated)

deleted = delete_webhook(created.id)
print(deleted)
5 changes: 5 additions & 0 deletions mailtrap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from .exceptions import ClientConfigurationError
from .exceptions import MailtrapError
from .models.accounts import AccountAccessFilterParams
from .models.api_tokens import ApiTokenResource
from .models.api_tokens import CreateApiTokenParams
from .models.contacts import ContactEventParams
from .models.contacts import ContactExportFilter
from .models.contacts import ContactListParams
Expand All @@ -31,10 +33,13 @@
from .models.mail import Mail
from .models.mail import MailFromTemplate
from .models.messages import UpdateEmailMessageParams
from .models.organizations import CreateSubAccountParams
from .models.permissions import PermissionResourceParams
from .models.projects import ProjectParams
from .models.sending_domains import CreateSendingDomainParams
from .models.sending_domains import SendSetupInstructionsParams
from .models.stats import StatsFilterParams
from .models.templates import CreateEmailTemplateParams
from .models.templates import UpdateEmailTemplateParams
from .models.webhooks import CreateWebhookParams
from .models.webhooks import UpdateWebhookParams
5 changes: 5 additions & 0 deletions mailtrap/api/general.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from mailtrap.api.resources.account_accesses import AccountAccessesApi
from mailtrap.api.resources.accounts import AccountsApi
from mailtrap.api.resources.api_tokens import ApiTokensApi
from mailtrap.api.resources.billing import BillingApi
from mailtrap.api.resources.permissions import PermissionsApi
from mailtrap.http import HttpClient
Expand All @@ -17,6 +18,10 @@ def accounts(self) -> AccountsApi:
def account_accesses(self) -> AccountAccessesApi:
return AccountAccessesApi(client=self._client)

@property
def api_tokens(self) -> ApiTokensApi:
return ApiTokensApi(client=self._client)

@property
def billing(self) -> BillingApi:
return BillingApi(client=self._client)
Expand Down
14 changes: 14 additions & 0 deletions mailtrap/api/organizations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from mailtrap.api.resources.sub_accounts import SubAccountsApi
from mailtrap.http import HttpClient


class OrganizationsBaseApi:
def __init__(self, client: HttpClient, organization_id: str) -> None:
self._organization_id = organization_id
self._client = client

@property
def sub_accounts(self) -> SubAccountsApi:
return SubAccountsApi(
organization_id=self._organization_id, client=self._client
)
63 changes: 63 additions & 0 deletions mailtrap/api/resources/api_tokens.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
from typing import Optional

from mailtrap.http import HttpClient
from mailtrap.models.api_tokens import ApiToken
from mailtrap.models.api_tokens import ApiTokenWithToken
from mailtrap.models.api_tokens import CreateApiTokenParams
from mailtrap.models.common import DeletedObject


class ApiTokensApi:
def __init__(self, client: HttpClient) -> None:
self._client = client

def get_list(self, account_id: int) -> list[ApiToken]:
"""
Returns all API tokens visible to the current API token.
"""
response = self._client.get(self._api_path(account_id))
return [ApiToken(**api_token) for api_token in response]

def get_by_id(self, account_id: int, api_token_id: int) -> ApiToken:
"""
Get a single API token by id.
"""
response = self._client.get(self._api_path(account_id, api_token_id))
return ApiToken(**response)

def create(
self, account_id: int, token_params: CreateApiTokenParams
) -> ApiTokenWithToken:
"""
Create a new API token. The full token value is only returned once
in the response — store it securely.
"""
response = self._client.post(
self._api_path(account_id), json=token_params.api_data
)
return ApiTokenWithToken(**response)

def delete(self, account_id: int, api_token_id: int) -> DeletedObject:
"""
Permanently delete an API token.
"""
self._client.delete(self._api_path(account_id, api_token_id))
return DeletedObject(id=api_token_id)

def reset(self, account_id: int, api_token_id: int) -> ApiTokenWithToken:
"""
Expire the requested token and create a new token with the same
permissions. The full new token value is returned once — store it
securely. Only tokens that have not already been reset can be reset.
"""
response = self._client.post(
f"{self._api_path(account_id, api_token_id)}/reset"
)
return ApiTokenWithToken(**response)

@staticmethod
def _api_path(account_id: int, api_token_id: Optional[int] = None) -> str:
path = f"/api/accounts/{account_id}/api_tokens"
if api_token_id is not None:
return f"{path}/{api_token_id}"
return path
31 changes: 31 additions & 0 deletions mailtrap/api/resources/sub_accounts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from mailtrap.http import HttpClient
from mailtrap.models.organizations import CreateSubAccountParams
from mailtrap.models.organizations import SubAccount


class SubAccountsApi:
def __init__(self, client: HttpClient, organization_id: str) -> None:
self._organization_id = organization_id
self._client = client

def get_list(self) -> list[SubAccount]:
"""
Get a list of sub accounts for the organization. Requires sub
account management permissions for this organization.
"""
response = self._client.get(self._api_path())
return [SubAccount(**sub_account) for sub_account in response]

def create(self, sub_account_params: CreateSubAccountParams) -> SubAccount:
"""
Create a new sub account under the organization. Requires sub
account management permissions for this organization.
"""
response = self._client.post(
self._api_path(),
json={"account": sub_account_params.api_data},
)
return SubAccount(**response)

def _api_path(self) -> str:
return f"/api/organizations/{self._organization_id}/sub_accounts"
Loading
Loading