From 54390d06a17b184e36cd709eb3d6fb068cd3d8ec Mon Sep 17 00:00:00 2001 From: ecederstrand Date: Wed, 24 Apr 2024 00:04:50 +0200 Subject: [PATCH] feat: make Contact.im_addresses writable --- exchangelib/fields.py | 10 ++++++++++ exchangelib/indexed_properties.py | 10 ++++++++++ exchangelib/items/contact.py | 3 ++- exchangelib/util.py | 4 +++- tests/common.py | 8 +++++++- 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/exchangelib/fields.py b/exchangelib/fields.py index 4a93f8aa..9d26ef85 100644 --- a/exchangelib/fields.py +++ b/exchangelib/fields.py @@ -1378,6 +1378,16 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) +class ImAddressField(IndexedField): + PARENT_ELEMENT_NAME = "ImAddresses" + + def __init__(self, *args, **kwargs): + from .indexed_properties import ImAddress + + kwargs["value_cls"] = ImAddress + super().__init__(*args, **kwargs) + + class PhoneNumberField(IndexedField): PARENT_ELEMENT_NAME = "PhoneNumbers" diff --git a/exchangelib/indexed_properties.py b/exchangelib/indexed_properties.py index 503c09d1..122d34a0 100644 --- a/exchangelib/indexed_properties.py +++ b/exchangelib/indexed_properties.py @@ -33,6 +33,16 @@ class EmailAddress(SingleFieldIndexedElement): email = EmailSubField(is_required=True) +class ImAddress(SingleFieldIndexedElement): + """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/entry-imaddress""" + + ELEMENT_NAME = "Entry" + LABEL_CHOICES = ("ImAddress1", "ImAddress2", "ImAddress3") + + label = LabelField(field_uri="Key", choices={Choice(c) for c in LABEL_CHOICES}, default=LABEL_CHOICES[0]) + im_address = SubField(is_required=True) + + class PhoneNumber(SingleFieldIndexedElement): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/entry-phonenumber""" diff --git a/exchangelib/items/contact.py b/exchangelib/items/contact.py index 5a182f1e..c53bb215 100644 --- a/exchangelib/items/contact.py +++ b/exchangelib/items/contact.py @@ -16,6 +16,7 @@ EWSElementField, EWSElementListField, IdElementField, + ImAddressField, MailboxField, MailboxListField, MemberListField, @@ -86,7 +87,7 @@ class Contact(Item): ) department = TextField(field_uri="contacts:Department") generation = TextField(field_uri="contacts:Generation") - im_addresses = CharField(field_uri="contacts:ImAddresses", is_read_only=True) + im_addresses = ImAddressField(field_uri="contacts:ImAddress") job_title = TextField(field_uri="contacts:JobTitle") manager = TextField(field_uri="contacts:Manager") mileage = TextField(field_uri="contacts:Mileage") diff --git a/exchangelib/util.py b/exchangelib/util.py index 2abec794..20d09bdf 100644 --- a/exchangelib/util.py +++ b/exchangelib/util.py @@ -184,7 +184,7 @@ def get_xml_attrs(tree, name): def value_to_xml_text(value): from .ewsdatetime import EWSDate, EWSDateTime, EWSTimeZone - from .indexed_properties import EmailAddress, PhoneNumber + from .indexed_properties import EmailAddress, ImAddress, PhoneNumber from .properties import AssociatedCalendarItemId, Attendee, ConversationId, Mailbox # We can't just create a map and look up with type(value) because we want to support subtypes @@ -208,6 +208,8 @@ def value_to_xml_text(value): return value.phone_number if isinstance(value, EmailAddress): return value.email + if isinstance(value, ImAddress): + return value.im_address if isinstance(value, Mailbox): return value.email_address if isinstance(value, Attendee): diff --git a/tests/common.py b/tests/common.py index a8ac7181..d1c0be05 100644 --- a/tests/common.py +++ b/tests/common.py @@ -40,6 +40,7 @@ EmailAddressField, EWSElementField, ExtendedPropertyField, + ImAddressField, IntegerField, MailboxField, MailboxListField, @@ -52,7 +53,7 @@ TimeZoneField, URIField, ) -from exchangelib.indexed_properties import EmailAddress, PhoneNumber, PhysicalAddress +from exchangelib.indexed_properties import EmailAddress, ImAddress, PhoneNumber, PhysicalAddress from exchangelib.properties import ( Attendee, CompleteName, @@ -247,6 +248,11 @@ def random_val(self, field): for label in EmailAddress.get_field_by_fieldname("label").supported_choices(version=self.account.version): addrs.append(EmailAddress(email=get_random_email(), label=label)) return addrs + if isinstance(field, ImAddressField): + addrs = [] + for label in ImAddress.get_field_by_fieldname("label").supported_choices(version=self.account.version): + addrs.append(ImAddress(im_address=get_random_email(), label=label)) + return addrs if isinstance(field, PhysicalAddressField): addrs = [] for label in PhysicalAddress.get_field_by_fieldname("label").supported_choices(