Skip to content

Commit bbbb707

Browse files
Ihor BilousIhor Bilous
authored andcommitted
Fix issue #27: Add InboxesApi, related models, examples. Improve ProjectsApi with parameters classes, add docstring to all resources methods.
1 parent ddfac64 commit bbbb707

File tree

18 files changed

+907
-15
lines changed

18 files changed

+907
-15
lines changed

examples/testing/inboxes.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from typing import Optional
2+
3+
import mailtrap as mt
4+
from mailtrap.models.inboxes import Inbox
5+
6+
API_TOKEN = "YOU_API_TOKEN"
7+
ACCOUNT_ID = "YOU_ACCOUNT_ID"
8+
9+
client = mt.MailtrapClient(token=API_TOKEN, account_id=ACCOUNT_ID)
10+
inboxes_api = client.testing_api.inboxes
11+
12+
13+
def list_inboxes() -> list[Inbox]:
14+
return inboxes_api.get_list()
15+
16+
17+
def create_inbox(project_id: int, inbox_name: str) -> Inbox:
18+
return inboxes_api.create(
19+
project_id=project_id, inbox_params=mt.CreateInboxParams(name=inbox_name)
20+
)
21+
22+
23+
def get_inbox_by_id(inbox_id: int) -> Inbox:
24+
return inboxes_api.get_by_id(inbox_id)
25+
26+
27+
def update_inbox(
28+
inbox_id: int,
29+
new_name: Optional[str] = None,
30+
new_email_username: Optional[str] = None,
31+
) -> Inbox:
32+
return inboxes_api.update(
33+
inbox_id, mt.UpdateInboxParams(name=new_name, email_username=new_email_username)
34+
)
35+
36+
37+
def clean_inbox(inbox_id: int) -> Inbox:
38+
return inboxes_api.clean(inbox_id)
39+
40+
41+
def mark_inbox_as_read(inbox_id: int) -> Inbox:
42+
return inboxes_api.mark_as_read(inbox_id)
43+
44+
45+
def reset_inbox_credentials(inbox_id: int) -> Inbox:
46+
return inboxes_api.reset_credentials(inbox_id)
47+
48+
49+
def enable_inbox_email_address(inbox_id: int) -> Inbox:
50+
return inboxes_api.enable_email_address(inbox_id)
51+
52+
53+
def reset_inbox_email_username(inbox_id: int) -> Inbox:
54+
return inboxes_api.reset_email_username(inbox_id)
55+
56+
57+
def delete_inbox(inbox_id: int):
58+
return inboxes_api.delete(inbox_id)
59+
60+
61+
if __name__ == "__main__":
62+
inboxes = list_inboxes()
63+
print(inboxes)

examples/testing/projects.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
1-
from mailtrap import MailtrapClient
1+
import mailtrap as mt
22
from mailtrap.models.projects import Project
33

44
API_TOKEN = "YOU_API_TOKEN"
55
ACCOUNT_ID = "YOU_ACCOUNT_ID"
66

7-
client = MailtrapClient(token=API_TOKEN, account_id=ACCOUNT_ID)
7+
client = mt.MailtrapClient(token=API_TOKEN, account_id=ACCOUNT_ID)
88
projects_api = client.testing_api.projects
99

1010

1111
def list_projects() -> list[Project]:
1212
return projects_api.get_list()
1313

1414

15-
def create_project(project_name: str) -> Project:
16-
return projects_api.create(project_name=project_name)
15+
def get_project(project_id: int) -> Project:
16+
return projects_api.get_by_id(project_id)
1717

1818

19-
def update_project(project_id: str, new_name: str) -> Project:
20-
return projects_api.update(project_id, new_name)
19+
def create_project(name: str) -> Project:
20+
return projects_api.create(project_params=mt.ProjectParams(name=name))
2121

2222

23-
def delete_project(project_id: str):
23+
def update_project(project_id: int, new_name: str) -> Project:
24+
return projects_api.update(project_id, mt.ProjectParams(name=new_name))
25+
26+
27+
def delete_project(project_id: int):
2428
return projects_api.delete(project_id)
2529

2630

mailtrap/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@
1010
from .models.contacts import ImportContactParams
1111
from .models.contacts import UpdateContactFieldParams
1212
from .models.contacts import UpdateContactParams
13+
from .models.inboxes import CreateInboxParams
14+
from .models.inboxes import UpdateInboxParams
1315
from .models.mail import Address
1416
from .models.mail import Attachment
1517
from .models.mail import BaseMail
1618
from .models.mail import Disposition
1719
from .models.mail import Mail
1820
from .models.mail import MailFromTemplate
21+
from .models.projects import ProjectParams
1922
from .models.templates import CreateEmailTemplateParams
2023
from .models.templates import UpdateEmailTemplateParams

mailtrap/api/resources/contact_fields.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@ def __init__(self, client: HttpClient, account_id: str) -> None:
1313
self._client = client
1414

1515
def get_list(self) -> list[ContactField]:
16+
"""Get all Contact Fields existing in your account."""
1617
response = self._client.get(self._api_path())
1718
return [ContactField(**field) for field in response]
1819

