Skip to content

Conversation

Ihor-Bilous
Copy link
Collaborator

@Ihor-Bilous Ihor-Bilous commented Sep 4, 2025

Motivation

In this PR I added SuppressionsApi.

Changes

  • Added SuppressionsApi, models, test, examples

How to test

  • see examples/suppressions/suppressions.py

Summary by CodeRabbit

  • New Features

    • Introduced suppressions management: list account-level suppressions (with optional email filter) and delete individual entries.
    • Added structured types for suppression records to ensure consistent data handling.
    • Exposed a new client accessor to reach suppression operations.
  • Documentation

    • Added an example demonstrating how to list and delete suppressions.
  • Tests

    • Added unit tests covering listing (including email filtering), deletion, and error scenarios to ensure reliability.

Copy link

coderabbitai bot commented Sep 4, 2025

Walkthrough

Introduces account-level Suppressions API: new models, resource client with list/delete endpoints, a base API accessor, client integration method, example usage, and unit tests validating GET with optional email filter and DELETE behaviors.

Changes

Cohort / File(s) Summary of Changes
API Resource: Suppressions
mailtrap/api/resources/suppressions.py
New SuppressionsApi with get_list(email: Optional[str]) and delete(suppression_id) using HttpClient; builds paths under /api/accounts/{account_id}/suppressions; returns Suppression models.
API Base + Client Integration
mailtrap/api/suppressions.py, mailtrap/client.py
Added SuppressionsBaseApi with lazy suppressions property; MailtrapClient.suppressions_api accessor validates account_id and returns SuppressionsBaseApi with GENERAL_HOST HttpClient.
Models
mailtrap/models/suppressions.py
Added enums SuppressionType, SendingStream, and pydantic dataclass Suppression with required/optional fields for suppression payloads.
Examples
examples/suppressions/suppressions.py
Example script exposing list_suppressions(email) and delete_suppression(id) using client.suppressions_api.suppressions.
Tests
tests/unit/api/suppressions/test_suppressions.py
Unit tests for list (with/without email filter) and delete; error cases (401/403/404) and model/enum mapping assertions.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Dev as Developer Code
  participant MC as MailtrapClient
  participant SBA as SuppressionsBaseApi
  participant SA as SuppressionsApi
  participant HC as HttpClient (GENERAL_HOST)

  rect rgb(235,245,255)
  note right of Dev: Obtain API accessor
  Dev->>MC: suppressions_api(account_id)
  MC->>SBA: construct(account_id, HttpClient)
  MC-->>Dev: SuppressionsBaseApi
  Dev->>SBA: suppressions
  SBA-->>Dev: SuppressionsApi
  end

  alt List suppressions (optional email)
    Dev->>SA: get_list(email?)
    SA->>HC: GET /api/accounts/{id}/suppressions[?email=...]
    HC-->>SA: 200 JSON list
    SA-->>Dev: list[Suppression]
  else Delete suppression
    Dev->>SA: delete(suppression_id)
    SA->>HC: DELETE /api/accounts/{id}/suppressions/{suppression_id}
    HC-->>SA: 200 JSON object
    SA-->>Dev: Suppression
  end

  note over HC,SA: Errors propagate from HttpClient
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • IgorDobryn
  • i7an
  • VladimirTaytor
  • andrii-porokhnavets

Poem

I thump my paws on morning logs,
New routes hop forth through misty fogs—
Suppressions listed, one by one,
Delete a bounce, and then I’m done.
With tidy enums, fields aligned,
I nibble bugs and peace of mind. 🥕

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ISSUE-23

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (8)
mailtrap/models/suppressions.py (1)

32-32: Normalize message_created_at to datetime

API returns ISO timestamps; let Pydantic coerce to datetime instead of allowing str|datetime.

-    message_created_at: Optional[Union[str, datetime]] = None
+    message_created_at: Optional[datetime] = None
mailtrap/client.py (1)

137-140: Broaden the validation error message

now mentions only “Testing API” but this check guards Contacts/Templates/Suppressions too.

