Skip to content

Commit 15aae0f

Browse files
Merge pull request #439 from nylas/CUST-4797-v3-python-sdk-overwrites-from-field
Resolves issue where Gmail message sending with aliases behaved differently between REST API and SDK usage - The Python SDK now correctly handles the reserved keyword "from" by mapping from_ field to from field during request processing - Ensures consistent behavior when sending messages with custom sender addresses - Maintains backward compatibility by preserving existing "from" field when both "from" and "from_" are present
2 parents a8cd1f3 + 5b8e2a6 commit 15aae0f

File tree

3 files changed

+130
-2
lines changed

3 files changed

+130
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
nylas-python Changelog
22
======================
33

4+
Unreleased
5+
----------
6+
* Fixed from field handling in messages.send() to properly map "from_" field to "from field
7+
48
v6.12.0
59
----------
610
* Added Yahoo, Zoom, EWS as providers to models/auth.py

nylas/resources/messages.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,11 @@ def send(
170170
json_body = None
171171

172172
# From is a reserved keyword in Python, so we need to pull the data from 'from_' instead
173-
request_body["from"] = request_body.get("from_", None)
173+
# Handle both dictionary-style "from" and typed "from_" field
174+
if "from_" in request_body and "from" not in request_body:
175+
request_body["from"] = request_body["from_"]
176+
del request_body["from_"]
177+
# If "from" already exists, leave it unchanged
174178

175179
# Use form data only if the attachment size is greater than 3mb
176180
attachment_size = sum(

tests/resources/test_messages.py

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,4 +949,124 @@ def test_send_message_without_is_plaintext_backwards_compatibility(self, http_cl
949949
request_body=request_body,
950950
data=None,
951951
overrides=None,
952-
)
952+
)
953+
954+
def test_send_message_with_from_field_mapping(self, http_client_response):
955+
"""Test that from_ field is properly mapped to from field in request body."""
956+
messages = Messages(http_client_response)
957+
request_body = {
958+
"subject": "Hello from Nylas!",
959+
"to": [{"name": "Jon Snow", "email": "jsnow@gmail.com"}],
960+
"body": "This is the body of my message.",
961+
"from_": [
962+
{"name": "Daenerys Targaryen", "email": "daenerys.t@example.com"}
963+
],
964+
}
965+
966+
messages.send(identifier="abc-123", request_body=request_body)
967+
968+
# Verify that from_ was mapped to from and from_ was removed
969+
expected_request_body = {
970+
"subject": "Hello from Nylas!",
971+
"to": [{"name": "Jon Snow", "email": "jsnow@gmail.com"}],
972+
"body": "This is the body of my message.",
973+
"from": [{"name": "Daenerys Targaryen", "email": "daenerys.t@example.com"}],
974+
}
975+
976+
http_client_response._execute.assert_called_once_with(
977+
method="POST",
978+
path="/v3/grants/abc-123/messages/send",
979+
request_body=expected_request_body,
980+
data=None,
981+
overrides=None,
982+
)
983+
984+
def test_send_message_with_existing_from_field_unchanged(
985+
self, http_client_response
986+
):
987+
"""Test that existing from field is left unchanged when both from and from_ are present."""
988+
messages = Messages(http_client_response)
989+
request_body = {
990+
"subject": "Hello from Nylas!",
991+
"to": [{"name": "Jon Snow", "email": "jsnow@gmail.com"}],
992+
"body": "This is the body of my message.",
993+
"from": [{"name": "Existing Sender", "email": "existing@example.com"}],
994+
"from_": [
995+
{"name": "Daenerys Targaryen", "email": "daenerys.t@example.com"}
996+
],
997+
}
998+
999+
messages.send(identifier="abc-123", request_body=request_body)
1000+
1001+
# Verify that the original from field is preserved and from_ is not processed
1002+
expected_request_body = {
1003+
"subject": "Hello from Nylas!",
1004+
"to": [{"name": "Jon Snow", "email": "jsnow@gmail.com"}],
1005+
"body": "This is the body of my message.",
1006+
"from": [{"name": "Existing Sender", "email": "existing@example.com"}],
1007+
"from_": [
1008+
{"name": "Daenerys Targaryen", "email": "daenerys.t@example.com"}
1009+
],
1010+
}
1011+
1012+
http_client_response._execute.assert_called_once_with(
1013+
method="POST",
1014+
path="/v3/grants/abc-123/messages/send",
1015+
request_body=expected_request_body,
1016+
data=None,
1017+
overrides=None,
1018+
)
1019+
1020+
def test_send_message_with_only_from_field_unchanged(self, http_client_response):
1021+
"""Test that when only from field is present, it remains unchanged."""
1022+
messages = Messages(http_client_response)
1023+
request_body = {
1024+
"subject": "Hello from Nylas!",
1025+
"to": [{"name": "Jon Snow", "email": "jsnow@gmail.com"}],
1026+
"body": "This is the body of my message.",
1027+
"from": [{"name": "Direct Sender", "email": "direct@example.com"}],
1028+
}
1029+
1030+
messages.send(identifier="abc-123", request_body=request_body)
1031+
1032+
# Verify that the from field remains unchanged
1033+
expected_request_body = {
1034+
"subject": "Hello from Nylas!",
1035+
"to": [{"name": "Jon Snow", "email": "jsnow@gmail.com"}],
1036+
"body": "This is the body of my message.",
1037+
"from": [{"name": "Direct Sender", "email": "direct@example.com"}],
1038+
}
1039+
1040+
http_client_response._execute.assert_called_once_with(
1041+
method="POST",
1042+
path="/v3/grants/abc-123/messages/send",
1043+
request_body=expected_request_body,
1044+
data=None,
1045+
overrides=None,
1046+
)
1047+
1048+
def test_send_message_without_from_fields_unchanged(self, http_client_response):
1049+
"""Test that request body without from or from_ fields remains unchanged."""
1050+
messages = Messages(http_client_response)
1051+
request_body = {
1052+
"subject": "Hello from Nylas!",
1053+
"to": [{"name": "Jon Snow", "email": "jsnow@gmail.com"}],
1054+
"body": "This is the body of my message.",
1055+
}
1056+
1057+
messages.send(identifier="abc-123", request_body=request_body)
1058+
1059+
# Verify that the request body remains unchanged
1060+
expected_request_body = {
1061+
"subject": "Hello from Nylas!",
1062+
"to": [{"name": "Jon Snow", "email": "jsnow@gmail.com"}],
1063+
"body": "This is the body of my message.",
1064+
}
1065+
1066+
http_client_response._execute.assert_called_once_with(
1067+
method="POST",
1068+
path="/v3/grants/abc-123/messages/send",
1069+
request_body=expected_request_body,
1070+
data=None,
1071+
overrides=None,
1072+
)

0 commit comments

Comments
 (0)