diff --git a/O365/message.py b/O365/message.py index 3b7ba459..61ffb787 100644 --- a/O365/message.py +++ b/O365/message.py @@ -340,7 +340,7 @@ def __init__(self, *, parent=None, con=None, **kwargs): self.web_link = cloud_data.get(cc('webLink'), '') # Headers only retrieved when selecting 'internetMessageHeaders' - self.message_headers = cloud_data.get(cc('internetMessageHeaders'), []) + self.__message_headers = cloud_data.get(cc('internetMessageHeaders'), []) def __str__(self): return self.__repr__() @@ -622,6 +622,31 @@ def single_value_extended_properties(self): """ singleValueExtendedProperties """ return self.__single_value_extended_properties + @property + def message_headers(self): + """ Custom message headers + List of internetMessageHeaders, see definition: https://learn.microsoft.com/en-us/graph/api/resources/internetmessageheader?view=graph-rest-1.0 + :type: list[dict[str, str]] + """ + + return self.__message_headers + + @message_headers.setter + def message_headers(self, value): + if not isinstance(value, list): + raise ValueError('"message_header" must be a list') + + self.__message_headers = value + self._track_changes.add('message_headers') + + def add_message_header(self, name, value): + # Look if we already have the key. If we do, update it, otherwise write + for header in self.__message_headers: + if header["name"] == name: + header["value"] = value + return + self.__message_headers.append({"name": name, "value": value}) + def to_api_data(self, restrict_keys=None): """ Returns a dict representation of this message prepared to be sent to the cloud @@ -686,6 +711,9 @@ def to_api_data(self, restrict_keys=None): # this property does not form part of the message itself message[cc('parentFolderId')] = self.folder_id + if self.message_headers: + message[cc('internetMessageHeaders')] = self.message_headers + if restrict_keys: for key in list(message.keys()): if key not in restrict_keys: diff --git a/tests/test_message.py b/tests/test_message.py index 8afd0376..1ff60859 100644 --- a/tests/test_message.py +++ b/tests/test_message.py @@ -211,6 +211,25 @@ def test_save_draft_with_with_large_attachment_when_object_id_is_set(self): assert msg.con.calls[2].payload == b"conte" assert msg.con.calls[3].payload == b"nt" + def test_save_draft_with_custom_header(self): + msg = message() + msg.subject = "Test" + my_custom_header = [{"name": "x-my-custom-header", "value": "myHeaderValue"}] + msg.message_headers = my_custom_header + + assert msg.save_draft() is True + [call] = msg.con.calls + assert call.url == self.base_url + "me/mailFolders/Drafts/messages" + assert call.payload == { + "body": {"content": "", "contentType": "HTML"}, + "flag": {"flagStatus": "notFlagged"}, + "importance": "normal", + "isDeliveryReceiptRequested": False, + "isReadReceiptRequested": False, + "subject": "Test", + "internetMessageHeaders": my_custom_header, + } + def test_save_message(self): msg = message(__cloud_data__={"id": "123", "isDraft": False}) msg.subject = "Changed" @@ -291,6 +310,25 @@ def test_send(self): "saveToSentItems": False, } + def test_send_with_headers(self): + my_testheader = {"x-my-custom-header": "some_value"} + msg = message(__cloud_data__={"internetMessageHeaders": [my_testheader]}) + assert msg.send(save_to_sent_folder=False) + [call] = msg.con.calls + assert call.url == self.base_url + "me/sendMail" + assert call.payload == { + "message": { + "body": {"content": "", "contentType": "HTML"}, + "flag": {"flagStatus": "notFlagged"}, + "importance": "normal", + "isDeliveryReceiptRequested": False, + "isReadReceiptRequested": False, + "subject": "", + "internetMessageHeaders": [my_testheader], + }, + "saveToSentItems": False, + } + def test_send_existing_object(self): msg = message(__cloud_data__={"id": "123"}) assert msg.send()