-        if not self.account_id:
-            raise ClientConfigurationError("`account_id` is required for Testing API")
+        if not self.account_id:
+            raise ClientConfigurationError("`account_id` is required for account-scoped APIs (Testing, Contacts, Templates, Suppressions)")
mailtrap/api/suppressions.py (2)

10-12: Optionally cache the SuppressionsApi instance

Avoid re-instantiation per access (micro). Safe to keep as-is if consistency with other accessors is preferred.

 class SuppressionsBaseApi:
     def __init__(self, client: HttpClient, account_id: str) -> None:
         self._account_id = account_id
         self._client = client
+        self._suppressions: SuppressionsApi | None = None
 
     @property
     def suppressions(self) -> SuppressionsApi:
-        return SuppressionsApi(account_id=self._account_id, client=self._client)
+        if self._suppressions is None:
+            self._suppressions = SuppressionsApi(
+                account_id=self._account_id, client=self._client
+            )
+        return self._suppressions

10-12: Rename parameter to suppression_id for consistency (resources)

Small naming inconsistency: “suppressions_id” → “suppression_id”.

Apply in mailtrap/api/resources/suppressions.py:

-    def delete(self, suppressions_id: str) -> Suppression:
-        response = self._client.delete(self._api_path(suppressions_id))
+    def delete(self, suppression_id: str) -> Suppression:
+        response = self._client.delete(self._api_path(suppression_id))
         return Suppression(**response)
@@
-    def _api_path(self, suppressions_id: Optional[str] = None) -> str:
+    def _api_path(self, suppression_id: Optional[str] = None) -> str:
         path = f"/api/accounts/{self._account_id}/suppressions"
-        if suppressions_id is not None:
-            return f"{path}/{suppressions_id}"
+        if suppression_id is not None:
+            return f"{path}/{suppression_id}"
         return path
tests/unit/api/test_suppressions.py (1)

79-80: Ruff S101 in tests

If your CI enforces S101, add per-file ignores for tests or disable S101 under tests in ruff config.

Example pyproject entry:

[tool.ruff.lint.per-file-ignores]
"tests/**/*" = ["S101"]

Also applies to: 93-95, 110-113, 152-152, 166-170

examples/suppressions.py (1)

6-7: Nit: fix placeholders and avoid hardcoding secrets

Use env vars and correct “YOUR_...” placeholders.

-from typing import Optional
+from typing import Optional
+import os
@@
-API_TOKEN = "YOU_API_TOKEN"
-ACCOUNT_ID = "YOU_ACCOUNT_ID"
+API_TOKEN = os.environ.get("MAILTRAP_API_TOKEN", "YOUR_API_TOKEN")
+ACCOUNT_ID = os.environ.get("MAILTRAP_ACCOUNT_ID", "YOUR_ACCOUNT_ID")
mailtrap/api/resources/suppressions.py (2)

16-24: Rename suppressions_idsuppression_id for clarity/consistency.

Reads better and matches singular resource semantics.

-    def delete(self, suppressions_id: str) -> Suppression:
-        response = self._client.delete(self._api_path(suppressions_id))
+    def delete(self, suppression_id: str) -> Suppression:
+        response = self._client.delete(self._api_path(suppression_id))
         return Suppression(**response)

-    def _api_path(self, suppressions_id: Optional[str] = None) -> str:
+    def _api_path(self, suppression_id: Optional[str] = None) -> str:
         path = f"/api/accounts/{self._account_id}/suppressions"
-        if suppressions_id is not None:
-            return f"{path}/{suppressions_id}"
+        if suppression_id is not None:
+            return f"{path}/{suppression_id}"
         return path

7-11: Add a brief class docstring.

Helps discoverability in IDEs and docs.

 class SuppressionsApi:
+    """Account-level Suppressions resource: list and delete suppressions."""
     def __init__(self, client: HttpClient, account_id: str) -> None:
         self._account_id = account_id
         self._client = client
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between ddfac64 and e3b1f44.

