Module exchangelib.items
Sub-modules
exchangelib.items.baseexchangelib.items.calendar_itemexchangelib.items.contactexchangelib.items.itemexchangelib.items.messageexchangelib.items.postexchangelib.items.task
Classes
class AcceptItem (**kwargs)-
Expand source code
class AcceptItem(BaseMeetingReplyItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/acceptitem""" ELEMENT_NAME = "AcceptItem"MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/acceptitem
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Inherited members
BaseMeetingReplyItem:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachmentsbcc_recipientsbodycc_recipientsderegisterheadersis_delivery_receipt_requestedis_read_receipt_requesteditem_classproposed_endproposed_startreceived_byreceived_representingreference_item_idregisterremove_fieldsendersensitivitysupported_fieldsto_recipientsvalidate_field
class BaseItem (**kwargs)-
Expand source code
class BaseItem(RegisterMixIn, metaclass=EWSMeta): """Base class for all other classes that implement EWS items.""" ID_ELEMENT_CLS = ItemId _id = IdElementField(field_uri="item:ItemId", value_cls=ID_ELEMENT_CLS) __slots__ = "account", "folder" def __init__(self, **kwargs): """Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class. :param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account. """ from ..account import Account from ..folders import BaseFolder self.account = kwargs.pop("account", None) if self.account is not None and not isinstance(self.account, Account): raise InvalidTypeError("account", self.account, Account) self.folder = kwargs.pop("folder", None) if self.folder is not None: if not isinstance(self.folder, BaseFolder): raise InvalidTypeError("folder", self.folder, BaseFolder) if self.folder.account is not None: if self.account is not None: # Make sure the account from kwargs matches the folder account if self.account != self.folder.account: raise ValueError("'account' does not match 'folder.account'") self.account = self.folder.account super().__init__(**kwargs) @classmethod def from_xml(cls, elem, account): item = super().from_xml(elem=elem, account=account) item.account = account return itemBase class for all other classes that implement EWS items.
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Subclasses
Static methods
def from_xml(elem, account)
Instance variables
var account-
Expand source code
class BaseItem(RegisterMixIn, metaclass=EWSMeta): """Base class for all other classes that implement EWS items.""" ID_ELEMENT_CLS = ItemId _id = IdElementField(field_uri="item:ItemId", value_cls=ID_ELEMENT_CLS) __slots__ = "account", "folder" def __init__(self, **kwargs): """Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class. :param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account. """ from ..account import Account from ..folders import BaseFolder self.account = kwargs.pop("account", None) if self.account is not None and not isinstance(self.account, Account): raise InvalidTypeError("account", self.account, Account) self.folder = kwargs.pop("folder", None) if self.folder is not None: if not isinstance(self.folder, BaseFolder): raise InvalidTypeError("folder", self.folder, BaseFolder) if self.folder.account is not None: if self.account is not None: # Make sure the account from kwargs matches the folder account if self.account != self.folder.account: raise ValueError("'account' does not match 'folder.account'") self.account = self.folder.account super().__init__(**kwargs) @classmethod def from_xml(cls, elem, account): item = super().from_xml(elem=elem, account=account) item.account = account return item var folder-
Expand source code
class BaseItem(RegisterMixIn, metaclass=EWSMeta): """Base class for all other classes that implement EWS items.""" ID_ELEMENT_CLS = ItemId _id = IdElementField(field_uri="item:ItemId", value_cls=ID_ELEMENT_CLS) __slots__ = "account", "folder" def __init__(self, **kwargs): """Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class. :param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account. """ from ..account import Account from ..folders import BaseFolder self.account = kwargs.pop("account", None) if self.account is not None and not isinstance(self.account, Account): raise InvalidTypeError("account", self.account, Account) self.folder = kwargs.pop("folder", None) if self.folder is not None: if not isinstance(self.folder, BaseFolder): raise InvalidTypeError("folder", self.folder, BaseFolder) if self.folder.account is not None: if self.account is not None: # Make sure the account from kwargs matches the folder account if self.account != self.folder.account: raise ValueError("'account' does not match 'folder.account'") self.account = self.folder.account super().__init__(**kwargs) @classmethod def from_xml(cls, elem, account): item = super().from_xml(elem=elem, account=account) item.account = account return item
Inherited members
class BulkCreateResult (**kwargs)-
Expand source code
class BulkCreateResult(BaseItem): """A dummy class to store return values from a CreateItem service call.""" attachments = AttachmentField(field_uri="item:Attachments") # ItemAttachment or FileAttachment def __init__(self, **kwargs): super().__init__(**kwargs) if self.attachments is None: self.attachments = []A dummy class to store return values from a CreateItem service call.
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Instance variables
var attachments-
The type of the None singleton.
Inherited members
class CalendarItem (**kwargs)-
Expand source code
class CalendarItem(Item, AcceptDeclineMixIn): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/calendaritem""" ELEMENT_NAME = "CalendarItem" uid = TextField(field_uri="calendar:UID", is_required_after_save=True, is_searchable=False) recurrence_id = DateTimeField(field_uri="calendar:RecurrenceId", is_read_only=True) start = DateOrDateTimeField(field_uri="calendar:Start", is_required=True) end = DateOrDateTimeField(field_uri="calendar:End", is_required=True) original_start = DateTimeField(field_uri="calendar:OriginalStart", is_read_only=True) is_all_day = BooleanField(field_uri="calendar:IsAllDayEvent", is_required=True, default=False) legacy_free_busy_status = FreeBusyStatusField( field_uri="calendar:LegacyFreeBusyStatus", is_required=True, default="Busy" ) location = TextField(field_uri="calendar:Location") when = TextField(field_uri="calendar:When") is_meeting = BooleanField(field_uri="calendar:IsMeeting", is_read_only=True) is_cancelled = BooleanField(field_uri="calendar:IsCancelled", is_read_only=True) is_recurring = BooleanField(field_uri="calendar:IsRecurring", is_read_only=True) meeting_request_was_sent = BooleanField(field_uri="calendar:MeetingRequestWasSent", is_read_only=True) is_response_requested = BooleanField( field_uri="calendar:IsResponseRequested", default=None, is_required_after_save=True, is_searchable=False ) type = ChoiceField( field_uri="calendar:CalendarItemType", choices={Choice(c) for c in CALENDAR_ITEM_CHOICES}, is_read_only=True ) my_response_type = ChoiceField( field_uri="calendar:MyResponseType", choices={Choice(c) for c in Attendee.RESPONSE_TYPES}, is_read_only=True ) organizer = MailboxField(field_uri="calendar:Organizer", is_read_only=True) required_attendees = AttendeesField(field_uri="calendar:RequiredAttendees", is_searchable=False) optional_attendees = AttendeesField(field_uri="calendar:OptionalAttendees", is_searchable=False) resources = AttendeesField(field_uri="calendar:Resources", is_searchable=False) conflicting_meeting_count = IntegerField(field_uri="calendar:ConflictingMeetingCount", is_read_only=True) adjacent_meeting_count = IntegerField(field_uri="calendar:AdjacentMeetingCount", is_read_only=True) conflicting_meetings = EWSElementListField( field_uri="calendar:ConflictingMeetings", value_cls="CalendarItem", namespace=Item.NAMESPACE, is_read_only=True ) adjacent_meetings = EWSElementListField( field_uri="calendar:AdjacentMeetings", value_cls="CalendarItem", namespace=Item.NAMESPACE, is_read_only=True ) duration = CharField(field_uri="calendar:Duration", is_read_only=True) appointment_reply_time = DateTimeField(field_uri="calendar:AppointmentReplyTime", is_read_only=True) appointment_sequence_number = IntegerField(field_uri="calendar:AppointmentSequenceNumber", is_read_only=True) appointment_state = AppointmentStateField(field_uri="calendar:AppointmentState", is_read_only=True) recurrence = RecurrenceField(field_uri="calendar:Recurrence", is_searchable=False) first_occurrence = OccurrenceField( field_uri="calendar:FirstOccurrence", value_cls=FirstOccurrence, is_read_only=True ) last_occurrence = OccurrenceField(field_uri="calendar:LastOccurrence", value_cls=LastOccurrence, is_read_only=True) modified_occurrences = OccurrenceListField( field_uri="calendar:ModifiedOccurrences", value_cls=Occurrence, is_read_only=True ) deleted_occurrences = OccurrenceListField( field_uri="calendar:DeletedOccurrences", value_cls=DeletedOccurrence, is_read_only=True ) _meeting_timezone = TimeZoneField( field_uri="calendar:MeetingTimeZone", deprecated_from=EXCHANGE_2010, is_searchable=False ) _start_timezone = TimeZoneField( field_uri="calendar:StartTimeZone", supported_from=EXCHANGE_2010, is_searchable=False ) _end_timezone = TimeZoneField(field_uri="calendar:EndTimeZone", supported_from=EXCHANGE_2010, is_searchable=False) conference_type = EnumAsIntField( field_uri="calendar:ConferenceType", enum=CONFERENCE_TYPES, min=0, default=None, is_required_after_save=True ) allow_new_time_proposal = BooleanField( field_uri="calendar:AllowNewTimeProposal", default=None, is_required_after_save=True, is_searchable=False ) is_online_meeting = BooleanField(field_uri="calendar:IsOnlineMeeting", default=None, is_read_only=True) meeting_workspace_url = URIField(field_uri="calendar:MeetingWorkspaceUrl") net_show_url = URIField(field_uri="calendar:NetShowUrl") def occurrence(self, index): """Get an occurrence of a recurring master by index. No query is sent to the server to actually fetch the item. Call refresh() on the item to do so. Only call this method on a recurring master. :param index: The index, which is 1-based :return The occurrence """ return self.__class__( account=self.account, folder=self.folder, _id=OccurrenceItemId(id=self.id, changekey=self.changekey, instance_index=index), ) def recurring_master(self): """Get the recurring master of an occurrence. No query is sent to the server to actually fetch the item. Call refresh() on the item to do so. Only call this method on an occurrence of a recurring master. :return: The master occurrence """ return self.__class__( account=self.account, folder=self.folder, _id=RecurringMasterItemId(id=self.id, changekey=self.changekey), ) @classmethod def timezone_fields(cls): return tuple(f for f in cls.FIELDS if isinstance(f, TimeZoneField)) def clean_timezone_fields(self, version): # Sets proper values on the timezone fields if they are not already set if self.start is None: start_tz = None elif type(self.start) in (EWSDate, datetime.date): start_tz = self.account.default_timezone else: start_tz = self.start.tzinfo if self.end is None: end_tz = None elif type(self.end) in (EWSDate, datetime.date): end_tz = self.account.default_timezone else: end_tz = self.end.tzinfo if version.build < EXCHANGE_2010: if self._meeting_timezone is None: self._meeting_timezone = start_tz self._start_timezone = None self._end_timezone = None else: self._meeting_timezone = None if self._start_timezone is None: self._start_timezone = start_tz if self._end_timezone is None: self._end_timezone = end_tz def clean(self, version=None): super().clean(version=version) if self.start and self.end and self.end < self.start: raise ValueError(f"'end' must be greater than 'start' ({self.start} -> {self.end})") if version: self.clean_timezone_fields(version=version) def cancel(self, **kwargs): return CancelCalendarItem( account=self.account, reference_item_id=ReferenceItemId(id=self.id, changekey=self.changekey), **kwargs ).send() def _update_fieldnames(self): update_fields = super()._update_fieldnames() if self.type == OCCURRENCE: # Some CalendarItem fields cannot be updated when the item is an occurrence. The values are empty when we # receive them so would have been updated because they are set to None. update_fields.remove("recurrence") update_fields.remove("uid") return update_fields @classmethod def from_xml(cls, elem, account): item = super().from_xml(elem=elem, account=account) # EWS returns the start and end values as a datetime regardless of the is_all_day status. Convert to date if # applicable. if not item.is_all_day: return item for field_name in ("start", "end"): val = getattr(item, field_name) if val is None: continue # Return just the date part of the value. Subtract 1 day from the date if this is the end field. This is # the inverse of what we do in .to_xml(). Convert to the local timezone before getting the date. if field_name == "end": val -= datetime.timedelta(days=1) tz = getattr(item, f"_{field_name}_timezone") setattr(item, field_name, val.astimezone(tz).date()) return item def tz_field_for_field_name(self, field_name): meeting_tz_field, start_tz_field, end_tz_field = CalendarItem.timezone_fields() if self.account.version.build < EXCHANGE_2010: return meeting_tz_field if field_name == "start": return start_tz_field if field_name == "end": return end_tz_field raise ValueError("Unsupported field_name") def date_to_datetime(self, field_name): # EWS always expects a datetime. If we have a date value, then convert it to datetime in the local # timezone. Additionally, if this the end field, add 1 day to the date. We could add 12 hours to both # start and end values and let EWS apply its logic, but that seems hacky. value = getattr(self, field_name) tz = getattr(self, self.tz_field_for_field_name(field_name).name) value = EWSDateTime.combine(value, datetime.time(0, 0)).replace(tzinfo=tz) if field_name == "end": value += datetime.timedelta(days=1) return value def to_xml(self, version): # EWS has some special logic related to all-day start and end values. Non-midnight start values are pushed to # the previous midnight. Non-midnight end values are pushed to the following midnight. Midnight in this context # refers to midnight in the local timezone. See # # https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-create-all-day-events-by-using-ews-in-exchange # elem = super().to_xml(version=version) if not self.is_all_day: return elem for field_name in ("start", "end"): value = getattr(self, field_name) if value is None: continue if type(value) in (EWSDate, datetime.date): # EWS always expects a datetime value = self.date_to_datetime(field_name=field_name) # We already generated an XML element for this field, but it contains a plain date at this point, which # is invalid. Replace the value. field = self.get_field_by_fieldname(field_name) set_xml_value(elem.find(field.response_tag()), value) return elemMSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/calendaritem
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Static methods
def from_xml(elem, account)def timezone_fields()
Instance variables
var adjacent_meeting_count-
The type of the None singleton.
var adjacent_meetings-
The type of the None singleton.
var allow_new_time_proposal-
The type of the None singleton.
var appointment_reply_time-
The type of the None singleton.
var appointment_sequence_number-
The type of the None singleton.
var appointment_state-
The type of the None singleton.
var conference_type-
The type of the None singleton.
var conflicting_meeting_count-
The type of the None singleton.
var conflicting_meetings-
The type of the None singleton.
var deleted_occurrences-
The type of the None singleton.
var duration-
The type of the None singleton.
var end-
The type of the None singleton.
var first_occurrence-
The type of the None singleton.
var is_all_day-
The type of the None singleton.
var is_cancelled-
The type of the None singleton.
var is_meeting-
The type of the None singleton.
var is_online_meeting-
The type of the None singleton.
var is_recurring-
The type of the None singleton.
var is_response_requested-
The type of the None singleton.
var last_occurrence-
The type of the None singleton.
var legacy_free_busy_status-
The type of the None singleton.
var location-
The type of the None singleton.
var meeting_request_was_sent-
The type of the None singleton.
var meeting_workspace_url-
The type of the None singleton.
var modified_occurrences-
The type of the None singleton.
var my_response_type-
The type of the None singleton.
var net_show_url-
The type of the None singleton.
var optional_attendees-
The type of the None singleton.
var organizer-
The type of the None singleton.
var original_start-
The type of the None singleton.
var recurrence-
The type of the None singleton.
var recurrence_id-
The type of the None singleton.
var required_attendees-
The type of the None singleton.
var resources-
The type of the None singleton.
var start-
The type of the None singleton.
var type-
The type of the None singleton.
var uid-
The type of the None singleton.
var when-
The type of the None singleton.
Methods
def cancel(self, **kwargs)-
Expand source code
def cancel(self, **kwargs): return CancelCalendarItem( account=self.account, reference_item_id=ReferenceItemId(id=self.id, changekey=self.changekey), **kwargs ).send() def clean(self, version=None)-
Expand source code
def clean(self, version=None): super().clean(version=version) if self.start and self.end and self.end < self.start: raise ValueError(f"'end' must be greater than 'start' ({self.start} -> {self.end})") if version: self.clean_timezone_fields(version=version) def clean_timezone_fields(self, version)-
Expand source code
def clean_timezone_fields(self, version): # Sets proper values on the timezone fields if they are not already set if self.start is None: start_tz = None elif type(self.start) in (EWSDate, datetime.date): start_tz = self.account.default_timezone else: start_tz = self.start.tzinfo if self.end is None: end_tz = None elif type(self.end) in (EWSDate, datetime.date): end_tz = self.account.default_timezone else: end_tz = self.end.tzinfo if version.build < EXCHANGE_2010: if self._meeting_timezone is None: self._meeting_timezone = start_tz self._start_timezone = None self._end_timezone = None else: self._meeting_timezone = None if self._start_timezone is None: self._start_timezone = start_tz if self._end_timezone is None: self._end_timezone = end_tz def date_to_datetime(self, field_name)-
Expand source code
def date_to_datetime(self, field_name): # EWS always expects a datetime. If we have a date value, then convert it to datetime in the local # timezone. Additionally, if this the end field, add 1 day to the date. We could add 12 hours to both # start and end values and let EWS apply its logic, but that seems hacky. value = getattr(self, field_name) tz = getattr(self, self.tz_field_for_field_name(field_name).name) value = EWSDateTime.combine(value, datetime.time(0, 0)).replace(tzinfo=tz) if field_name == "end": value += datetime.timedelta(days=1) return value def occurrence(self, index)-
Expand source code
def occurrence(self, index): """Get an occurrence of a recurring master by index. No query is sent to the server to actually fetch the item. Call refresh() on the item to do so. Only call this method on a recurring master. :param index: The index, which is 1-based :return The occurrence """ return self.__class__( account=self.account, folder=self.folder, _id=OccurrenceItemId(id=self.id, changekey=self.changekey, instance_index=index), )Get an occurrence of a recurring master by index. No query is sent to the server to actually fetch the item. Call refresh() on the item to do so.
Only call this method on a recurring master.
:param index: The index, which is 1-based
:return The occurrence
def recurring_master(self)-
Expand source code
def recurring_master(self): """Get the recurring master of an occurrence. No query is sent to the server to actually fetch the item. Call refresh() on the item to do so. Only call this method on an occurrence of a recurring master. :return: The master occurrence """ return self.__class__( account=self.account, folder=self.folder, _id=RecurringMasterItemId(id=self.id, changekey=self.changekey), )Get the recurring master of an occurrence. No query is sent to the server to actually fetch the item. Call refresh() on the item to do so.
Only call this method on an occurrence of a recurring master.
:return: The master occurrence
def to_xml(self, version)-
Expand source code
def to_xml(self, version): # EWS has some special logic related to all-day start and end values. Non-midnight start values are pushed to # the previous midnight. Non-midnight end values are pushed to the following midnight. Midnight in this context # refers to midnight in the local timezone. See # # https://docs.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-create-all-day-events-by-using-ews-in-exchange # elem = super().to_xml(version=version) if not self.is_all_day: return elem for field_name in ("start", "end"): value = getattr(self, field_name) if value is None: continue if type(value) in (EWSDate, datetime.date): # EWS always expects a datetime value = self.date_to_datetime(field_name=field_name) # We already generated an XML element for this field, but it contains a plain date at this point, which # is invalid. Replace the value. field = self.get_field_by_fieldname(field_name) set_xml_value(elem.find(field.response_tag()), value) return elem def tz_field_for_field_name(self, field_name)-
Expand source code
def tz_field_for_field_name(self, field_name): meeting_tz_field, start_tz_field, end_tz_field = CalendarItem.timezone_fields() if self.account.version.build < EXCHANGE_2010: return meeting_tz_field if field_name == "start": return start_tz_field if field_name == "end": return end_tz_field raise ValueError("Unsupported field_name")
Inherited members
Item:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachattachmentsbodycategoriesconversation_idculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightshas_attachmentsheadersimportancein_reply_tois_associatedis_draftis_from_meis_resendis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemime_contentparent_folder_idregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldresponse_objectssensitivitysizesubjectsupported_fieldstext_bodyunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
class CancelCalendarItem (**kwargs)-
Expand source code
class CancelCalendarItem(BaseReplyItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/cancelcalendaritem""" ELEMENT_NAME = "CancelCalendarItem" author_idx = BaseReplyItem.FIELDS.index_by_name("author") FIELDS = BaseReplyItem.FIELDS[:author_idx] + BaseReplyItem.FIELDS[author_idx + 1 :]MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/cancelcalendaritem
Ancestors
Class variables
-
The type of the None singleton.
Inherited members
-
class Contact (**kwargs)-
Expand source code
class Contact(Item): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/contact""" ELEMENT_NAME = "Contact" file_as = TextField(field_uri="contacts:FileAs") file_as_mapping = ChoiceField( field_uri="contacts:FileAsMapping", choices={ Choice("None"), Choice("LastCommaFirst"), Choice("FirstSpaceLast"), Choice("Company"), Choice("LastCommaFirstCompany"), Choice("CompanyLastFirst"), Choice("LastFirst"), Choice("LastFirstCompany"), Choice("CompanyLastCommaFirst"), Choice("LastFirstSuffix"), Choice("LastSpaceFirstCompany"), Choice("CompanyLastSpaceFirst"), Choice("LastSpaceFirst"), Choice("DisplayName"), Choice("FirstName"), Choice("LastFirstMiddleSuffix"), Choice("LastName"), Choice("Empty"), }, ) display_name = TextField(field_uri="contacts:DisplayName", is_required=True) given_name = CharField(field_uri="contacts:GivenName") initials = TextField(field_uri="contacts:Initials") middle_name = CharField(field_uri="contacts:MiddleName") nickname = TextField(field_uri="contacts:Nickname") complete_name = EWSElementField(field_uri="contacts:CompleteName", value_cls=CompleteName, is_read_only=True) company_name = TextField(field_uri="contacts:CompanyName") email_addresses = EmailAddressesField(field_uri="contacts:EmailAddress") physical_addresses = PhysicalAddressField(field_uri="contacts:PhysicalAddress") phone_numbers = PhoneNumberField(field_uri="contacts:PhoneNumber") assistant_name = TextField(field_uri="contacts:AssistantName") birthday = DateTimeBackedDateField(field_uri="contacts:Birthday", default_time=datetime.time(11, 59)) business_homepage = URIField(field_uri="contacts:BusinessHomePage") children = TextListField(field_uri="contacts:Children") companies = TextListField(field_uri="contacts:Companies", is_searchable=False) contact_source = ChoiceField( field_uri="contacts:ContactSource", choices={Choice("Store"), Choice("ActiveDirectory")}, is_read_only=True ) department = TextField(field_uri="contacts:Department") generation = TextField(field_uri="contacts:Generation") 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") office = TextField(field_uri="contacts:OfficeLocation") postal_address_index = ChoiceField( field_uri="contacts:PostalAddressIndex", choices={Choice("Business"), Choice("Home"), Choice("Other"), Choice("None")}, default="None", is_required_after_save=True, ) profession = TextField(field_uri="contacts:Profession") spouse_name = TextField(field_uri="contacts:SpouseName") surname = CharField(field_uri="contacts:Surname") wedding_anniversary = DateTimeBackedDateField( field_uri="contacts:WeddingAnniversary", default_time=datetime.time(11, 59) ) has_picture = BooleanField(field_uri="contacts:HasPicture", supported_from=EXCHANGE_2010, is_read_only=True) phonetic_full_name = TextField( field_uri="contacts:PhoneticFullName", supported_from=EXCHANGE_2010_SP2, is_read_only=True ) phonetic_first_name = TextField( field_uri="contacts:PhoneticFirstName", supported_from=EXCHANGE_2010_SP2, is_read_only=True ) phonetic_last_name = TextField( field_uri="contacts:PhoneticLastName", supported_from=EXCHANGE_2010_SP2, is_read_only=True ) email_alias = EmailAddressField(field_uri="contacts:Alias", is_read_only=True, supported_from=EXCHANGE_2010_SP2) # 'notes' is documented in MSDN but apparently unused. Writing to it raises ErrorInvalidPropertyRequest. OWA # put entries into the 'notes' form field into the 'body' field. notes = CharField(field_uri="contacts:Notes", supported_from=EXCHANGE_2010_SP2, is_read_only=True) # 'photo' is documented in MSDN but apparently unused. Writing to it raises ErrorInvalidPropertyRequest. OWA # adds photos as FileAttachments on the contact item (with 'is_contact_photo=True'), which automatically flips # the 'has_picture' field. photo = Base64Field(field_uri="contacts:Photo", supported_from=EXCHANGE_2010_SP2, is_read_only=True) user_smime_certificate = Base64Field( field_uri="contacts:UserSMIMECertificate", supported_from=EXCHANGE_2010_SP2, is_read_only=True ) ms_exchange_certificate = Base64Field( field_uri="contacts:MSExchangeCertificate", supported_from=EXCHANGE_2010_SP2, is_read_only=True ) directory_id = TextField(field_uri="contacts:DirectoryId", supported_from=EXCHANGE_2010_SP2, is_read_only=True) manager_mailbox = MailboxField( field_uri="contacts:ManagerMailbox", supported_from=EXCHANGE_2010_SP2, is_read_only=True ) direct_reports = MailboxListField( field_uri="contacts:DirectReports", supported_from=EXCHANGE_2010_SP2, is_read_only=True ) # O365 throws ErrorInternalServerError "[0x004f0102] MapiReplyToBlob" if UniqueBody is requested unique_body_idx = Item.FIELDS.index_by_name("unique_body") FIELDS = Item.FIELDS[:unique_body_idx] + Item.FIELDS[unique_body_idx + 1 :]MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/contact
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Class variables
var unique_body_idx-
The type of the None singleton.
Instance variables
var assistant_name-
The type of the None singleton.
var birthday-
The type of the None singleton.
var business_homepage-
The type of the None singleton.
var children-
The type of the None singleton.
var companies-
The type of the None singleton.
var company_name-
The type of the None singleton.
var complete_name-
The type of the None singleton.
var contact_source-
The type of the None singleton.
var department-
The type of the None singleton.
var direct_reports-
The type of the None singleton.
var directory_id-
The type of the None singleton.
var display_name-
The type of the None singleton.
var email_addresses-
The type of the None singleton.
var email_alias-
The type of the None singleton.
var file_as-
The type of the None singleton.
var file_as_mapping-
The type of the None singleton.
var generation-
The type of the None singleton.
var given_name-
The type of the None singleton.
var has_picture-
The type of the None singleton.
var im_addresses-
The type of the None singleton.
var initials-
The type of the None singleton.
var job_title-
The type of the None singleton.
var manager-
The type of the None singleton.
var manager_mailbox-
The type of the None singleton.
var middle_name-
The type of the None singleton.
var mileage-
The type of the None singleton.
var ms_exchange_certificate-
The type of the None singleton.
var nickname-
The type of the None singleton.
var notes-
The type of the None singleton.
var office-
The type of the None singleton.
var phone_numbers-
The type of the None singleton.
var phonetic_first_name-
The type of the None singleton.
var phonetic_full_name-
The type of the None singleton.
var phonetic_last_name-
The type of the None singleton.
var photo-
The type of the None singleton.
var physical_addresses-
The type of the None singleton.
var postal_address_index-
The type of the None singleton.
var profession-
The type of the None singleton.
var spouse_name-
The type of the None singleton.
var surname-
The type of the None singleton.
var user_smime_certificate-
The type of the None singleton.
var wedding_anniversary-
The type of the None singleton.
Inherited members
Item:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachattachmentsbodycategoriesconversation_idculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightshas_attachmentsheadersimportancein_reply_tois_associatedis_draftis_from_meis_resendis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemime_contentparent_folder_idregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldresponse_objectssensitivitysizesubjectsupported_fieldstext_bodyunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
class DeclineItem (**kwargs)-
Expand source code
class DeclineItem(BaseMeetingReplyItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/declineitem""" ELEMENT_NAME = "DeclineItem"MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/declineitem
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Inherited members
BaseMeetingReplyItem:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachmentsbcc_recipientsbodycc_recipientsderegisterheadersis_delivery_receipt_requestedis_read_receipt_requesteditem_classproposed_endproposed_startreceived_byreceived_representingreference_item_idregisterremove_fieldsendersensitivitysupported_fieldsto_recipientsvalidate_field
class DistributionList (**kwargs)-
Expand source code
class DistributionList(Item): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/distributionlist""" ELEMENT_NAME = "DistributionList" display_name = CharField(field_uri="contacts:DisplayName", is_required=True) file_as = CharField(field_uri="contacts:FileAs", is_read_only=True) contact_source = ChoiceField( field_uri="contacts:ContactSource", choices={Choice("Store"), Choice("ActiveDirectory")}, is_read_only=True ) members = MemberListField(field_uri="distributionlist:Members") # O365 throws ErrorInternalServerError "[0x004f0102] MapiReplyToBlob" if UniqueBody is requested unique_body_idx = Item.FIELDS.index_by_name("unique_body") FIELDS = Item.FIELDS[:unique_body_idx] + Item.FIELDS[unique_body_idx + 1 :]MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/distributionlist
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Class variables
var unique_body_idx-
The type of the None singleton.
Instance variables
var contact_source-
The type of the None singleton.
var display_name-
The type of the None singleton.
var file_as-
The type of the None singleton.
var members-
The type of the None singleton.
Inherited members
Item:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachattachmentsbodycategoriesconversation_idculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightshas_attachmentsheadersimportancein_reply_tois_associatedis_draftis_from_meis_resendis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemime_contentparent_folder_idregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldresponse_objectssensitivitysizesubjectsupported_fieldstext_bodyunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
class ForwardItem (**kwargs)-
Expand source code
class ForwardItem(BaseReplyItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/forwarditem""" ELEMENT_NAME = "ForwardItem"Ancestors
Inherited members
class Item (**kwargs)-
Expand source code
class Item(BaseItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/item""" ELEMENT_NAME = "Item" mime_content = MimeContentField(field_uri="item:MimeContent", is_read_only_after_send=True) _id = BaseItem.FIELDS["_id"] parent_folder_id = EWSElementField(field_uri="item:ParentFolderId", value_cls=ParentFolderId, is_read_only=True) item_class = CharField(field_uri="item:ItemClass", is_read_only=True) subject = CharField(field_uri="item:Subject") sensitivity = ChoiceField( field_uri="item:Sensitivity", choices={Choice("Normal"), Choice("Personal"), Choice("Private"), Choice("Confidential")}, is_required=True, default="Normal", ) text_body = TextField(field_uri="item:TextBody", is_read_only=True, supported_from=EXCHANGE_2013) body = BodyField(field_uri="item:Body") # Accepts and returns Body or HTMLBody instances attachments = AttachmentField(field_uri="item:Attachments") # ItemAttachment or FileAttachment datetime_received = DateTimeField(field_uri="item:DateTimeReceived", is_read_only=True) size = IntegerField(field_uri="item:Size", is_read_only=True) # Item size in bytes categories = CharListField(field_uri="item:Categories") importance = ChoiceField( field_uri="item:Importance", choices={Choice("Low"), Choice("Normal"), Choice("High")}, is_required=True, default="Normal", ) in_reply_to = TextField(field_uri="item:InReplyTo") is_submitted = BooleanField(field_uri="item:IsSubmitted", is_read_only=True) is_draft = BooleanField(field_uri="item:IsDraft", is_read_only=True) is_from_me = BooleanField(field_uri="item:IsFromMe", is_read_only=True) is_resend = BooleanField(field_uri="item:IsResend", is_read_only=True) is_unmodified = BooleanField(field_uri="item:IsUnmodified", is_read_only=True) headers = MessageHeaderField(field_uri="item:InternetMessageHeaders", is_read_only=True) datetime_sent = DateTimeField(field_uri="item:DateTimeSent", is_read_only=True) datetime_created = DateTimeField(field_uri="item:DateTimeCreated", is_read_only=True) response_objects = EWSElementField( field_uri="item:ResponseObjects", value_cls=ResponseObjects, is_read_only=True, ) # Placeholder for ResponseObjects reminder_due_by = DateTimeField(field_uri="item:ReminderDueBy", is_required_after_save=True, is_searchable=False) reminder_is_set = BooleanField(field_uri="item:ReminderIsSet", is_required=True, default=False) reminder_minutes_before_start = IntegerField( field_uri="item:ReminderMinutesBeforeStart", is_required_after_save=True, min=0, default=0 ) display_cc = TextField(field_uri="item:DisplayCc", is_read_only=True) display_to = TextField(field_uri="item:DisplayTo", is_read_only=True) has_attachments = BooleanField(field_uri="item:HasAttachments", is_read_only=True) # ExtendedProperty fields go here culture = CultureField(field_uri="item:Culture", is_required_after_save=True, is_searchable=False) effective_rights = EffectiveRightsField(field_uri="item:EffectiveRights", is_read_only=True) last_modified_name = CharField(field_uri="item:LastModifiedName", is_read_only=True) last_modified_time = DateTimeField(field_uri="item:LastModifiedTime", is_read_only=True) is_associated = BooleanField(field_uri="item:IsAssociated", is_read_only=True, supported_from=EXCHANGE_2010) web_client_read_form_query_string = URIField( field_uri="item:WebClientReadFormQueryString", is_read_only=True, supported_from=EXCHANGE_2010 ) web_client_edit_form_query_string = URIField( field_uri="item:WebClientEditFormQueryString", is_read_only=True, supported_from=EXCHANGE_2010 ) conversation_id = EWSElementField( field_uri="item:ConversationId", value_cls=ConversationId, is_read_only=True, supported_from=EXCHANGE_2010 ) unique_body = BodyField(field_uri="item:UniqueBody", is_read_only=True, supported_from=EXCHANGE_2010) FIELDS = Fields() # Used to register extended properties INSERT_AFTER_FIELD = "has_attachments" def __init__(self, **kwargs): super().__init__(**kwargs) if self.attachments: for a in self.attachments: if a.parent_item: if a.parent_item is not self: raise ValueError(f"'parent_item' of attachment {a} must point to this item") else: a.parent_item = self self.attach(self.attachments) else: self.attachments = [] def save(self, update_fields=None, conflict_resolution=AUTO_RESOLVE, send_meeting_invitations=SEND_TO_NONE): from .task import Task if self.id: item_id, changekey = self._update( update_fieldnames=update_fields, message_disposition=SAVE_ONLY, conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations, ) if ( self.id != item_id and not isinstance(self._id, (OccurrenceItemId, RecurringMasterItemId)) and not isinstance(self, Task) ): # When we update an item with an OccurrenceItemId as ID, EWS returns the ID of the occurrence, so # the ID of this item changes. # # When we update certain fields on a task, the ID may change. A full description is available at # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem-operation-task raise ValueError("'id' mismatch in returned update response") # Don't check that changekeys are different. No-op saves will sometimes leave the changekey intact self._id = self.ID_ELEMENT_CLS(item_id, changekey) else: if update_fields: raise ValueError("'update_fields' is only valid for updates") tmp_attachments = None if self.account and self.account.version.build < EXCHANGE_2013 and self.attachments: # At least some versions prior to Exchange 2013 can't save attachments immediately. You need to first # save, then attach. Store the attachment of this item temporarily and attach later. tmp_attachments, self.attachments = self.attachments, [] item = self._create(message_disposition=SAVE_ONLY, send_meeting_invitations=send_meeting_invitations) self._id = self.ID_ELEMENT_CLS(item.id, item.changekey) for old_att, new_att in zip(self.attachments, item.attachments): if old_att.attachment_id is not None: raise ValueError("Old 'attachment_id' is not empty") if new_att.attachment_id is None: raise ValueError("New 'attachment_id' is empty") old_att.attachment_id = new_att.attachment_id if tmp_attachments: # Exchange 2007 workaround. See above self.attach(tmp_attachments) return self @require_account def _create(self, message_disposition, send_meeting_invitations): # Return a BulkCreateResult because we want to return the ID of both the main item *and* attachments. In send # and send-and-save-copy mode, the server does not return an ID, so we just return True. from ..services import CreateItem return CreateItem(account=self.account).get( items=[self], folder=self.folder, message_disposition=message_disposition, send_meeting_invitations=send_meeting_invitations, ) def _update_fieldnames(self): from .contact import Contact, DistributionList # Return the list of fields we are allowed to update update_fieldnames = [] for f in self.supported_fields(version=self.account.version): if f.name == "attachments": # Attachments are handled separately after item creation continue if f.is_read_only: # These cannot be changed continue if (f.is_required or f.is_required_after_save) and ( getattr(self, f.name) is None or (f.is_list and not getattr(self, f.name)) ): # These are required and cannot be deleted continue if not self.is_draft and f.is_read_only_after_send: # These cannot be changed when the item is no longer a draft continue if f.name == "message_id" and f.is_read_only_after_send: # 'message_id' doesn't support updating, no matter the draft status continue if f.name == "mime_content" and isinstance(self, (Contact, DistributionList)): # Contact and DistributionList don't support updating mime_content, no matter the draft status continue update_fieldnames.append(f.name) return update_fieldnames @require_account def _update(self, update_fieldnames, message_disposition, conflict_resolution, send_meeting_invitations): from ..services import UpdateItem if not self.changekey: raise ValueError(f"{self.__class__.__name__} must have changekey") if not update_fieldnames: # The fields to update was not specified explicitly. Update all fields where update is possible update_fieldnames = self._update_fieldnames() return UpdateItem(account=self.account).get( items=[(self, update_fieldnames)], message_disposition=message_disposition, conflict_resolution=conflict_resolution, send_meeting_invitations_or_cancellations=send_meeting_invitations, suppress_read_receipts=True, expect_result=message_disposition != SEND_AND_SAVE_COPY, ) @require_id def refresh(self): # Updates the item based on fresh data from EWS from ..services import GetItem additional_fields = {FieldPath(field=f) for f in self.supported_fields(version=self.account.version)} res = GetItem(account=self.account).get(items=[self], additional_fields=additional_fields, shape=ID_ONLY) if self.id != res.id and not isinstance(self._id, (OccurrenceItemId, RecurringMasterItemId)): # When we refresh an item with an OccurrenceItemId as ID, EWS returns the ID of the occurrence, so # the ID of this item changes. raise ValueError("'id' mismatch in returned update response") for f in self.FIELDS: setattr(self, f.name, getattr(res, f.name)) # 'parent_item' should point to 'self', not 'fresh_item'. That way, 'fresh_item' can be garbage collected. for a in self.attachments: a.parent_item = self return self @require_id def copy(self, to_folder): from ..services import CopyItem # If 'to_folder' is a public folder or a folder in a different mailbox then None is returned return CopyItem(account=self.account).get( items=[self], to_folder=to_folder, expect_result=None, ) @require_id def move(self, to_folder): from ..services import MoveItem res = MoveItem(account=self.account).get( items=[self], to_folder=to_folder, expect_result=None, ) if res is None: # Assume 'to_folder' is a public folder or a folder in a different mailbox self._id = None return self._id = self.ID_ELEMENT_CLS(*res) self.folder = to_folder def move_to_trash( self, send_meeting_cancellations=SEND_TO_NONE, affected_task_occurrences=ALL_OCCURRENCES, suppress_read_receipts=True, ): # Delete and move to the trash folder. self._delete( delete_type=MOVE_TO_DELETED_ITEMS, send_meeting_cancellations=send_meeting_cancellations, affected_task_occurrences=affected_task_occurrences, suppress_read_receipts=suppress_read_receipts, ) self._id = None self.folder = self.account.trash def soft_delete( self, send_meeting_cancellations=SEND_TO_NONE, affected_task_occurrences=ALL_OCCURRENCES, suppress_read_receipts=True, ): # Delete and move to the dumpster, if it is enabled. self._delete( delete_type=SOFT_DELETE, send_meeting_cancellations=send_meeting_cancellations, affected_task_occurrences=affected_task_occurrences, suppress_read_receipts=suppress_read_receipts, ) self._id = None self.folder = self.account.recoverable_items_deletions def delete( self, send_meeting_cancellations=SEND_TO_NONE, affected_task_occurrences=ALL_OCCURRENCES, suppress_read_receipts=True, ): # Remove the item permanently. No copies are stored anywhere. self._delete( delete_type=HARD_DELETE, send_meeting_cancellations=send_meeting_cancellations, affected_task_occurrences=affected_task_occurrences, suppress_read_receipts=suppress_read_receipts, ) self._id, self.folder = None, None @require_id def _delete(self, delete_type, send_meeting_cancellations, affected_task_occurrences, suppress_read_receipts): from ..services import DeleteItem DeleteItem(account=self.account).get( items=[self], delete_type=delete_type, send_meeting_cancellations=send_meeting_cancellations, affected_task_occurrences=affected_task_occurrences, suppress_read_receipts=suppress_read_receipts, ) @require_id def archive(self, to_folder): from ..services import ArchiveItem return ArchiveItem(account=self.account).get(items=[self], to_folder=to_folder, expect_result=True) def attach(self, attachments): """Add an attachment, or a list of attachments, to this item. If the item has already been saved, the attachments will be created on the server immediately. If the item has not yet been saved, the attachments will be created on the server when the item is saved. Adding attachments to an existing item will update the changekey of the item. :param attachments: """ if not is_iterable(attachments, generators_allowed=True): attachments = [attachments] for a in attachments: if not a.parent_item: a.parent_item = self if self.id and not a.attachment_id: # Already saved object. Attach the attachment server-side now a.attach() if a not in self.attachments: self.attachments.append(a) def detach(self, attachments): """Remove an attachment, or a list of attachments, from this item. If the item has already been saved, the attachments will be deleted on the server immediately. If the item has not yet been saved, the attachments will simply not be created on the server the item is saved. Removing attachments from an existing item will update the changekey of the item. :param attachments: """ if not is_iterable(attachments, generators_allowed=True): attachments = [attachments] if attachments is self.attachments: # Don't remove from the same list we are iterating attachments = list(attachments) for a in attachments: if a.parent_item is not self: raise ValueError("Attachment does not belong to this item") if self.id: # Item is already created. Detach the attachment server-side now a.detach() if a in self.attachments: self.attachments.remove(a) @require_id def create_forward(self, subject, body, to_recipients, cc_recipients=None, bcc_recipients=None): from .message import ForwardItem return ForwardItem( account=self.account, reference_item_id=ReferenceItemId(id=self.id, changekey=self.changekey), subject=subject, new_body=body, to_recipients=to_recipients, cc_recipients=cc_recipients, bcc_recipients=bcc_recipients, ) def forward(self, subject, body, to_recipients, cc_recipients=None, bcc_recipients=None): return self.create_forward( subject, body, to_recipients, cc_recipients, bcc_recipients, ).send()MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/item
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Subclasses
- BaseMeetingItem
- CalendarItem
- exchangelib.items.calendar_item._Booking
- Contact
- DistributionList
- Message
- PostItem
- PostReplyItem
- Task
Instance variables
var attachments-
The type of the None singleton.
var body-
The type of the None singleton.
var categories-
The type of the None singleton.
var conversation_id-
The type of the None singleton.
var culture-
The type of the None singleton.
var datetime_created-
The type of the None singleton.
var datetime_received-
The type of the None singleton.
var datetime_sent-
The type of the None singleton.
var display_cc-
The type of the None singleton.
var display_to-
The type of the None singleton.
var effective_rights-
The type of the None singleton.
var has_attachments-
The type of the None singleton.
var headers-
The type of the None singleton.
var importance-
The type of the None singleton.
var in_reply_to-
The type of the None singleton.
var is_associated-
The type of the None singleton.
var is_draft-
The type of the None singleton.
var is_from_me-
The type of the None singleton.
var is_resend-
The type of the None singleton.
var is_submitted-
The type of the None singleton.
var is_unmodified-
The type of the None singleton.
var item_class-
The type of the None singleton.
var last_modified_name-
The type of the None singleton.
var last_modified_time-
The type of the None singleton.
var mime_content-
The type of the None singleton.
var parent_folder_id-
The type of the None singleton.
var reminder_due_by-
The type of the None singleton.
var reminder_is_set-
The type of the None singleton.
var reminder_minutes_before_start-
The type of the None singleton.
var response_objects-
The type of the None singleton.
var sensitivity-
The type of the None singleton.
var size-
The type of the None singleton.
var subject-
The type of the None singleton.
var text_body-
The type of the None singleton.
var unique_body-
The type of the None singleton.
var web_client_edit_form_query_string-
The type of the None singleton.
var web_client_read_form_query_string-
The type of the None singleton.
Methods
def archive(self, to_folder)-
Expand source code
@require_id def archive(self, to_folder): from ..services import ArchiveItem return ArchiveItem(account=self.account).get(items=[self], to_folder=to_folder, expect_result=True) def attach(self, attachments)-
Expand source code
def attach(self, attachments): """Add an attachment, or a list of attachments, to this item. If the item has already been saved, the attachments will be created on the server immediately. If the item has not yet been saved, the attachments will be created on the server when the item is saved. Adding attachments to an existing item will update the changekey of the item. :param attachments: """ if not is_iterable(attachments, generators_allowed=True): attachments = [attachments] for a in attachments: if not a.parent_item: a.parent_item = self if self.id and not a.attachment_id: # Already saved object. Attach the attachment server-side now a.attach() if a not in self.attachments: self.attachments.append(a)Add an attachment, or a list of attachments, to this item. If the item has already been saved, the attachments will be created on the server immediately. If the item has not yet been saved, the attachments will be created on the server when the item is saved.
Adding attachments to an existing item will update the changekey of the item.
:param attachments:
def copy(self, to_folder)-
Expand source code
@require_id def copy(self, to_folder): from ..services import CopyItem # If 'to_folder' is a public folder or a folder in a different mailbox then None is returned return CopyItem(account=self.account).get( items=[self], to_folder=to_folder, expect_result=None, ) def create_forward(self, subject, body, to_recipients, cc_recipients=None, bcc_recipients=None)-
Expand source code
@require_id def create_forward(self, subject, body, to_recipients, cc_recipients=None, bcc_recipients=None): from .message import ForwardItem return ForwardItem( account=self.account, reference_item_id=ReferenceItemId(id=self.id, changekey=self.changekey), subject=subject, new_body=body, to_recipients=to_recipients, cc_recipients=cc_recipients, bcc_recipients=bcc_recipients, ) def delete(self,
send_meeting_cancellations='SendToNone',
affected_task_occurrences='AllOccurrences',
suppress_read_receipts=True)-
Expand source code
def delete( self, send_meeting_cancellations=SEND_TO_NONE, affected_task_occurrences=ALL_OCCURRENCES, suppress_read_receipts=True, ): # Remove the item permanently. No copies are stored anywhere. self._delete( delete_type=HARD_DELETE, send_meeting_cancellations=send_meeting_cancellations, affected_task_occurrences=affected_task_occurrences, suppress_read_receipts=suppress_read_receipts, ) self._id, self.folder = None, None def detach(self, attachments)-
Expand source code
def detach(self, attachments): """Remove an attachment, or a list of attachments, from this item. If the item has already been saved, the attachments will be deleted on the server immediately. If the item has not yet been saved, the attachments will simply not be created on the server the item is saved. Removing attachments from an existing item will update the changekey of the item. :param attachments: """ if not is_iterable(attachments, generators_allowed=True): attachments = [attachments] if attachments is self.attachments: # Don't remove from the same list we are iterating attachments = list(attachments) for a in attachments: if a.parent_item is not self: raise ValueError("Attachment does not belong to this item") if self.id: # Item is already created. Detach the attachment server-side now a.detach() if a in self.attachments: self.attachments.remove(a)Remove an attachment, or a list of attachments, from this item. If the item has already been saved, the attachments will be deleted on the server immediately. If the item has not yet been saved, the attachments will simply not be created on the server the item is saved.
Removing attachments from an existing item will update the changekey of the item.
:param attachments:
def forward(self, subject, body, to_recipients, cc_recipients=None, bcc_recipients=None)-
Expand source code
def forward(self, subject, body, to_recipients, cc_recipients=None, bcc_recipients=None): return self.create_forward( subject, body, to_recipients, cc_recipients, bcc_recipients, ).send() def move(self, to_folder)-
Expand source code
@require_id def move(self, to_folder): from ..services import MoveItem res = MoveItem(account=self.account).get( items=[self], to_folder=to_folder, expect_result=None, ) if res is None: # Assume 'to_folder' is a public folder or a folder in a different mailbox self._id = None return self._id = self.ID_ELEMENT_CLS(*res) self.folder = to_folder def move_to_trash(self,
send_meeting_cancellations='SendToNone',
affected_task_occurrences='AllOccurrences',
suppress_read_receipts=True)-
Expand source code
def move_to_trash( self, send_meeting_cancellations=SEND_TO_NONE, affected_task_occurrences=ALL_OCCURRENCES, suppress_read_receipts=True, ): # Delete and move to the trash folder. self._delete( delete_type=MOVE_TO_DELETED_ITEMS, send_meeting_cancellations=send_meeting_cancellations, affected_task_occurrences=affected_task_occurrences, suppress_read_receipts=suppress_read_receipts, ) self._id = None self.folder = self.account.trash def refresh(self)-
Expand source code
@require_id def refresh(self): # Updates the item based on fresh data from EWS from ..services import GetItem additional_fields = {FieldPath(field=f) for f in self.supported_fields(version=self.account.version)} res = GetItem(account=self.account).get(items=[self], additional_fields=additional_fields, shape=ID_ONLY) if self.id != res.id and not isinstance(self._id, (OccurrenceItemId, RecurringMasterItemId)): # When we refresh an item with an OccurrenceItemId as ID, EWS returns the ID of the occurrence, so # the ID of this item changes. raise ValueError("'id' mismatch in returned update response") for f in self.FIELDS: setattr(self, f.name, getattr(res, f.name)) # 'parent_item' should point to 'self', not 'fresh_item'. That way, 'fresh_item' can be garbage collected. for a in self.attachments: a.parent_item = self return self def save(self,
update_fields=None,
conflict_resolution='AutoResolve',
send_meeting_invitations='SendToNone')-
Expand source code
def save(self, update_fields=None, conflict_resolution=AUTO_RESOLVE, send_meeting_invitations=SEND_TO_NONE): from .task import Task if self.id: item_id, changekey = self._update( update_fieldnames=update_fields, message_disposition=SAVE_ONLY, conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations, ) if ( self.id != item_id and not isinstance(self._id, (OccurrenceItemId, RecurringMasterItemId)) and not isinstance(self, Task) ): # When we update an item with an OccurrenceItemId as ID, EWS returns the ID of the occurrence, so # the ID of this item changes. # # When we update certain fields on a task, the ID may change. A full description is available at # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/updateitem-operation-task raise ValueError("'id' mismatch in returned update response") # Don't check that changekeys are different. No-op saves will sometimes leave the changekey intact self._id = self.ID_ELEMENT_CLS(item_id, changekey) else: if update_fields: raise ValueError("'update_fields' is only valid for updates") tmp_attachments = None if self.account and self.account.version.build < EXCHANGE_2013 and self.attachments: # At least some versions prior to Exchange 2013 can't save attachments immediately. You need to first # save, then attach. Store the attachment of this item temporarily and attach later. tmp_attachments, self.attachments = self.attachments, [] item = self._create(message_disposition=SAVE_ONLY, send_meeting_invitations=send_meeting_invitations) self._id = self.ID_ELEMENT_CLS(item.id, item.changekey) for old_att, new_att in zip(self.attachments, item.attachments): if old_att.attachment_id is not None: raise ValueError("Old 'attachment_id' is not empty") if new_att.attachment_id is None: raise ValueError("New 'attachment_id' is empty") old_att.attachment_id = new_att.attachment_id if tmp_attachments: # Exchange 2007 workaround. See above self.attach(tmp_attachments) return self def soft_delete(self,
send_meeting_cancellations='SendToNone',
affected_task_occurrences='AllOccurrences',
suppress_read_receipts=True)-
Expand source code
def soft_delete( self, send_meeting_cancellations=SEND_TO_NONE, affected_task_occurrences=ALL_OCCURRENCES, suppress_read_receipts=True, ): # Delete and move to the dumpster, if it is enabled. self._delete( delete_type=SOFT_DELETE, send_meeting_cancellations=send_meeting_cancellations, affected_task_occurrences=affected_task_occurrences, suppress_read_receipts=suppress_read_receipts, ) self._id = None self.folder = self.account.recoverable_items_deletions
Inherited members
class MeetingCancellation (**kwargs)-
Expand source code
class MeetingCancellation(BaseMeetingItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/meetingcancellation""" ELEMENT_NAME = "MeetingCancellation"MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/meetingcancellation
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Inherited members
BaseMeetingItem:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldassociated_calendar_item_idattachattachmentsauthorbcc_recipientsbodycategoriescc_recipientsconversation_idconversation_indexconversation_topicculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightseffective_rights_idxhas_attachmentshas_been_processedheadersimportancein_reply_tois_associatedis_delegatedis_delivery_receipt_requestedis_draftis_from_meis_out_of_dateis_readis_read_receipt_requestedis_resendis_response_requestedis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemessage_idmime_contentparent_folder_idreceived_byreceived_representingreceived_representing_idxreferencesregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldreply_toresponse_objectsresponse_typesendersender_idxsensitivitysizesubjectsupported_fieldstext_bodyto_recipientsunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
class MeetingRequest (**kwargs)-
Expand source code
class MeetingRequest(BaseMeetingItem, AcceptDeclineMixIn): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/meetingrequest""" ELEMENT_NAME = "MeetingRequest" meeting_request_type = ChoiceField( field_uri="meetingRequest:MeetingRequestType", choices={ Choice("FullUpdate"), Choice("InformationalUpdate"), Choice("NewMeetingRequest"), Choice("None"), Choice("Outdated"), Choice("PrincipalWantsCopy"), Choice("SilentUpdate"), }, default="None", ) intended_free_busy_status = ChoiceField( field_uri="meetingRequest:IntendedFreeBusyStatus", choices={Choice("Free"), Choice("Tentative"), Choice("Busy"), Choice("OOF"), Choice("NoData")}, is_required=True, default="Busy", ) # This element also has some fields from CalendarItem start_idx = CalendarItem.FIELDS.index_by_name("start") is_response_requested_idx = CalendarItem.FIELDS.index_by_name("is_response_requested") FIELDS = ( BaseMeetingItem.FIELDS + CalendarItem.FIELDS[start_idx:is_response_requested_idx] + CalendarItem.FIELDS[is_response_requested_idx + 1 :] )MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/meetingrequest
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Class variables
var is_response_requested_idx-
The type of the None singleton.
var start_idx-
The type of the None singleton.
Instance variables
var adjacent_meeting_count-
The type of the None singleton.
var adjacent_meetings-
The type of the None singleton.
var allow_new_time_proposal-
The type of the None singleton.
var appointment_reply_time-
The type of the None singleton.
var appointment_sequence_number-
The type of the None singleton.
var appointment_state-
The type of the None singleton.
var conference_type-
The type of the None singleton.
var conflicting_meeting_count-
The type of the None singleton.
var conflicting_meetings-
The type of the None singleton.
var deleted_occurrences-
The type of the None singleton.
var duration-
The type of the None singleton.
var end-
The type of the None singleton.
var first_occurrence-
The type of the None singleton.
var intended_free_busy_status-
The type of the None singleton.
var is_all_day-
The type of the None singleton.
var is_cancelled-
The type of the None singleton.
var is_meeting-
The type of the None singleton.
var is_online_meeting-
The type of the None singleton.
var is_recurring-
The type of the None singleton.
var last_occurrence-
The type of the None singleton.
var legacy_free_busy_status-
The type of the None singleton.
var location-
The type of the None singleton.
var meeting_request_type-
The type of the None singleton.
var meeting_request_was_sent-
The type of the None singleton.
var meeting_workspace_url-
The type of the None singleton.
var modified_occurrences-
The type of the None singleton.
var my_response_type-
The type of the None singleton.
var net_show_url-
The type of the None singleton.
var optional_attendees-
The type of the None singleton.
var organizer-
The type of the None singleton.
var original_start-
The type of the None singleton.
var recurrence-
The type of the None singleton.
var required_attendees-
The type of the None singleton.
var resources-
The type of the None singleton.
var start-
The type of the None singleton.
var type-
The type of the None singleton.
var when-
The type of the None singleton.
Inherited members
BaseMeetingItem:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldassociated_calendar_item_idattachattachmentsauthorbcc_recipientsbodycategoriescc_recipientsconversation_idconversation_indexconversation_topicculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightseffective_rights_idxhas_attachmentshas_been_processedheadersimportancein_reply_tois_associatedis_delegatedis_delivery_receipt_requestedis_draftis_from_meis_out_of_dateis_readis_read_receipt_requestedis_resendis_response_requestedis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemessage_idmime_contentparent_folder_idreceived_byreceived_representingreceived_representing_idxreferencesregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldreply_toresponse_objectsresponse_typesendersender_idxsensitivitysizesubjectsupported_fieldstext_bodyto_recipientsunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
class MeetingResponse (**kwargs)-
Expand source code
class MeetingResponse(BaseMeetingItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/meetingresponse""" ELEMENT_NAME = "MeetingResponse" proposed_start = DateTimeField(field_uri="meeting:ProposedStart", supported_from=EXCHANGE_2013) proposed_end = DateTimeField(field_uri="meeting:ProposedEnd", supported_from=EXCHANGE_2013)MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/meetingresponse
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Instance variables
var proposed_end-
The type of the None singleton.
var proposed_start-
The type of the None singleton.
Inherited members
BaseMeetingItem:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldassociated_calendar_item_idattachattachmentsauthorbcc_recipientsbodycategoriescc_recipientsconversation_idconversation_indexconversation_topicculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightseffective_rights_idxhas_attachmentshas_been_processedheadersimportancein_reply_tois_associatedis_delegatedis_delivery_receipt_requestedis_draftis_from_meis_out_of_dateis_readis_read_receipt_requestedis_resendis_response_requestedis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemessage_idmime_contentparent_folder_idreceived_byreceived_representingreceived_representing_idxreferencesregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldreply_toresponse_objectsresponse_typesendersender_idxsensitivitysizesubjectsupported_fieldstext_bodyto_recipientsunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
class Message (**kwargs)-
Expand source code
class Message(Item): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/message-ex15websvcsotherref """ ELEMENT_NAME = "Message" sender = MailboxField(field_uri="message:Sender", is_read_only=True, is_read_only_after_send=True) to_recipients = MailboxListField( field_uri="message:ToRecipients", is_read_only_after_send=True, is_searchable=False ) cc_recipients = MailboxListField( field_uri="message:CcRecipients", is_read_only_after_send=True, is_searchable=False ) bcc_recipients = MailboxListField( field_uri="message:BccRecipients", is_read_only_after_send=True, is_searchable=False ) is_read_receipt_requested = BooleanField( field_uri="message:IsReadReceiptRequested", is_required=True, default=False, is_read_only_after_send=True ) is_delivery_receipt_requested = BooleanField( field_uri="message:IsDeliveryReceiptRequested", is_required=True, default=False, is_read_only_after_send=True ) conversation_index = Base64Field(field_uri="message:ConversationIndex", is_read_only=True) conversation_topic = CharField(field_uri="message:ConversationTopic", is_read_only=True) # Rename 'From' to 'author'. We can't use field name 'from' since it's a Python keyword. author = MailboxField(field_uri="message:From", is_read_only_after_send=True) message_id = TextField(field_uri="message:InternetMessageId", is_read_only_after_send=True) is_read = BooleanField(field_uri="message:IsRead", is_required=True, default=False) is_response_requested = BooleanField(field_uri="message:IsResponseRequested", default=False, is_required=True) references = TextField(field_uri="message:References") reply_to = MailboxListField(field_uri="message:ReplyTo", is_read_only_after_send=True, is_searchable=False) received_by = MailboxField(field_uri="message:ReceivedBy", is_read_only=True) received_representing = MailboxField(field_uri="message:ReceivedRepresenting", is_read_only=True) reminder_message_data = EWSElementField( field_uri="message:ReminderMessageData", value_cls=ReminderMessageData, supported_from=EXCHANGE_2013_SP1, is_read_only=True, ) @require_account def send( self, save_copy=True, copy_to_folder=None, conflict_resolution=AUTO_RESOLVE, send_meeting_invitations=SEND_TO_NONE, ): from ..services import SendItem # Only sends a message. The message can either be an existing draft stored in EWS or a new message that does # not yet exist in EWS. if copy_to_folder and not save_copy: raise AttributeError("'save_copy' must be True when 'copy_to_folder' is set") if save_copy and not copy_to_folder: copy_to_folder = self.account.sent # 'Sent' is default EWS behaviour if self.id: SendItem(account=self.account).get(items=[self], saved_item_folder=copy_to_folder) # The item will be deleted from the original folder self._id = None self.folder = copy_to_folder return None # New message if copy_to_folder: # This would better be done via send_and_save() but let's just support it here self.folder = copy_to_folder return self.send_and_save( conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations ) if self.account.version.build < EXCHANGE_2013 and self.attachments: # At least some versions prior to Exchange 2013 can't send attachments immediately. You need to first save, # then attach, then send. This is done in send_and_save(). send() will delete the item again. self.send_and_save( conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations ) return None self._create(message_disposition=SEND_ONLY, send_meeting_invitations=send_meeting_invitations) return None def send_and_save( self, update_fields=None, conflict_resolution=AUTO_RESOLVE, send_meeting_invitations=SEND_TO_NONE ): # Sends Message and saves a copy in the parent folder. Does not return an ItemId. if self.id: return self._update( update_fieldnames=update_fields, message_disposition=SEND_AND_SAVE_COPY, conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations, ) if self.account.version.build < EXCHANGE_2013 and self.attachments: # At least some versions prior to Exchange 2013 can't send-and-save attachments immediately. You need # to first save, then attach, then send. This is done in save(). self.save( update_fields=update_fields, conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations, ) return self.send( save_copy=False, conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations, ) return self._create(message_disposition=SEND_AND_SAVE_COPY, send_meeting_invitations=send_meeting_invitations) @require_id def create_reply(self, subject, body, to_recipients=None, cc_recipients=None, bcc_recipients=None, author=None): if not to_recipients: if not self.author: raise ValueError("'to_recipients' must be set when message has no 'author'") to_recipients = [self.author] return ReplyToItem( account=self.account, reference_item_id=ReferenceItemId(id=self.id, changekey=self.changekey), subject=subject, new_body=body, to_recipients=to_recipients, cc_recipients=cc_recipients, bcc_recipients=bcc_recipients, author=author, ) def reply(self, subject, body, to_recipients=None, cc_recipients=None, bcc_recipients=None, author=None): return self.create_reply(subject, body, to_recipients, cc_recipients, bcc_recipients, author).send() @require_id def create_reply_all(self, subject, body, author=None): me = MailboxField().clean(self.account.primary_smtp_address.lower()) to_recipients = set(self.to_recipients or []) to_recipients.discard(me) cc_recipients = set(self.cc_recipients or []) cc_recipients.discard(me) bcc_recipients = set(self.bcc_recipients or []) bcc_recipients.discard(me) if self.author: to_recipients.add(self.author) return ReplyAllToItem( account=self.account, reference_item_id=ReferenceItemId(id=self.id, changekey=self.changekey), subject=subject, new_body=body, to_recipients=list(to_recipients), cc_recipients=list(cc_recipients), bcc_recipients=list(bcc_recipients), author=author, ) def reply_all(self, subject, body, author=None): return self.create_reply_all(subject, body, author).send() def mark_as_junk(self, is_junk=True, move_item=True): """Mark or un-marks items as junk email. :param is_junk: If True, the sender will be added from the blocked sender list. Otherwise, the sender will be removed. :param move_item: If true, the item will be moved to the junk folder. :return: """ from ..services import MarkAsJunk res = MarkAsJunk(account=self.account).get( items=[self], is_junk=is_junk, move_item=move_item, expect_result=None ) if res is None: return self.folder = self.account.junk if is_junk else self.account.inbox self.id, self.changekey = resPick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Instance variables
-
The type of the None singleton.
var bcc_recipients-
The type of the None singleton.
var cc_recipients-
The type of the None singleton.
var conversation_index-
The type of the None singleton.
var conversation_topic-
The type of the None singleton.
var is_delivery_receipt_requested-
The type of the None singleton.
var is_read-
The type of the None singleton.
var is_read_receipt_requested-
The type of the None singleton.
var is_response_requested-
The type of the None singleton.
var message_id-
The type of the None singleton.
var received_by-
The type of the None singleton.
var received_representing-
The type of the None singleton.
var references-
The type of the None singleton.
var reminder_message_data-
The type of the None singleton.
var reply_to-
The type of the None singleton.
var sender-
The type of the None singleton.
var to_recipients-
The type of the None singleton.
Methods
def create_reply(self,
subject,
body,
to_recipients=None,
cc_recipients=None,
bcc_recipients=None,
author=None)-
Expand source code
@require_id def create_reply(self, subject, body, to_recipients=None, cc_recipients=None, bcc_recipients=None, author=None): if not to_recipients: if not self.author: raise ValueError("'to_recipients' must be set when message has no 'author'") to_recipients = [self.author] return ReplyToItem( account=self.account, reference_item_id=ReferenceItemId(id=self.id, changekey=self.changekey), subject=subject, new_body=body, to_recipients=to_recipients, cc_recipients=cc_recipients, bcc_recipients=bcc_recipients, author=author, ) def create_reply_all(self, subject, body, author=None)-
Expand source code
@require_id def create_reply_all(self, subject, body, author=None): me = MailboxField().clean(self.account.primary_smtp_address.lower()) to_recipients = set(self.to_recipients or []) to_recipients.discard(me) cc_recipients = set(self.cc_recipients or []) cc_recipients.discard(me) bcc_recipients = set(self.bcc_recipients or []) bcc_recipients.discard(me) if self.author: to_recipients.add(self.author) return ReplyAllToItem( account=self.account, reference_item_id=ReferenceItemId(id=self.id, changekey=self.changekey), subject=subject, new_body=body, to_recipients=list(to_recipients), cc_recipients=list(cc_recipients), bcc_recipients=list(bcc_recipients), author=author, ) def mark_as_junk(self, is_junk=True, move_item=True)-
Expand source code
def mark_as_junk(self, is_junk=True, move_item=True): """Mark or un-marks items as junk email. :param is_junk: If True, the sender will be added from the blocked sender list. Otherwise, the sender will be removed. :param move_item: If true, the item will be moved to the junk folder. :return: """ from ..services import MarkAsJunk res = MarkAsJunk(account=self.account).get( items=[self], is_junk=is_junk, move_item=move_item, expect_result=None ) if res is None: return self.folder = self.account.junk if is_junk else self.account.inbox self.id, self.changekey = resMark or un-marks items as junk email.
:param is_junk: If True, the sender will be added from the blocked sender list. Otherwise, the sender will be removed. :param move_item: If true, the item will be moved to the junk folder. :return:
def reply(self,
subject,
body,
to_recipients=None,
cc_recipients=None,
bcc_recipients=None,
author=None)-
Expand source code
def reply(self, subject, body, to_recipients=None, cc_recipients=None, bcc_recipients=None, author=None): return self.create_reply(subject, body, to_recipients, cc_recipients, bcc_recipients, author).send() def reply_all(self, subject, body, author=None)-
Expand source code
def reply_all(self, subject, body, author=None): return self.create_reply_all(subject, body, author).send() def send(self,
save_copy=True,
copy_to_folder=None,
conflict_resolution='AutoResolve',
send_meeting_invitations='SendToNone')-
Expand source code
@require_account def send( self, save_copy=True, copy_to_folder=None, conflict_resolution=AUTO_RESOLVE, send_meeting_invitations=SEND_TO_NONE, ): from ..services import SendItem # Only sends a message. The message can either be an existing draft stored in EWS or a new message that does # not yet exist in EWS. if copy_to_folder and not save_copy: raise AttributeError("'save_copy' must be True when 'copy_to_folder' is set") if save_copy and not copy_to_folder: copy_to_folder = self.account.sent # 'Sent' is default EWS behaviour if self.id: SendItem(account=self.account).get(items=[self], saved_item_folder=copy_to_folder) # The item will be deleted from the original folder self._id = None self.folder = copy_to_folder return None # New message if copy_to_folder: # This would better be done via send_and_save() but let's just support it here self.folder = copy_to_folder return self.send_and_save( conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations ) if self.account.version.build < EXCHANGE_2013 and self.attachments: # At least some versions prior to Exchange 2013 can't send attachments immediately. You need to first save, # then attach, then send. This is done in send_and_save(). send() will delete the item again. self.send_and_save( conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations ) return None self._create(message_disposition=SEND_ONLY, send_meeting_invitations=send_meeting_invitations) return None def send_and_save(self,
update_fields=None,
conflict_resolution='AutoResolve',
send_meeting_invitations='SendToNone')-
Expand source code
def send_and_save( self, update_fields=None, conflict_resolution=AUTO_RESOLVE, send_meeting_invitations=SEND_TO_NONE ): # Sends Message and saves a copy in the parent folder. Does not return an ItemId. if self.id: return self._update( update_fieldnames=update_fields, message_disposition=SEND_AND_SAVE_COPY, conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations, ) if self.account.version.build < EXCHANGE_2013 and self.attachments: # At least some versions prior to Exchange 2013 can't send-and-save attachments immediately. You need # to first save, then attach, then send. This is done in save(). self.save( update_fields=update_fields, conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations, ) return self.send( save_copy=False, conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations, ) return self._create(message_disposition=SEND_AND_SAVE_COPY, send_meeting_invitations=send_meeting_invitations)
Inherited members
Item:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachattachmentsbodycategoriesconversation_idculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightshas_attachmentsheadersimportancein_reply_tois_associatedis_draftis_from_meis_resendis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemime_contentparent_folder_idregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldresponse_objectssensitivitysizesubjectsupported_fieldstext_bodyunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
-
class Persona (**kwargs)-
Expand source code
class Persona(IdChangeKeyMixIn): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/persona""" ELEMENT_NAME = "Persona" ID_ELEMENT_CLS = PersonaId _id = IdElementField(field_uri="persona:PersonaId", value_cls=ID_ELEMENT_CLS, namespace=TNS) persona_type = CharField(field_uri="persona:PersonaType") persona_object_type = TextField(field_uri="persona:PersonaObjectStatus") creation_time = DateTimeField(field_uri="persona:CreationTime") bodies = BodyContentAttributedValueField(field_uri="persona:Bodies") display_name_first_last_sort_key = TextField(field_uri="persona:DisplayNameFirstLastSortKey") display_name_last_first_sort_key = TextField(field_uri="persona:DisplayNameLastFirstSortKey") company_sort_key = TextField(field_uri="persona:CompanyNameSortKey") home_sort_key = TextField(field_uri="persona:HomeCitySortKey") work_city_sort_key = TextField(field_uri="persona:WorkCitySortKey") display_name_first_last_header = CharField(field_uri="persona:DisplayNameFirstLastHeader") display_name_last_first_header = CharField(field_uri="persona:DisplayNameLastFirstHeader") file_as_header = TextField(field_uri="persona:FileAsHeader") display_name = CharField(field_uri="persona:DisplayName") display_name_first_last = CharField(field_uri="persona:DisplayNameFirstLast") display_name_last_first = CharField(field_uri="persona:DisplayNameLastFirst") file_as = CharField(field_uri="persona:FileAs") file_as_id = TextField(field_uri="persona:FileAsId") display_name_prefix = CharField(field_uri="persona:DisplayNamePrefix") given_name = CharField(field_uri="persona:GivenName") middle_name = CharField(field_uri="persona:MiddleName") surname = CharField(field_uri="persona:Surname") generation = CharField(field_uri="persona:Generation") nickname = TextField(field_uri="persona:Nickname") yomi_company_name = TextField(field_uri="persona:YomiCompanyName") yomi_first_name = TextField(field_uri="persona:YomiFirstName") yomi_last_name = TextField(field_uri="persona:YomiLastName") title = CharField(field_uri="persona:Title") department = TextField(field_uri="persona:Department") company_name = CharField(field_uri="persona:CompanyName") email_address = EWSElementField(field_uri="persona:EmailAddress", value_cls=EmailAddress) email_addresses = EWSElementListField(field_uri="persona:EmailAddresses", value_cls=Address) PhoneNumber = PersonaPhoneNumberField(field_uri="persona:PhoneNumber") im_address = CharField(field_uri="persona:ImAddress") home_city = CharField(field_uri="persona:HomeCity") work_city = CharField(field_uri="persona:WorkCity") relevance_score = CharField(field_uri="persona:RelevanceScore") folder_ids = EWSElementListField(field_uri="persona:FolderIds", value_cls=FolderId) attributions = EWSElementListField(field_uri="persona:Attributions", value_cls=Attribution) display_names = StringAttributedValueField(field_uri="persona:DisplayNames") file_ases = StringAttributedValueField(field_uri="persona:FileAses") file_as_ids = StringAttributedValueField(field_uri="persona:FileAsIds") display_name_prefixes = StringAttributedValueField(field_uri="persona:DisplayNamePrefixes") given_names = StringAttributedValueField(field_uri="persona:GivenNames") middle_names = StringAttributedValueField(field_uri="persona:MiddleNames") surnames = StringAttributedValueField(field_uri="persona:Surnames") generations = StringAttributedValueField(field_uri="persona:Generations") nicknames = StringAttributedValueField(field_uri="persona:Nicknames") initials = StringAttributedValueField(field_uri="persona:Initials") yomi_company_names = StringAttributedValueField(field_uri="persona:YomiCompanyNames") yomi_first_names = StringAttributedValueField(field_uri="persona:YomiFirstNames") yomi_last_names = StringAttributedValueField(field_uri="persona:YomiLastNames") business_phone_numbers = PhoneNumberAttributedValueField(field_uri="persona:BusinessPhoneNumbers") business_phone_numbers2 = PhoneNumberAttributedValueField(field_uri="persona:BusinessPhoneNumbers2") home_phones = PhoneNumberAttributedValueField(field_uri="persona:HomePhones") home_phones2 = PhoneNumberAttributedValueField(field_uri="persona:HomePhones2") mobile_phones = PhoneNumberAttributedValueField(field_uri="persona:MobilePhones") mobile_phones2 = PhoneNumberAttributedValueField(field_uri="persona:MobilePhones2") assistant_phone_numbers = PhoneNumberAttributedValueField(field_uri="persona:AssistantPhoneNumbers") callback_phones = PhoneNumberAttributedValueField(field_uri="persona:CallbackPhones") car_phones = PhoneNumberAttributedValueField(field_uri="persona:CarPhones") home_faxes = PhoneNumberAttributedValueField(field_uri="persona:HomeFaxes") organization_main_phones = PhoneNumberAttributedValueField(field_uri="persona:OrganizationMainPhones") other_faxes = PhoneNumberAttributedValueField(field_uri="persona:OtherFaxes") other_telephones = PhoneNumberAttributedValueField(field_uri="persona:OtherTelephones") other_phones2 = PhoneNumberAttributedValueField(field_uri="persona:OtherPhones2") pagers = PhoneNumberAttributedValueField(field_uri="persona:Pagers") radio_phones = PhoneNumberAttributedValueField(field_uri="persona:RadioPhones") telex_numbers = PhoneNumberAttributedValueField(field_uri="persona:TelexNumbers") tty_tdd_phone_numbers = PhoneNumberAttributedValueField(field_uri="persona:TTYTDDPhoneNumbers") work_faxes = PhoneNumberAttributedValueField(field_uri="persona:WorkFaxes") emails1 = EmailAddressAttributedValueField(field_uri="persona:Emails1") emails2 = EmailAddressAttributedValueField(field_uri="persona:Emails2") emails3 = EmailAddressAttributedValueField(field_uri="persona:Emails3") business_home_pages = StringAttributedValueField(field_uri="persona:BusinessHomePages") personal_home_pages = StringAttributedValueField(field_uri="persona:PersonalHomePages") office_locations = StringAttributedValueField(field_uri="persona:OfficeLocations") im_addresses = StringAttributedValueField(field_uri="persona:ImAddresses") im_addresses2 = StringAttributedValueField(field_uri="persona:ImAddresses2") im_addresses3 = StringAttributedValueField(field_uri="persona:ImAddresses3") business_addresses = PostalAddressAttributedValueField(field_uri="persona:BusinessAddresses") home_addresses = PostalAddressAttributedValueField(field_uri="persona:HomeAddresses") other_addresses = PostalAddressAttributedValueField(field_uri="persona:OtherAddresses") titles = StringAttributedValueField(field_uri="persona:Titles") departments = StringAttributedValueField(field_uri="persona:Departments") company_names = StringAttributedValueField(field_uri="persona:CompanyNames") managers = StringAttributedValueField(field_uri="persona:Managers") assistant_names = StringAttributedValueField(field_uri="persona:AssistantNames") professions = StringAttributedValueField(field_uri="persona:Professions") spouse_names = StringAttributedValueField(field_uri="persona:SpouseNames") children = StringAttributedValueField(field_uri="persona:Children") schools = StringAttributedValueField(field_uri="persona:Schools") hobbies = StringAttributedValueField(field_uri="persona:Hobbies") wedding_anniversaries = StringAttributedValueField(field_uri="persona:WeddingAnniversaries") birthdays = StringAttributedValueField(field_uri="persona:Birthdays") locations = StringAttributedValueField(field_uri="persona:Locations") # This class has an additional field of type "ExtendedPropertyAttributedValueField" and # field_uri 'persona:ExtendedProperties'Ancestors
Instance variables
var PhoneNumber-
The type of the None singleton.
var assistant_names-
The type of the None singleton.
var assistant_phone_numbers-
The type of the None singleton.
var attributions-
The type of the None singleton.
var birthdays-
The type of the None singleton.
var bodies-
The type of the None singleton.
var business_addresses-
The type of the None singleton.
var business_home_pages-
The type of the None singleton.
var business_phone_numbers-
The type of the None singleton.
var business_phone_numbers2-
The type of the None singleton.
var callback_phones-
The type of the None singleton.
var car_phones-
The type of the None singleton.
var children-
The type of the None singleton.
var company_name-
The type of the None singleton.
var company_names-
The type of the None singleton.
var company_sort_key-
The type of the None singleton.
var creation_time-
The type of the None singleton.
var department-
The type of the None singleton.
var departments-
The type of the None singleton.
var display_name-
The type of the None singleton.
var display_name_first_last-
The type of the None singleton.
var display_name_first_last_header-
The type of the None singleton.
var display_name_first_last_sort_key-
The type of the None singleton.
var display_name_last_first-
The type of the None singleton.
var display_name_last_first_header-
The type of the None singleton.
var display_name_last_first_sort_key-
The type of the None singleton.
var display_name_prefix-
The type of the None singleton.
var display_name_prefixes-
The type of the None singleton.
var display_names-
The type of the None singleton.
var email_address-
The type of the None singleton.
var email_addresses-
The type of the None singleton.
var emails1-
The type of the None singleton.
var emails2-
The type of the None singleton.
var emails3-
The type of the None singleton.
var file_as-
The type of the None singleton.
var file_as_header-
The type of the None singleton.
var file_as_id-
The type of the None singleton.
var file_as_ids-
The type of the None singleton.
var file_ases-
The type of the None singleton.
var folder_ids-
The type of the None singleton.
var generation-
The type of the None singleton.
var generations-
The type of the None singleton.
var given_name-
The type of the None singleton.
var given_names-
The type of the None singleton.
var hobbies-
The type of the None singleton.
var home_addresses-
The type of the None singleton.
var home_city-
The type of the None singleton.
var home_faxes-
The type of the None singleton.
var home_phones-
The type of the None singleton.
var home_phones2-
The type of the None singleton.
var home_sort_key-
The type of the None singleton.
var im_address-
The type of the None singleton.
var im_addresses-
The type of the None singleton.
var im_addresses2-
The type of the None singleton.
var im_addresses3-
The type of the None singleton.
var initials-
The type of the None singleton.
var locations-
The type of the None singleton.
var managers-
The type of the None singleton.
var middle_name-
The type of the None singleton.
var middle_names-
The type of the None singleton.
var mobile_phones-
The type of the None singleton.
var mobile_phones2-
The type of the None singleton.
var nickname-
The type of the None singleton.
var nicknames-
The type of the None singleton.
var office_locations-
The type of the None singleton.
var organization_main_phones-
The type of the None singleton.
var other_addresses-
The type of the None singleton.
var other_faxes-
The type of the None singleton.
var other_phones2-
The type of the None singleton.
var other_telephones-
The type of the None singleton.
var pagers-
The type of the None singleton.
var persona_object_type-
The type of the None singleton.
var persona_type-
The type of the None singleton.
var personal_home_pages-
The type of the None singleton.
var professions-
The type of the None singleton.
var radio_phones-
The type of the None singleton.
var relevance_score-
The type of the None singleton.
var schools-
The type of the None singleton.
var spouse_names-
The type of the None singleton.
var surname-
The type of the None singleton.
var surnames-
The type of the None singleton.
var telex_numbers-
The type of the None singleton.
var title-
The type of the None singleton.
var titles-
The type of the None singleton.
var tty_tdd_phone_numbers-
The type of the None singleton.
var wedding_anniversaries-
The type of the None singleton.
var work_city-
The type of the None singleton.
var work_city_sort_key-
The type of the None singleton.
var work_faxes-
The type of the None singleton.
var yomi_company_name-
The type of the None singleton.
var yomi_company_names-
The type of the None singleton.
var yomi_first_name-
The type of the None singleton.
var yomi_first_names-
The type of the None singleton.
var yomi_last_name-
The type of the None singleton.
var yomi_last_names-
The type of the None singleton.
Inherited members
class PostItem (**kwargs)-
Expand source code
class PostItem(Item): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/postitem""" ELEMENT_NAME = "PostItem" conversation_index = Message.FIELDS["conversation_index"] conversation_topic = Message.FIELDS["conversation_topic"] author = Message.FIELDS["author"] message_id = Message.FIELDS["message_id"] is_read = Message.FIELDS["is_read"] posted_time = DateTimeField(field_uri="postitem:PostedTime", is_read_only=True) references = TextField(field_uri="message:References") sender = MailboxField(field_uri="message:Sender", is_read_only=True, is_read_only_after_send=True)MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/postitem
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Instance variables
-
The type of the None singleton.
var conversation_index-
The type of the None singleton.
var conversation_topic-
The type of the None singleton.
var is_read-
The type of the None singleton.
var message_id-
The type of the None singleton.
var posted_time-
The type of the None singleton.
var references-
The type of the None singleton.
var sender-
The type of the None singleton.
Inherited members
Item:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachattachmentsbodycategoriesconversation_idculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightshas_attachmentsheadersimportancein_reply_tois_associatedis_draftis_from_meis_resendis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemime_contentparent_folder_idregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldresponse_objectssensitivitysizesubjectsupported_fieldstext_bodyunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
-
class PostReplyItem (**kwargs)-
Expand source code
class PostReplyItem(Item): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/postreplyitem""" ELEMENT_NAME = "PostReplyItem" # This element only has Item fields up to, and including, 'culture' # TDO: Plus all message fields new_body = BodyField(field_uri="NewBodyContent") # Accepts and returns Body or HTMLBody instances culture_idx = Item.FIELDS.index_by_name("culture") sender_idx = Message.FIELDS.index_by_name("sender") FIELDS = Item.FIELDS[: culture_idx + 1] + Message.FIELDS[sender_idx:]MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/postreplyitem
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Class variables
var culture_idx-
The type of the None singleton.
var sender_idx-
The type of the None singleton.
Instance variables
-
The type of the None singleton.
var bcc_recipients-
The type of the None singleton.
var cc_recipients-
The type of the None singleton.
var conversation_index-
The type of the None singleton.
var conversation_topic-
The type of the None singleton.
var is_delivery_receipt_requested-
The type of the None singleton.
var is_read-
The type of the None singleton.
var is_read_receipt_requested-
The type of the None singleton.
var is_response_requested-
The type of the None singleton.
var message_id-
The type of the None singleton.
var new_body-
The type of the None singleton.
var received_by-
The type of the None singleton.
var received_representing-
The type of the None singleton.
var references-
The type of the None singleton.
var reminder_message_data-
The type of the None singleton.
var reply_to-
The type of the None singleton.
var sender-
The type of the None singleton.
var to_recipients-
The type of the None singleton.
Inherited members
Item:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachattachmentsbodycategoriesconversation_idculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightshas_attachmentsheadersimportancein_reply_tois_associatedis_draftis_from_meis_resendis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemime_contentparent_folder_idregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldresponse_objectssensitivitysizesubjectsupported_fieldstext_bodyunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
class RegisterMixIn (**kwargs)-
Expand source code
class RegisterMixIn(IdChangeKeyMixIn, metaclass=EWSMeta): """Base class for classes that can change their list of supported fields dynamically.""" # This class implements dynamic fields on an element class, so we need to include __dict__ in __slots__ __slots__ = ("__dict__",) INSERT_AFTER_FIELD = None @classmethod def register(cls, attr_name, attr_cls): """Register a custom extended property in this item class so they can be accessed just like any other attribute :param attr_name: :param attr_cls: :return: """ if not cls.INSERT_AFTER_FIELD: raise ValueError(f"Class {cls} is missing INSERT_AFTER_FIELD value") try: cls.get_field_by_fieldname(attr_name) except InvalidField: pass else: raise ValueError(f"'attr_name' {attr_name!r} is already registered") if not issubclass(attr_cls, ExtendedProperty): raise TypeError(f"'attr_cls' {attr_cls!r} must be a subclass of type {ExtendedProperty}") # Check if class attributes are properly defined attr_cls.validate_cls() # ExtendedProperty is not a real field, but a placeholder in the fields list. See # https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/item # # Find the correct index for the new extended property, and insert. if attr_cls.is_array_type(): field = ExtendedPropertyListField(attr_name, value_cls=attr_cls) else: field = ExtendedPropertyField(attr_name, value_cls=attr_cls) cls.add_field(field, insert_after=cls.INSERT_AFTER_FIELD) @classmethod def deregister(cls, attr_name): """De-register an extended property that has been registered with register(). :param attr_name: :return: """ try: field = cls.get_field_by_fieldname(attr_name) except InvalidField: raise ValueError(f"{attr_name!r} is not registered") if not isinstance(field, ExtendedPropertyField): raise ValueError(f"{attr_name} is not registered as an ExtendedProperty") cls.remove_field(field)Base class for classes that can change their list of supported fields dynamically.
Ancestors
Subclasses
Class variables
var INSERT_AFTER_FIELD-
The type of the None singleton.
Static methods
def deregister(attr_name)-
De-register an extended property that has been registered with register().
:param attr_name: :return:
def register(attr_name, attr_cls)-
Register a custom extended property in this item class so they can be accessed just like any other attribute
:param attr_name: :param attr_cls: :return:
Inherited members
class ReplyAllToItem (**kwargs)-
Expand source code
class ReplyAllToItem(BaseReplyItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/replyalltoitem""" ELEMENT_NAME = "ReplyAllToItem"MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/replyalltoitem
Ancestors
Inherited members
class ReplyToItem (**kwargs)-
Expand source code
class ReplyToItem(BaseReplyItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/replytoitem""" ELEMENT_NAME = "ReplyToItem"Ancestors
Inherited members
class Task (**kwargs)-
Expand source code
class Task(Item): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/task""" ELEMENT_NAME = "Task" NOT_STARTED = "NotStarted" COMPLETED = "Completed" actual_work = IntegerField(field_uri="task:ActualWork", min=0) assigned_time = DateTimeField(field_uri="task:AssignedTime", is_read_only=True) billing_information = TextField(field_uri="task:BillingInformation") change_count = IntegerField(field_uri="task:ChangeCount", is_read_only=True, min=0) companies = TextListField(field_uri="task:Companies") # 'complete_date' can be set, but is ignored by the server, which sets it to now() complete_date = DateTimeField(field_uri="task:CompleteDate", is_read_only=True) contacts = TextListField(field_uri="task:Contacts") delegation_state = ChoiceField( field_uri="task:DelegationState", choices={ Choice("NoMatch"), Choice("OwnNew"), Choice("Owned"), Choice("Accepted"), Choice("Declined"), Choice("Max"), }, is_read_only=True, ) delegator = CharField(field_uri="task:Delegator", is_read_only=True) due_date = DateTimeBackedDateField(field_uri="task:DueDate") is_editable = BooleanField(field_uri="task:IsAssignmentEditable", is_read_only=True) is_complete = BooleanField(field_uri="task:IsComplete", is_read_only=True) is_recurring = BooleanField(field_uri="task:IsRecurring", is_read_only=True) is_team_task = BooleanField(field_uri="task:IsTeamTask", is_read_only=True) mileage = TextField(field_uri="task:Mileage") owner = CharField(field_uri="task:Owner", is_read_only=True) percent_complete = DecimalField( field_uri="task:PercentComplete", is_required=True, default=Decimal(0.0), min=Decimal(0), max=Decimal(100), is_searchable=False, ) recurrence = TaskRecurrenceField(field_uri="task:Recurrence", is_searchable=False) start_date = DateTimeBackedDateField(field_uri="task:StartDate") status = ChoiceField( field_uri="task:Status", choices={ Choice(NOT_STARTED), Choice("InProgress"), Choice(COMPLETED), Choice("WaitingOnOthers"), Choice("Deferred"), }, is_required=True, is_searchable=False, default=NOT_STARTED, ) status_description = CharField(field_uri="task:StatusDescription", is_read_only=True) total_work = IntegerField(field_uri="task:TotalWork", min=0) # O365 throws ErrorInternalServerError "[0x004f0102] MapiReplyToBlob" if UniqueBody is requested unique_body_idx = Item.FIELDS.index_by_name("unique_body") FIELDS = Item.FIELDS[:unique_body_idx] + Item.FIELDS[unique_body_idx + 1 :] def clean(self, version=None): super().clean(version=version) if self.due_date and self.start_date and self.due_date < self.start_date: log.warning( "'due_date' must be greater than 'start_date' (%s vs %s). Resetting 'due_date'", self.due_date, self.start_date, ) self.due_date = self.start_date if self.complete_date: if self.status != self.COMPLETED: log.warning( "'status' must be '%s' when 'complete_date' is set (%s). Resetting", self.COMPLETED, self.status ) self.status = self.COMPLETED now = datetime.datetime.now(tz=UTC) if (self.complete_date - now).total_seconds() > 120: # Reset complete_date values that are in the future # 'complete_date' can be set automatically by the server. Allow some grace between local and server time log.warning("'complete_date' must be in the past (%s vs %s). Resetting", self.complete_date, now) self.complete_date = now if self.start_date and self.complete_date.date() < self.start_date: log.warning( "'complete_date' must be greater than 'start_date' (%s vs %s). Resetting", self.complete_date, self.start_date, ) self.complete_date = EWSDateTime.combine(self.start_date, datetime.time(0, 0)).replace(tzinfo=UTC) if self.percent_complete is not None: if self.status == self.COMPLETED and self.percent_complete != Decimal(100): # percent_complete must be 100% if task is complete log.warning( "'percent_complete' must be 100 when 'status' is '%s' (%s). Resetting", self.COMPLETED, self.percent_complete, ) self.percent_complete = Decimal(100) elif self.status == self.NOT_STARTED and self.percent_complete != Decimal(0): # percent_complete must be 0% if task is not started log.warning( "'percent_complete' must be 0 when 'status' is '%s' (%s). Resetting", self.NOT_STARTED, self.percent_complete, ) self.percent_complete = Decimal(0) def complete(self): # A helper method to mark a task as complete on the server self.status = Task.COMPLETED self.percent_complete = Decimal(100) self.save()MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/task
Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Class variables
var COMPLETED-
The type of the None singleton.
var NOT_STARTED-
The type of the None singleton.
var unique_body_idx-
The type of the None singleton.
Instance variables
var actual_work-
The type of the None singleton.
var assigned_time-
The type of the None singleton.
var billing_information-
The type of the None singleton.
var change_count-
The type of the None singleton.
var companies-
The type of the None singleton.
var complete_date-
The type of the None singleton.
var contacts-
The type of the None singleton.
var delegation_state-
The type of the None singleton.
var delegator-
The type of the None singleton.
var due_date-
The type of the None singleton.
var is_complete-
The type of the None singleton.
var is_editable-
The type of the None singleton.
var is_recurring-
The type of the None singleton.
var is_team_task-
The type of the None singleton.
var mileage-
The type of the None singleton.
var owner-
The type of the None singleton.
var percent_complete-
The type of the None singleton.
var recurrence-
The type of the None singleton.
var start_date-
The type of the None singleton.
var status-
The type of the None singleton.
var status_description-
The type of the None singleton.
var total_work-
The type of the None singleton.
Methods
def clean(self, version=None)-
Expand source code
def clean(self, version=None): super().clean(version=version) if self.due_date and self.start_date and self.due_date < self.start_date: log.warning( "'due_date' must be greater than 'start_date' (%s vs %s). Resetting 'due_date'", self.due_date, self.start_date, ) self.due_date = self.start_date if self.complete_date: if self.status != self.COMPLETED: log.warning( "'status' must be '%s' when 'complete_date' is set (%s). Resetting", self.COMPLETED, self.status ) self.status = self.COMPLETED now = datetime.datetime.now(tz=UTC) if (self.complete_date - now).total_seconds() > 120: # Reset complete_date values that are in the future # 'complete_date' can be set automatically by the server. Allow some grace between local and server time log.warning("'complete_date' must be in the past (%s vs %s). Resetting", self.complete_date, now) self.complete_date = now if self.start_date and self.complete_date.date() < self.start_date: log.warning( "'complete_date' must be greater than 'start_date' (%s vs %s). Resetting", self.complete_date, self.start_date, ) self.complete_date = EWSDateTime.combine(self.start_date, datetime.time(0, 0)).replace(tzinfo=UTC) if self.percent_complete is not None: if self.status == self.COMPLETED and self.percent_complete != Decimal(100): # percent_complete must be 100% if task is complete log.warning( "'percent_complete' must be 100 when 'status' is '%s' (%s). Resetting", self.COMPLETED, self.percent_complete, ) self.percent_complete = Decimal(100) elif self.status == self.NOT_STARTED and self.percent_complete != Decimal(0): # percent_complete must be 0% if task is not started log.warning( "'percent_complete' must be 0 when 'status' is '%s' (%s). Resetting", self.NOT_STARTED, self.percent_complete, ) self.percent_complete = Decimal(0) def complete(self)-
Expand source code
def complete(self): # A helper method to mark a task as complete on the server self.status = Task.COMPLETED self.percent_complete = Decimal(100) self.save()
Inherited members
Item:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachattachmentsbodycategoriesconversation_idculturedatetime_createddatetime_receiveddatetime_sentderegisterdetachdisplay_ccdisplay_toeffective_rightshas_attachmentsheadersimportancein_reply_tois_associatedis_draftis_from_meis_resendis_submittedis_unmodifieditem_classlast_modified_namelast_modified_timemime_contentparent_folder_idregisterreminder_due_byreminder_is_setreminder_minutes_before_startremove_fieldresponse_objectssensitivitysizesubjectsupported_fieldstext_bodyunique_bodyvalidate_fieldweb_client_edit_form_query_stringweb_client_read_form_query_string
class TentativelyAcceptItem (**kwargs)-
Expand source code
class TentativelyAcceptItem(BaseMeetingReplyItem): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/tentativelyacceptitem""" ELEMENT_NAME = "TentativelyAcceptItem"Pick out optional 'account' and 'folder' kwargs, and pass the rest to the parent class.
:param kwargs: 'account' is optional but allows calling 'send()' and 'delete()' 'folder' is optional but allows calling 'save()'. If 'folder' has an account, and 'account' is not set, we use folder.account.
Ancestors
Inherited members
BaseMeetingReplyItem:ELEMENT_NAMEFIELDSID_ELEMENT_CLSINSERT_AFTER_FIELDNAMESPACEadd_fieldattachmentsbcc_recipientsbodycc_recipientsderegisterheadersis_delivery_receipt_requestedis_read_receipt_requesteditem_classproposed_endproposed_startreceived_byreceived_representingreference_item_idregisterremove_fieldsendersensitivitysupported_fieldsto_recipientsvalidate_field