Skip to content
Open
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ 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)

### Inbound Email API:
- Folders management – [`inbound/folders.py`](examples/inbound/folders.py)
- Inboxes management – [`inbound/inboxes.py`](examples/inbound/inboxes.py)
- Messages (list/get/delete + reply/reply_all/forward) – [`inbound/messages.py`](examples/inbound/messages.py)
- Threads (list/get/delete) – [`inbound/threads.py`](examples/inbound/threads.py)

### Webhooks API:
- Webhooks management – [`webhooks/webhooks.py`](examples/webhooks/webhooks.py)
- Verifying webhook signatures – [`webhooks/verify_signature.py`](examples/webhooks/verify_signature.py)
Expand Down
38 changes: 38 additions & 0 deletions examples/inbound/folders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import mailtrap as mt
from mailtrap.models.common import DeletedObject
from mailtrap.models.inbound import InboundFolder

API_TOKEN = "YOUR_API_TOKEN"

client = mt.MailtrapClient(token=API_TOKEN)
folders_api = client.inbound_api.folders


def list_folders() -> list[InboundFolder]:
return folders_api.get_list()


def get_folder(folder_id: int) -> InboundFolder:
return folders_api.get_by_id(folder_id)


def create_folder(name: str) -> InboundFolder:
return folders_api.create(mt.CreateInboundFolderParams(name=name))


def update_folder(folder_id: int, name: str) -> InboundFolder:
return folders_api.update(folder_id, mt.UpdateInboundFolderParams(name=name))


def delete_folder(folder_id: int) -> DeletedObject:
return folders_api.delete(folder_id)


if __name__ == "__main__":
folder = create_folder("Support")
print(folder)

print(list_folders())
print(get_folder(folder.id))
print(update_folder(folder.id, "Support (renamed)"))
print(delete_folder(folder.id))
40 changes: 40 additions & 0 deletions examples/inbound/inboxes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import mailtrap as mt
from mailtrap.models.common import DeletedObject
from mailtrap.models.inbound import InboundInbox

API_TOKEN = "YOUR_API_TOKEN"
FOLDER_ID = 42

client = mt.MailtrapClient(token=API_TOKEN)
inboxes_api = client.inbound_api.inboxes


def list_inboxes(folder_id: int) -> list[InboundInbox]:
return inboxes_api.get_list(folder_id)


def get_inbox(folder_id: int, inbox_id: int) -> InboundInbox:
return inboxes_api.get_by_id(folder_id, inbox_id)


def create_inbox(folder_id: int, name: str) -> InboundInbox:
# Omit domain_id for a Mailtrap-hosted inbox; pass it for a custom-domain inbox.
return inboxes_api.create(folder_id, mt.CreateInboundInboxParams(name=name))


def update_inbox(folder_id: int, inbox_id: int, name: str) -> InboundInbox:
return inboxes_api.update(folder_id, inbox_id, mt.UpdateInboundInboxParams(name=name))


def delete_inbox(folder_id: int, inbox_id: int) -> DeletedObject:
return inboxes_api.delete(folder_id, inbox_id)


if __name__ == "__main__":
inbox = create_inbox(FOLDER_ID, "Tickets")
print(inbox)

print(list_inboxes(FOLDER_ID))
print(get_inbox(FOLDER_ID, inbox.id))
print(update_inbox(FOLDER_ID, inbox.id, "Tickets (renamed)"))
print(delete_inbox(FOLDER_ID, inbox.id))
53 changes: 53 additions & 0 deletions examples/inbound/messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import mailtrap as mt
from mailtrap.models.common import DeletedObject
from mailtrap.models.inbound import InboundMessageDetails
from mailtrap.models.inbound import InboundMessagesListResponse
from mailtrap.models.inbound import InboundSendResult
from mailtrap.models.mail.address import Address

API_TOKEN = "YOUR_API_TOKEN"
INBOX_ID = 9

client = mt.MailtrapClient(token=API_TOKEN)
messages_api = client.inbound_api.messages


def list_messages(inbox_id: int) -> InboundMessagesListResponse:
# Pass last_id from the previous page to paginate.
return messages_api.get_list(inbox_id)


def get_message(inbox_id: int, message_id: str) -> InboundMessageDetails:
return messages_api.get_by_id(inbox_id, message_id)


def delete_message(inbox_id: int, message_id: str) -> DeletedObject:
return messages_api.delete(inbox_id, message_id)


def reply(inbox_id: int, message_id: str, text: str) -> InboundSendResult:
params = mt.ReplyInboundMessageParams(text=text)
return messages_api.reply(inbox_id, message_id, params)