📒 Files selected for processing (6)
  • examples/suppressions.py (1 hunks)
  • mailtrap/api/resources/suppressions.py (1 hunks)
  • mailtrap/api/suppressions.py (1 hunks)
  • mailtrap/client.py (2 hunks)
  • mailtrap/models/suppressions.py (1 hunks)
  • tests/unit/api/test_suppressions.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
mailtrap/api/suppressions.py (2)
mailtrap/api/resources/suppressions.py (1)
  • SuppressionsApi (7-24)
mailtrap/http.py (1)
  • HttpClient (13-96)
examples/suppressions.py (4)
mailtrap/api/suppressions.py (1)
  • suppressions (11-12)
mailtrap/models/suppressions.py (1)
  • Suppression (22-38)
mailtrap/client.py (1)
  • suppressions_api (77-82)
mailtrap/api/resources/suppressions.py (2)
  • get_list (12-14)
  • delete (16-18)
tests/unit/api/test_suppressions.py (5)
mailtrap/api/resources/suppressions.py (3)
  • SuppressionsApi (7-24)
  • get_list (12-14)
  • delete (16-18)
mailtrap/exceptions.py (1)
  • APIError (10-15)
mailtrap/http.py (2)
  • HttpClient (13-96)
  • get (25-29)
mailtrap/models/suppressions.py (3)
  • SendingStream (16-18)
  • Suppression (22-38)
  • SuppressionType (9-13)
mailtrap/client.py (1)
  • suppressions_api (77-82)
mailtrap/api/resources/suppressions.py (3)
mailtrap/http.py (2)
  • HttpClient (13-96)
  • get (25-29)
mailtrap/api/suppressions.py (1)
  • suppressions (11-12)
mailtrap/models/suppressions.py (1)
  • Suppression (22-38)
mailtrap/client.py (2)
mailtrap/api/suppressions.py (2)
  • suppressions (11-12)
  • SuppressionsBaseApi (5-12)
mailtrap/http.py (1)
  • HttpClient (13-96)
🪛 Ruff (0.12.2)
examples/suppressions.py

6-6: Possible hardcoded password assigned to: "API_TOKEN"

(S105)

tests/unit/api/test_suppressions.py

79-79: Use of assert detected

(S101)


93-93: Use of assert detected

(S101)


94-94: Use of assert detected

(S101)


95-95: Use of assert detected

(S101)


110-110: Use of assert detected

(S101)


111-111: Use of assert detected

(S101)


112-112: Use of assert detected

(S101)


113-113: Use of assert detected

(S101)


152-152: Use of assert detected

(S101)


166-166: Use of assert detected

(S101)


167-167: Use of assert detected

(S101)


168-168: Use of assert detected

(S101)


169-169: Use of assert detected

(S101)


170-170: Use of assert detected

(S101)

🔇 Additional comments (4)
mailtrap/models/suppressions.py (1)

9-18: Verify enum string values against API

Please confirm the exact server values for SuppressionType and SendingStream to avoid casing/spacing mismatches at runtime.

mailtrap/client.py (1)

76-82: LGTM: new suppressions_api accessor mirrors existing patterns

Constructor, host, and headers are consistent with other API accessors.

tests/unit/api/test_suppressions.py (2)

62-80: 401 behavior: ensure test expectation matches exceptions.AuthorizationError subtype

HttpClient raises AuthorizationError for 401. If it’s not a subclass of APIError, this test will miss it. Please confirm inheritance or assert the precise type for 401.


154-171: Consider delete 204 No Content scenario

If the API returns 204, current code constructs Suppression from None. Either adjust delete() to handle None or add a test to lock behavior.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
examples/suppressions.py (1)

17-18: Good: delete() typed to return Suppression (not Optional).

Matches API behavior returning the deleted entity body.

tests/unit/api/test_suppressions.py (1)

103-108: Nice: assert the email query param with responses.matchers.

Prevents false positives and locks the contract.

🧹 Nitpick comments (1)
tests/unit/api/test_suppressions.py (1)

1-1: Silence Ruff S101 for test assertions (optional).

If CI flags S101 in tests, disable it file-wide.

+# ruff: noqa: S101
 from datetime import datetime
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e3b1f44 and f837f7f.