1920
def get_by_id(self, field_id: int) -> ContactField:
21+
"""Get a contact Field by ID."""
2022
response = self._client.get(
2123
self._api_path(field_id),
2224
)
2325
return ContactField(**response)
2426

2527
def create(self, field_params: CreateContactFieldParams) -> ContactField:
28+
"""Create new Contact Fields. Please note, you can have up to 40 fields."""
2629
response = self._client.post(
2730
self._api_path(),
2831
json=field_params.api_data,
@@ -32,13 +35,22 @@ def create(self, field_params: CreateContactFieldParams) -> ContactField:
3235
def update(
3336
self, field_id: int, field_params: UpdateContactFieldParams
3437
) -> ContactField:
38+
"""
39+
Update existing Contact Field. Please note,
40+
you cannot change data_type of the field.
41+
"""
3542
response = self._client.patch(
3643
self._api_path(field_id),
3744
json=field_params.api_data,
3845
)
3946
return ContactField(**response)
4047

4148
def delete(self, field_id: int) -> DeletedObject:
49+
"""
50+
Delete existing Contact Field Please, note, you cannot delete a Contact Field
51+
which is used in Automations, Email Campaigns (started or scheduled), and in
52+
conditions of Contact Segments (you'll see the corresponding error)
53+
"""
4254
self._client.delete(self._api_path(field_id))
4355
return DeletedObject(field_id)
4456

mailtrap/api/resources/contact_imports.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,20 @@ def __init__(self, client: HttpClient, account_id: str) -> None:
1111
self._client = client
1212

1313
def import_contacts(self, contacts: list[ImportContactParams]) -> ContactImport:
14+
"""
15+
Import contacts in bulk with support for custom fields and list management.
16+
Existing contacts with matching email addresses will be updated automatically.
17+
You can import up to 50,000 contacts per request. The import process runs
18+
asynchronously - use the returned import ID to check the status and results.
19+
"""
1420
response = self._client.post(
1521
self._api_path(),
1622
json={"contacts": [contact.api_data for contact in contacts]},
1723
)
1824
return ContactImport(**response)
1925

2026
def get_by_id(self, import_id: int) -> ContactImport:
27+
"""Get Contact Import by ID."""
2128
response = self._client.get(self._api_path(import_id))
2229
return ContactImport(**response)
2330

mailtrap/api/resources/contact_lists.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,33 @@ def __init__(self, client: HttpClient, account_id: str) -> None:
1212
self._client = client
1313

1414
def get_list(self) -> list[ContactList]:
15+
"""Get all contact lists existing in your account."""
1516
response = self._client.get(self._api_path())
1617
return [ContactList(**field) for field in response]
1718

1819
def get_by_id(self, list_id: int) -> ContactList:
20+
"""Get a contact list by ID."""
1921
response = self._client.get(self._api_path(list_id))
2022
return ContactList(**response)
2123

2224
def create(self, list_params: ContactListParams) -> ContactList:
25+
"""Create new Contact Lists."""
2326
response = self._client.post(
2427
self._api_path(),
2528
json=list_params.api_data,
2629
)
2730
return ContactList(**response)
2831

2932
def update(self, list_id: int, list_params: ContactListParams) -> ContactList:
33+
"""Update existing Contact List."""
3034
response = self._client.patch(
3135
self._api_path(list_id),
3236
json=list_params.api_data,
3337
)
3438
return ContactList(**response)
3539

3640
def delete(self, list_id: int) -> DeletedObject:
41+
"""Delete existing Contact List."""
3742
self._client.delete(self._api_path(list_id))
3843
return DeletedObject(list_id)
3944

mailtrap/api/resources/contacts.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ def __init__(self, client: HttpClient, account_id: str) -> None:
1515
self._client = client
1616

1717
def get_by_id(self, contact_id_or_email: str) -> Contact:
18+
"""Get contact using id or email (URL encoded)."""
1819
response = self._client.get(self._api_path(contact_id_or_email))
1920
return ContactResponse(**response).data
2021

2122
def create(self, contact_params: CreateContactParams) -> Contact:
23+
"""Create a new contact."""
2224
response = self._client.post(
2325
self._api_path(),
2426
json={"contact": contact_params.api_data},
@@ -28,13 +30,15 @@ def create(self, contact_params: CreateContactParams) -> Contact:
2830
def update(
2931
self, contact_id_or_email: str, contact_params: UpdateContactParams
3032
) -> Contact:
33+
"""Update contact using id or email (URL encoded)."""
3134
response = self._client.patch(
3235
self._api_path(contact_id_or_email),
3336
json={"contact": contact_params.api_data},
3437
)
3538
return ContactResponse(**response).data
3639

3740
def delete(self, contact_id_or_email: str) -> DeletedObject:
41+
"""Delete contact using id or email (URL encoded)."""
3842
self._client.delete(self._api_path(contact_id_or_email))
3943
return DeletedObject(contact_id_or_email)
4044

mailtrap/api/resources/inboxes.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from typing import Optional
2+
3+
from mailtrap.http import HttpClient
4+
from mailtrap.models.inboxes import CreateInboxParams
5+
from mailtrap.models.inboxes import Inbox
6+
from mailtrap.models.inboxes import UpdateInboxParams
7+
8+
9+
class InboxesApi:
10+
def __init__(self, client: HttpClient, account_id: str) -> None:
11+
self._account_id = account_id
12+
self._client = client
13+
14+
def get_list(self) -> list[Inbox]:
15+
"""Get a list of inboxes."""
16+
response = self._client.get(self._api_path())
17+
return [Inbox(**inbox) for inbox in response]
18+
19+
def get_by_id(self, inbox_id: int) -> Inbox:
20+
"""Get inbox attributes by inbox id."""
21+
response = self._client.get(self._api_path(inbox_id))
22+
return Inbox(**response)
23+
24+
def create(self, project_id: int, inbox_params: CreateInboxParams) -> Inbox:
25+
"""Create an inbox in a project."""
26+
response = self._client.post(
27+
f"/api/accounts/{self._account_id}/projects/{project_id}/inboxes",
28+
json={"inbox": inbox_params.api_data},
29+
)
30+
return Inbox(**response)
31+
32+
def update(self, inbox_id: int, inbox_params: UpdateInboxParams) -> Inbox:
33+
"""Update inbox name, inbox email username."""
34+
response = self._client.patch(
35+
self._api_path(inbox_id),
36+
json={"inbox": inbox_params.api_data},
37+
)
38+
return Inbox(**response)
39+
40+
def delete(self, inbox_id: int) -> Inbox:
41+
"""Delete an inbox with all its emails."""
42+
response = self._client.delete(self._api_path(inbox_id))
43+
return Inbox(**response)
44+
45+
def clean(self, inbox_id: int) -> Inbox:
46+
"""Delete all messages (emails) from inbox."""
47+
response = self._client.patch(f"{self._api_path(inbox_id)}/clean")
48+
return Inbox(**response)
49+
50+
def mark_as_read(self, inbox_id: int) -> Inbox:
51+
"""Mark all messages in the inbox as read."""
52+
response = self._client.patch(f"{self._api_path(inbox_id)}/all_read")
53+
return Inbox(**response)
54+
55+
def reset_credentials(self, inbox_id: int) -> Inbox:
56+
"""Reset SMTP credentials of the inbox."""
57+
response = self._client.patch(f"{self._api_path(inbox_id)}/reset_credentials")
58+
return Inbox(**response)
59+
60+
def enable_email_address(self, inbox_id: int) -> Inbox:
61+
"""Turn the email address of the inbox on/off."""
62+
response = self._client.patch(f"{self._api_path(inbox_id)}/toggle_email_username")
63+
return Inbox(**response)
64+
65+
def reset_email_username(self, inbox_id: int) -> Inbox:
66+
"""Reset username of email address per inbox."""
67+
response = self._client.patch(f"{self._api_path(inbox_id)}/reset_email_username")
68+
return Inbox(**response)
69+
70+
def _api_path(self, inbox_id: Optional[int] = None) -> str:
71+
path = f"/api/accounts/{self._account_id}/inboxes"
72+
if inbox_id:
73+
return f"{path}/{inbox_id}"
74+
return path

mailtrap/api/resources/projects.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from mailtrap.http import HttpClient
44
from mailtrap.models.common import DeletedObject
55
from mailtrap.models.projects import Project
6+
from mailtrap.models.projects import ProjectParams
67

78

89
class ProjectsApi:
@@ -11,28 +12,39 @@ def __init__(self, client: HttpClient, account_id: str) -> None:
1112
self._client = client
1213

1314
def get_list(self) -> list[Project]:
15+
"""List projects and their inboxes to which the API token has access."""
1416
response = self._client.get(self._api_path())
1517
return [Project(**project) for project in response]
1618

1719
def get_by_id(self, project_id: int) -> Project:
20+
"""Get the project and its inboxes."""
1821
response = self._client.get(self._api_path(project_id))
1922
return Project(**response)
2023

21-
def create(self, project_name: str) -> Project:
24+
def create(self, project_params: ProjectParams) -> Project:
25+
"""
26+
Create a new project.
27+
The project name is min 2 characters and max 100 characters long.
28+
"""
2229
response = self._client.post(
2330
self._api_path(),
24-
json={"project": {"name": project_name}},
31+
json={"project": project_params.api_data},
2532
)
2633
return Project(**response)
2734

28-
def update(self, project_id: int, project_name: str) -> Project:
35+
def update(self, project_id: int, project_params: ProjectParams) -> Project:
36+
"""
37+
Update project name.
38+
The project name is min 2 characters and max 100 characters long.
39+
"""
2940
response = self._client.patch(
3041
self._api_path(project_id),
31-
json={"project": {"name": project_name}},
42+
json={"project": project_params.api_data},
3243
)
3344
return Project(**response)
3445

3546
def delete(self, project_id: int) -> DeletedObject:
47+
"""Delete project and its inboxes."""
3648
response = self._client.delete(self._api_path(project_id))
3749
return DeletedObject(**response)
3850

0 commit comments

Comments
 (0)