Skip to content

Commit

Permalink
feat: impl scheduled_at and cancel
Browse files Browse the repository at this point in the history
  • Loading branch information
drish committed Aug 13, 2024
1 parent 4a2a470 commit be070a2
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 1 deletion.
27 changes: 27 additions & 0 deletions examples/scheduled_email.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os

import resend

if not os.environ["RESEND_API_KEY"]:
raise EnvironmentError("RESEND_API_KEY is missing")

params: resend.Emails.SendParams = {
"from": "[email protected]",
"to": ["[email protected]"],
"subject": "hi",
"html": "<strong>hello, scheduled email!</strong>",
"scheduled_at": "2024-09-05T11:52:01.858Z",
}

# Throws a resend.exceptions.ValidationError
# when scheduled_at is not in ISO 8601 format
email: resend.Email = resend.Emails.send(params)

print(f"Email scheduled")
print("Email ID: ", email["id"])

cancel_resp: resend.Emails.CancelScheduledEmailResponse = resend.Emails.cancel(
email_id=email["id"]
)

print(f"Canceled email: {cancel_resp['id']}")
44 changes: 44 additions & 0 deletions resend/emails/_emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
from resend.emails._email import Email
from resend.emails._tag import Tag


class _CancelScheduledEmailResponse(TypedDict):
object: str
id: str
"""
The ID of the scheduled email that was cancelled.
"""


# SendParamsFrom is declared with functional TypedDict syntax here because
# "from" is a reserved keyword in Python, and this is the best way to
# support type-checking for it.
Expand Down Expand Up @@ -59,9 +68,24 @@ class _SendParamsDefault(_SendParamsFrom):
"""
List of tags to be added to the email.
"""
scheduled_at: NotRequired[str]
"""
Schedule email to be sent later.
The date should be in ISO 8601 format (e.g: 2024-08-05T11:52:01.858Z).
"""


class Emails:

class CancelScheduledEmailResponse(_CancelScheduledEmailResponse):
"""
CancelScheduledEmailResponse type that wraps the ID of the scheduled email that was cancelled
Attributes:
object (str): The object type
id (str): The ID of the scheduled email that was cancelled
"""

class SendParams(_SendParamsDefault):
"""SendParams is the class that wraps the parameters for the send method.
Expand Down Expand Up @@ -118,3 +142,23 @@ def get(cls, email_id: str) -> Email:
verb="get",
).perform_with_content()
return resp

@classmethod
def cancel(cls, email_id: str) -> CancelScheduledEmailResponse:
"""
Cancel a scheduled email.
see more: https://resend.com/docs/api-reference/emails/cancel-email
Args:
email_id (str): The ID of the scheduled email to cancel
Returns:
CancelScheduledEmailResponse: The response object that contains the ID of the scheduled email that was cancelled
"""
path = f"/emails/{email_id}/cancel"
resp = request.Request[_CancelScheduledEmailResponse](
path=path,
params={},
verb="post",
).perform_with_content()
return resp
2 changes: 1 addition & 1 deletion resend/version.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "2.3.0"
__version__ = "2.4.0"


def get_version() -> str:
Expand Down
11 changes: 11 additions & 0 deletions tests/emails_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,14 @@ def test_email_response_html(self) -> None:
_ = resend.Emails.send(params)
except ResendError as e:
assert e.message == "Failed to parse Resend API response. Please try again."

def test_cancel_scheduled_email(self) -> None:
self.set_mock_json(
{
"id": "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794",
}
)
email: resend.Emails.CancelScheduledEmailResponse = resend.Emails.cancel(
email_id="49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"
)
assert email["id"] == "49a3999c-0ce1-4ea6-ab68-afcd6dc2e794"

0 comments on commit be070a2

Please sign in to comment.