📒 Files selected for processing (6)
  • examples/suppressions.py (1 hunks)
  • mailtrap/api/resources/suppressions.py (1 hunks)
  • mailtrap/api/suppressions.py (1 hunks)
  • mailtrap/client.py (2 hunks)
  • mailtrap/models/suppressions.py (1 hunks)
  • tests/unit/api/test_suppressions.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • mailtrap/api/suppressions.py
  • mailtrap/models/suppressions.py
  • mailtrap/api/resources/suppressions.py
  • mailtrap/client.py
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Ihor-Bilous
PR: railsware/mailtrap-python#39
File: mailtrap/api/resources/suppressions.py:16-18
Timestamp: 2025-09-04T16:28:41.593Z
Learning: Mailtrap Suppressions API: DELETE /api/accounts/{account_id}/suppressions/{id} returns HTTP 200 OK with a JSON body of the deleted suppression. Keep SDK delete() typed as -> Suppression (not Optional).
📚 Learning: 2025-09-04T16:28:41.593Z
Learnt from: Ihor-Bilous
PR: railsware/mailtrap-python#39
File: mailtrap/api/resources/suppressions.py:16-18
Timestamp: 2025-09-04T16:28:41.593Z
Learning: Mailtrap Suppressions API: DELETE /api/accounts/{account_id}/suppressions/{id} returns HTTP 200 OK with a JSON body of the deleted suppression. Keep SDK delete() typed as -> Suppression (not Optional).

Applied to files:

  • examples/suppressions.py
  • tests/unit/api/test_suppressions.py
🧬 Code graph analysis (2)
examples/suppressions.py (4)
mailtrap/api/suppressions.py (1)
  • suppressions (11-12)
mailtrap/models/suppressions.py (1)
  • Suppression (22-38)
mailtrap/client.py (2)
  • MailtrapClient (25-151)
  • suppressions_api (77-82)
mailtrap/api/resources/suppressions.py (2)
  • get_list (12-15)
  • delete (17-19)
tests/unit/api/test_suppressions.py (4)
mailtrap/api/resources/suppressions.py (3)
  • SuppressionsApi (7-25)
  • get_list (12-15)
  • delete (17-19)
mailtrap/exceptions.py (1)
  • APIError (10-15)
mailtrap/http.py (2)
  • HttpClient (13-96)
  • get (25-29)
mailtrap/models/suppressions.py (3)
  • SendingStream (16-18)
  • Suppression (22-38)
  • SuppressionType (9-13)
🪛 Ruff (0.12.2)
examples/suppressions.py

6-6: Possible hardcoded password assigned to: "API_TOKEN"

(S105)

tests/unit/api/test_suppressions.py

80-80: Use of assert detected

(S101)


94-94: Use of assert detected

(S101)


95-95: Use of assert detected

(S101)


96-96: Use of assert detected

(S101)


112-112: Use of assert detected

(S101)


113-113: Use of assert detected

(S101)


114-114: Use of assert detected

(S101)


115-115: Use of assert detected

(S101)


116-116: Use of assert detected

(S101)


155-155: Use of assert detected

(S101)


169-169: Use of assert detected

(S101)


170-170: Use of assert detected

(S101)


171-171: Use of assert detected

(S101)


172-172: Use of assert detected

(S101)


173-173: Use of assert detected

(S101)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Test python3.11 on windows-latest
  • GitHub Check: Test python3.13 on windows-latest
  • GitHub Check: Test python3.12 on windows-latest
  • GitHub Check: Test python3.9 on windows-latest
  • GitHub Check: Test python3.10 on windows-latest
🔇 Additional comments (1)
tests/unit/api/test_suppressions.py (1)

167-173: Delete path test covers enums and typing correctly.

Validates id, type, email, and sending_stream per model.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/unit/api/suppressions/test_suppressions.py (1)