def reply_all(inbox_id: int, message_id: str, text: str) -> InboundSendResult:
params = mt.ReplyInboundMessageParams(text=text)
return messages_api.reply_all(inbox_id, message_id, params)


def forward(inbox_id: int, message_id: str, to: str) -> InboundSendResult:
params = mt.ForwardInboundMessageParams(to=[Address(email=to)])
return messages_api.forward(inbox_id, message_id, params)


if __name__ == "__main__":
page = list_messages(INBOX_ID)
print(f"{len(page.data)} of {page.total_count} messages")

if page.data:
message_id = page.data[0].id
print(get_message(INBOX_ID, message_id))
print(reply(INBOX_ID, message_id, "Thanks for reaching out!"))
print(reply_all(INBOX_ID, message_id, "Looping everyone in."))
print(forward(INBOX_ID, message_id, "colleague@example.com"))
print(delete_message(INBOX_ID, message_id))
33 changes: 33 additions & 0 deletions examples/inbound/threads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import mailtrap as mt
from mailtrap.models.common import DeletedObject
from mailtrap.models.inbound import InboundThread
from mailtrap.models.inbound import InboundThreadsListResponse

API_TOKEN = "YOUR_API_TOKEN"
INBOX_ID = 9

client = mt.MailtrapClient(token=API_TOKEN)
threads_api = client.inbound_api.threads


def list_threads(inbox_id: int) -> InboundThreadsListResponse:
# Pass last_id from the previous page to paginate.
return threads_api.get_list(inbox_id)


def get_thread(inbox_id: int, thread_id: str) -> InboundThread:
return threads_api.get_by_id(inbox_id, thread_id)


def delete_thread(inbox_id: int, thread_id: str) -> DeletedObject:
return threads_api.delete(inbox_id, thread_id)


if __name__ == "__main__":
page = list_threads(INBOX_ID)
print(f"{len(page.data)} of {page.total_count} threads")

if page.data:
thread_id = page.data[0].id
print(get_thread(INBOX_ID, thread_id))
print(delete_thread(INBOX_ID, thread_id))
6 changes: 6 additions & 0 deletions mailtrap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
from .models.email_logs import EmailLogMessage
from .models.email_logs import EmailLogsListFilters
from .models.email_logs import EmailLogsListResponse
from .models.inbound import CreateInboundFolderParams
from .models.inbound import CreateInboundInboxParams
from .models.inbound import ForwardInboundMessageParams
from .models.inbound import ReplyInboundMessageParams
from .models.inbound import UpdateInboundFolderParams
from .models.inbound import UpdateInboundInboxParams
from .models.inboxes import CreateInboxParams
from .models.inboxes import UpdateInboxParams
from .models.mail import Address
Expand Down
26 changes: 26 additions & 0 deletions mailtrap/api/inbound.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from mailtrap.api.resources.inbound_folders import InboundFoldersApi
from mailtrap.api.resources.inbound_inboxes import InboundInboxesApi
from mailtrap.api.resources.inbound_messages import InboundMessagesApi
from mailtrap.api.resources.inbound_threads import InboundThreadsApi
from mailtrap.http import HttpClient


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

@property
def folders(self) -> InboundFoldersApi:
return InboundFoldersApi(client=self._client)

@property
def inboxes(self) -> InboundInboxesApi:
return InboundInboxesApi(client=self._client)

@property
def messages(self) -> InboundMessagesApi:
return InboundMessagesApi(client=self._client)

@property
def threads(self) -> InboundThreadsApi:
return InboundThreadsApi(client=self._client)
43 changes: 43 additions & 0 deletions mailtrap/api/resources/inbound_folders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from typing import Optional

from mailtrap.http import HttpClient
from mailtrap.models.common import DeletedObject
from mailtrap.models.inbound import CreateInboundFolderParams
from mailtrap.models.inbound import InboundFolder
from mailtrap.models.inbound import UpdateInboundFolderParams


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

def get_list(self) -> list[InboundFolder]:
"""Get all inbound folders in the account."""
response = self._client.get(self._api_path())
return [InboundFolder(**folder) for folder in response]

def get_by_id(self, folder_id: int) -> InboundFolder:
"""Get an inbound folder by ID."""
response = self._client.get(self._api_path(folder_id))
return InboundFolder(**response)

def create(self, params: CreateInboundFolderParams) -> InboundFolder:
"""Create a new inbound folder."""
response = self._client.post(self._api_path(), json=params.api_data)
return InboundFolder(**response)

def update(self, folder_id: int, params: UpdateInboundFolderParams) -> InboundFolder:
"""Rename an inbound folder."""
response = self._client.patch(self._api_path(folder_id), json=params.api_data)
return InboundFolder(**response)

