Skip to content

Commit

Permalink
Merge branch 'main' into Python-SDK---For-iCloud-Calendar-events,-Vis…
Browse files Browse the repository at this point in the history
…ibility-needs-to-be-optional
  • Loading branch information
mrashed-dev authored May 3, 2024
2 parents dc91464 + 873363f commit d57b52d
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
nylas-python Changelog
======================

Unreleased
----------------
* Add clean messages support

v6.1.1
----------------
* Improved message sending and draft create/update performance
Expand Down
53 changes: 53 additions & 0 deletions nylas/models/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,56 @@ class StopScheduledMessageResponse:
"""

message: str


class CleanMessagesRequest(TypedDict):
"""
Request to clean a list of messages.
Attributes:
message_id: IDs of the email messages to clean.
ignore_links: If true, removes link-related tags (<a>) from the email message while keeping the text.
ignore_images: If true, removes images from the email message.
images_as_markdown: If true, converts images in the email message to Markdown.
ignore_tables: If true, removes table-related tags (<table>, <th>, <td>, <tr>) from the email message while
keeping rows.
remove_conclusion_phrases: If true, removes phrases such as "Best" and "Regards" in the email message signature.
"""

message_id: List[str]
ignore_links: NotRequired[bool]
ignore_images: NotRequired[bool]
images_as_markdown: NotRequired[bool]
ignore_tables: NotRequired[bool]
remove_conclusion_phrases: NotRequired[bool]


@dataclass_json
@dataclass
class CleanMessagesResponse(Message):
"""
Message object with the cleaned HTML message body.
Attributes:
id (str): Globally unique object identifier.
grant_id (str): The grant that this message belongs to.
from_ (List[EmailName]): The sender of the message.
date (int): The date the message was received.
object: The type of object.
thread_id (Optional[str]): The thread that this message belongs to.
subject (Optional[str]): The subject of the message.
to (Optional[List[EmailName]]): The recipients of the message.
cc (Optional[List[EmailName]]): The CC recipients of the message.
bcc (Optional[List[EmailName]]): The BCC recipients of the message.
reply_to (Optional[List[EmailName]]): The reply-to recipients of the message.
unread (Optional[bool]): Whether the message is unread.
starred (Optional[bool]): Whether the message is starred.
snippet (Optional[str]): A snippet of the message body.
body (Optional[str]): The body of the message.
attachments (Optional[List[Attachment]]): The attachments on the message.
folders (Optional[List[str]]): The folders that the message is in.
created_at (Optional[int]): Unix timestamp of when the message was created.
conversation (str): The cleaned HTML message body.
"""

conversation: str = ""
6 changes: 6 additions & 0 deletions nylas/models/webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ class WebhookTriggers(str, Enum):
GRANT_EXPIRED = "grant.expired"
MESSAGE_SEND_SUCCESS = "message.send_success"
MESSAGE_SEND_FAILED = "message.send_failed"
MESSAGE_BOUNCE_DETECTED = "message.bounce_detected"
MESSAGE_CREATED = "message.created"
MESSAGE_UPDATED = "message.updated"
MESSAGE_OPENED = "message.opened"
MESSAGE_LINK_CLICKED = "message.link_clicked"
THREAD_REPLIED = "thread.replied"


@dataclass_json
Expand Down
23 changes: 23 additions & 0 deletions nylas/resources/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
UpdateMessageRequest,
ScheduledMessage,
StopScheduledMessageResponse,
CleanMessagesRequest,
CleanMessagesResponse,
)
from nylas.models.response import Response, ListResponse, DeleteResponse
from nylas.resources.smart_compose import SmartCompose
Expand Down Expand Up @@ -223,3 +225,24 @@ def stop_scheduled_message(
)

return Response.from_dict(json_response, StopScheduledMessageResponse)

def clean_messages(
self, identifier: str, request_body: CleanMessagesRequest
) -> ListResponse[CleanMessagesResponse]:
"""
Remove extra information from a list of messages.
Args:
identifier: The identifier of the grant to clean the message for.
request_body: The values to clean the message with.
Returns:
The list of cleaned messages.
"""
json_resposne = self._http_client._execute(
method="PUT",
path=f"/v3/grants/{identifier}/messages/clean",
request_body=request_body,
)

return ListResponse.from_dict(json_resposne, CleanMessagesResponse)
29 changes: 29 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,32 @@ def http_client_list_scheduled_messages():
],
}
return mock_http_client


@pytest.fixture
def http_client_clean_messages():
mock_http_client = Mock()
mock_http_client._execute.return_value = {
"request_id": "dd3ec9a2-8f15-403d-b269-32b1f1beb9f5",
"data": [
{
"body": "Hello, I just sent a message using Nylas!",
"from": [
{"name": "Daenerys Targaryen", "email": "[email protected]"}
],
"grant_id": "41009df5-bf11-4c97-aa18-b285b5f2e386",
"id": "message-1",
"object": "message",
"conversation": "cleaned example",
},
{
"body": "Hello, this is a test message!",
"from": [{"name": "Michael Scott", "email": "[email protected]"}],
"grant_id": "41009df5-bf11-4c97-aa18-b285b5f2e386",
"id": "message-2",
"object": "message",
"conversation": "another example",
},
],
}
return mock_http_client
34 changes: 34 additions & 0 deletions tests/resources/test_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,3 +272,37 @@ def test_stop_scheduled_message(self, http_client_response):
method="DELETE",
path="/v3/grants/abc-123/messages/schedules/schedule-123",
)

def test_clean_messages(self, http_client_clean_messages):
messages = Messages(http_client_clean_messages)
request_body = {
"message_id": ["message-1", "message-2"],
"ignore_images": True,
"ignore_links": True,
"ignore_tables": True,
"images_as_markdown": True,
"remove_conclusion_phrases": True,
}

response = messages.clean_messages(
identifier="abc-123",
request_body=request_body,
)

http_client_clean_messages._execute.assert_called_once_with(
method="PUT",
path="/v3/grants/abc-123/messages/clean",
request_body=request_body,
)

# Assert the conversation field, and the typical message fields serialize properly
assert len(response.data) == 2
assert response.data[0].body == "Hello, I just sent a message using Nylas!"
assert response.data[0].from_ == [
{"name": "Daenerys Targaryen", "email": "[email protected]"}
]
assert response.data[0].object == "message"
assert response.data[0].id == "message-1"
assert response.data[0].grant_id == "41009df5-bf11-4c97-aa18-b285b5f2e386"
assert response.data[0].conversation == "cleaned example"
assert response.data[1].conversation == "another example"

0 comments on commit d57b52d

Please sign in to comment.