1-174: Add explicit parsing or converters for datetime fields
The Suppressions model is a plain @dataclass, so Suppression(**payload) won’t convert ISO-8601 strings to datetime—tests expecting created_at (and message_created_at) as datetime will fail. You need to either:

  • Change Suppressions to inherit from Pydantic’s BaseModel (which auto-parses datetime), or
  • Add a __post_init__ in the dataclass to manually datetime.fromisoformat those fields.
🧹 Nitpick comments (6)
examples/suppressions/suppressions.py (2)

21-22: Make example runnable with optional email filter and nicer output.

Small UX improvement for readers trying the example.

-if __name__ == "__main__":
-    print(list_suppressions())
+if __name__ == "__main__":
+    email = os.environ.get("MAILTRAP_EMAIL_FILTER")
+    suppressions = list_suppressions(email=email)
+    for s in suppressions:
+        print(f"{s.id} {s.type} {s.email} {s.sending_stream} {s.created_at}")

6-7: Fix placeholders typo.

Change "YOU_API_TOKEN/ID" to "YOUR_API_TOKEN/ID" if you keep placeholders anywhere.

tests/unit/api/suppressions/test_suppressions.py (4)

1-2: Silence Ruff S101 in tests file-wide.

Asserts are fine in tests; add a per-file ignore to keep CI green.

-from datetime import datetime
+ # ruff: noqa: S101
+from datetime import datetime

92-97: Also assert enum/value mapping on list endpoint.

You already validate this on DELETE; mirroring it here increases confidence in parsing.

-        assert suppressions[0].id == SUPPRESSION_ID
+        assert suppressions[0].id == SUPPRESSION_ID
+        assert suppressions[0].type == SuppressionType.UNSUBSCRIPTION
+        assert suppressions[0].sending_stream == SendingStream.TRANSACTIONAL

82-91: Add an empty-list case for GET.

Covers edge-case and guards against None being returned.

@responses.activate
def test_get_suppressions_should_return_empty_list(self, suppressions_api: SuppressionsApi) -> None:
    responses.get(BASE_SUPPRESSIONS_URL, json=[], status=200)
    suppressions = suppressions_api.get_list()
    assert suppressions == []

26-44: Optional: validate datetime parsing for nested field.

Since model allows message_created_at to be str or datetime, add an assertion it’s parsed to datetime if your model normalizes it.

assert isinstance(suppressions[0].created_at, datetime)
# If model normalizes nested timestamp:
# assert isinstance(suppressions[0].message_created_at, datetime)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f837f7f and 301204b.

📒 Files selected for processing (3)
  • examples/suppressions/suppressions.py (1 hunks)
  • mailtrap/api/resources/suppressions.py (1 hunks)
  • tests/unit/api/suppressions/test_suppressions.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • mailtrap/api/resources/suppressions.py
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Ihor-Bilous
PR: railsware/mailtrap-python#39
File: mailtrap/api/resources/suppressions.py:16-18
Timestamp: 2025-09-04T16:28:41.602Z
Learning: Mailtrap Suppressions API: DELETE /api/accounts/{account_id}/suppressions/{id} returns HTTP 200 OK with a JSON body of the deleted suppression. Keep SDK delete() typed as -> Suppression (not Optional).
📚 Learning: 2025-09-04T16:28:41.602Z
Learnt from: Ihor-Bilous
PR: railsware/mailtrap-python#39
File: mailtrap/api/resources/suppressions.py:16-18
Timestamp: 2025-09-04T16:28:41.602Z
Learning: Mailtrap Suppressions API: DELETE /api/accounts/{account_id}/suppressions/{id} returns HTTP 200 OK with a JSON body of the deleted suppression. Keep SDK delete() typed as -> Suppression (not Optional).

Applied to files:

  • tests/unit/api/suppressions/test_suppressions.py
  • examples/suppressions/suppressions.py
🧬 Code graph analysis (2)
tests/unit/api/suppressions/test_suppressions.py (4)
mailtrap/api/resources/suppressions.py (3)
  • SuppressionsApi (7-33)
  • get_list (12-19)
  • delete (21-27)
mailtrap/exceptions.py (1)
  • APIError (10-15)
mailtrap/http.py (2)
  • HttpClient (13-96)
  • get (25-29)