def delete(self, folder_id: int) -> DeletedObject:
"""Delete an inbound folder along with all of its inboxes."""
self._client.delete(self._api_path(folder_id))
return DeletedObject(folder_id)

def _api_path(self, folder_id: Optional[int] = None) -> str:
path = "/api/inbound/folders"
if folder_id:
return f"{path}/{folder_id}"
return path
47 changes: 47 additions & 0 deletions mailtrap/api/resources/inbound_inboxes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from typing import Optional

from mailtrap.http import HttpClient
from mailtrap.models.common import DeletedObject
from mailtrap.models.inbound import CreateInboundInboxParams
from mailtrap.models.inbound import InboundInbox
from mailtrap.models.inbound import UpdateInboundInboxParams


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

def get_list(self, folder_id: int) -> list[InboundInbox]:
"""Get all inboxes in an inbound folder."""
response = self._client.get(self._api_path(folder_id))
return [InboundInbox(**inbox) for inbox in response]

def get_by_id(self, folder_id: int, inbox_id: int) -> InboundInbox:
"""Get an inbound inbox by ID."""
response = self._client.get(self._api_path(folder_id, inbox_id))
return InboundInbox(**response)

def create(self, folder_id: int, params: CreateInboundInboxParams) -> InboundInbox:
"""Create a new inbound inbox in a folder."""
response = self._client.post(self._api_path(folder_id), json=params.api_data)
return InboundInbox(**response)

def update(
self, folder_id: int, inbox_id: int, params: UpdateInboundInboxParams
) -> InboundInbox:
"""Rename an inbound inbox."""
response = self._client.patch(
self._api_path(folder_id, inbox_id), json=params.api_data
)
return InboundInbox(**response)

def delete(self, folder_id: int, inbox_id: int) -> DeletedObject:
"""Delete an inbound inbox."""
self._client.delete(self._api_path(folder_id, inbox_id))
return DeletedObject(inbox_id)

def _api_path(self, folder_id: int, inbox_id: Optional[int] = None) -> str:
path = f"/api/inbound/folders/{folder_id}/inboxes"
if inbox_id:
return f"{path}/{inbox_id}"
return path
71 changes: 71 additions & 0 deletions mailtrap/api/resources/inbound_messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from typing import Any
from typing import Optional

from mailtrap.http import HttpClient
from mailtrap.models.common import DeletedObject
from mailtrap.models.inbound import ForwardInboundMessageParams
from mailtrap.models.inbound import InboundMessageDetails
from mailtrap.models.inbound import InboundMessagesListResponse
from mailtrap.models.inbound import InboundSendResult
from mailtrap.models.inbound import ReplyInboundMessageParams


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

def get_list(
self, inbox_id: int, last_id: Optional[str] = None
) -> InboundMessagesListResponse:
"""
List received messages in an inbox. Pass last_id from a previous
response to fetch the next page.
"""
params: dict[str, Any] = {}
if last_id:
params["last_id"] = last_id
response = self._client.get(self._api_path(inbox_id), params=params or None)
return InboundMessagesListResponse(**response)

def get_by_id(self, inbox_id: int, message_id: str) -> InboundMessageDetails:
"""Get a single message with its body and attachment download URLs."""
response = self._client.get(self._api_path(inbox_id, message_id))
return InboundMessageDetails(**response)

def delete(self, inbox_id: int, message_id: str) -> DeletedObject:
"""Delete a message."""
self._client.delete(self._api_path(inbox_id, message_id))
return DeletedObject(message_id)

def reply(
self, inbox_id: int, message_id: str, params: ReplyInboundMessageParams
) -> InboundSendResult:
"""Reply to a message (to the original sender). Sends a real email."""
response = self._client.post(
f"{self._api_path(inbox_id, message_id)}/reply", json=params.api_data
)
return InboundSendResult(**response)

def reply_all(
self, inbox_id: int, message_id: str, params: ReplyInboundMessageParams
) -> InboundSendResult:
"""Reply to a message and copy its other recipients. Sends a real email."""
response = self._client.post(
f"{self._api_path(inbox_id, message_id)}/reply_all", json=params.api_data
)
return InboundSendResult(**response)

def forward(
self, inbox_id: int, message_id: str, params: ForwardInboundMessageParams
) -> InboundSendResult:
"""Forward a message to new recipients. Sends a real email."""
response = self._client.post(
f"{self._api_path(inbox_id, message_id)}/forward", json=params.api_data
)
return InboundSendResult(**response)

def _api_path(self, inbox_id: int, message_id: Optional[str] = None) -> str:
path = f"/api/inbound/inboxes/{inbox_id}/messages"
if message_id:
return f"{path}/{message_id}"
return path
Loading
Loading