mailtrap/models/suppressions.py (3)
  • SendingStream (16-18)
  • Suppression (22-38)
  • SuppressionType (9-13)
examples/suppressions/suppressions.py (4)
mailtrap/api/suppressions.py (1)
  • suppressions (11-12)
mailtrap/models/suppressions.py (1)
  • Suppression (22-38)
mailtrap/client.py (1)
  • MailtrapClient (25-151)
mailtrap/api/resources/suppressions.py (2)
  • get_list (12-19)
  • delete (21-27)
🪛 Ruff (0.12.2)
tests/unit/api/suppressions/test_suppressions.py

80-80: Use of assert detected

(S101)


94-94: Use of assert detected

(S101)


95-95: Use of assert detected

(S101)


96-96: Use of assert detected

(S101)


112-112: Use of assert detected

(S101)


113-113: Use of assert detected

(S101)


114-114: Use of assert detected

(S101)


115-115: Use of assert detected

(S101)


116-116: Use of assert detected

(S101)


155-155: Use of assert detected

(S101)


169-169: Use of assert detected

(S101)


170-170: Use of assert detected

(S101)


171-171: Use of assert detected

(S101)


172-172: Use of assert detected

(S101)


173-173: Use of assert detected

(S101)

examples/suppressions/suppressions.py

6-6: Possible hardcoded password assigned to: "API_TOKEN"

(S105)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Test python3.9 on windows-latest
  • GitHub Check: Test python3.12 on windows-latest
  • GitHub Check: Test python3.13 on windows-latest
  • GitHub Check: Test python3.10 on windows-latest
  • GitHub Check: Test python3.11 on windows-latest
🔇 Additional comments (3)
examples/suppressions/suppressions.py (2)

6-10: Avoid hardcoded secrets; load from environment and fail fast.

Use env vars to satisfy S105 and prevent accidental leaks. Also validate presence before creating the client.

-from typing import Optional
+from typing import Optional
+import os

-API_TOKEN = "YOU_API_TOKEN"
-ACCOUNT_ID = "YOU_ACCOUNT_ID"
+API_TOKEN = os.environ.get("MAILTRAP_API_TOKEN", "")
+ACCOUNT_ID = os.environ.get("MAILTRAP_ACCOUNT_ID", "")
 
-client = mt.MailtrapClient(token=API_TOKEN, account_id=ACCOUNT_ID)
+if not API_TOKEN or not ACCOUNT_ID:
+    raise SystemExit("Set MAILTRAP_API_TOKEN and MAILTRAP_ACCOUNT_ID environment variables.")
+
+client = mt.MailtrapClient(token=API_TOKEN, account_id=ACCOUNT_ID)
⛔ Skipped due to learnings
Learnt from: Ihor-Bilous
PR: railsware/mailtrap-python#39
File: examples/suppressions.py:1-10
Timestamp: 2025-09-04T19:31:01.169Z
Learning: In the mailtrap-python repository, all example files consistently use placeholder strings like `API_TOKEN = "YOU_API_TOKEN"` and `ACCOUNT_ID = "YOU_ACCOUNT_ID"` instead of environment variable lookups. This pattern should be maintained for consistency across examples.
Learnt from: Ihor-Bilous
PR: railsware/mailtrap-python#39
File: mailtrap/api/resources/suppressions.py:16-18
Timestamp: 2025-09-04T16:28:41.602Z
Learning: Mailtrap Suppressions API: DELETE /api/accounts/{account_id}/suppressions/{id} returns HTTP 200 OK with a JSON body of the deleted suppression. Keep SDK delete() typed as -> Suppression (not Optional).

9-11: No changes required: suppressions is a property
The suppressions accessor in SuppressionsBaseApi is decorated with @property (mailtrap/api/suppressions.py:10–12), so using client.suppressions_api.suppressions correctly returns the API instance.

tests/unit/api/suppressions/test_suppressions.py (1)

158-174: Good coverage of DELETE happy-path and error cases.

Return typing as Suppression aligns with API behavior (200 + JSON body). LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant