ecederstrand/exchangelib

`ErrorNonExistentMailbox` in version 5.2.1 but not in 5.2.0

seanslma opened this issue · 6 comments

Describe the bug
My code works as expected in version 5.2.0 but got this error in 5.2.1:

exchangelib.errors.ErrorNonExistentMailbox: No mailbox with such guid.

To Reproduce

from exchangelib import (
    Account,
    Configuration,
    Credentials,
    DELEGATE,
    Message,
    NTLM,
)

server = 'owa.example.com'
sender = 'sender@example.com'
recipients = ['recipient_1@example.com']
username = 'username@example.com'
password = 'my-password'
 
config = Configuration(
    server=server,
    credentials=Credentials(username=username, password=password),
    auth_type=NTLM,
    version=None,
)
account = Account(sender, config=config, access_type=DELEGATE)

message = Message(
    account=account,
    subject='Test Email',
    body='Test OK',
    to_recipients=recipients,
)
message.send()

Expected behavior
The 5.2.1 should work as well

Log output

ErrorNonExistentMailbox                   Traceback (most recent call last)
Cell In[41], line 32
     24 account = Account(sender, config=config, access_type=DELEGATE)
     26 message = Message(
     27     account=account,
     28     subject='Test Email',
     29     body='Test OK',
     30     to_recipients=recipients,
     31 )
---> 32 message.send()

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\util.py:39, in require_account.<locals>.wrapper(self, *args, **kwargs)
     37 if not self.account:
     38     raise ValueError(f"{self.__class__.__name__} must have an account")
---> 39 return f(self, *args, **kwargs)

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\items\message.py:81, in Message.send(self, save_copy, copy_to_folder, conflict_resolution, send_meeting_invitations)
     78 if copy_to_folder:
     79     # This would better be done via send_and_save() but let's just support it here
     80     self.folder = copy_to_folder
---> 81     return self.send_and_save(
     82         conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations
     83     )
     85 if self.account.version.build < EXCHANGE_2013 and self.attachments:
     86     # At least some versions prior to Exchange 2013 can't send attachments immediately. You need to first save,
     87     # then attach, then send. This is done in send_and_save(). send() will delete the item again.
     88     self.send_and_save(
     89         conflict_resolution=conflict_resolution, send_meeting_invitations=send_meeting_invitations
     90     )

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\items\message.py:120, in Message.send_and_save(self, update_fields, conflict_resolution, send_meeting_invitations)
    110     self.save(
    111         update_fields=update_fields,
    112         conflict_resolution=conflict_resolution,
    113         send_meeting_invitations=send_meeting_invitations,
    114     )
    115     return self.send(
    116         save_copy=False,
    117         conflict_resolution=conflict_resolution,
    118         send_meeting_invitations=send_meeting_invitations,
    119     )
--> 120 return self._create(message_disposition=SEND_AND_SAVE_COPY, send_meeting_invitations=send_meeting_invitations)

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\util.py:39, in require_account.<locals>.wrapper(self, *args, **kwargs)
     37 if not self.account:
     38     raise ValueError(f"{self.__class__.__name__} must have an account")
---> 39 return f(self, *args, **kwargs)

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\items\item.py:185, in Item._create(self, message_disposition, send_meeting_invitations)
    179 @require_account
    180 def _create(self, message_disposition, send_meeting_invitations):
    181     # Return a BulkCreateResult because we want to return the ID of both the main item *and* attachments. In send
    182     # and send-and-save-copy mode, the server does not return an ID, so we just return True.
    183     from ..services import CreateItem
--> 185     return CreateItem(account=self.account).get(
    186         items=[self],
    187         folder=self.folder,
    188         message_disposition=message_disposition,
    189         send_meeting_invitations=send_meeting_invitations,
    190     )

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\services\common.py:164, in EWSService.get(self, expect_result, **kwargs)
    156 def get(self, expect_result=True, **kwargs):
    157     """Like .call(), but expects exactly one result from the server, or zero when expect_result=False, or either
    158     zero or one when expect_result=None. Returns either one object or None.
    159 
   (...)
    162     :return: Same as .call(), but returns either None or exactly one item
    163     """
--> 164     res = list(self.call(**kwargs))
    165     # Raise any errors
    166     for r in res:

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\services\common.py:225, in EWSService._elems_to_objs(self, elems)
    223 def _elems_to_objs(self, elems):
    224     """Takes a generator of XML elements and exceptions. Returns the equivalent Python objects (or exceptions)."""
--> 225     for elem in elems:
    226         # Allow None here. Some services don't return an ID if the target folder is outside the mailbox.
    227         if isinstance(elem, (Exception, type(None))):
    228             yield elem

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\services\common.py:287, in EWSService._chunked_get_elements(self, payload_func, items, **kwargs)
    285 for i, chunk in enumerate(chunkify(filtered_items, self.chunk_size), start=1):
    286     log.debug("Processing chunk %s containing %s items", i, len(chunk))
--> 287     yield from self._get_elements(payload=payload_func(chunk, **kwargs))

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\services\common.py:308, in EWSService._get_elements(self, payload)
    304 while True:
    305     try:
    306         # Create a generator over the response elements so exceptions in response elements are also raised
    307         # here and can be handled.
--> 308         yield from self._response_generator(payload=payload)
    309         # TODO: Restore session pool size on succeeding request?
    310         return

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\services\common.py:684, in EWSService._get_elements_in_response(self, response)
    659 """Take a list of 'SomeServiceResponseMessage' elements and return the elements in each response message that
    660 we want the service to return. With e.g. 'CreateItem', we get a list of 'CreateItemResponseMessage' elements
    661 and return the 'Message' elements.
   (...)
    681 :return: a generator of items as returned by '_get_elements_in_container()
    682 """
    683 for msg in response:
--> 684     container_or_exc = self._get_element_container(message=msg, name=self.element_container_name)
    685     if isinstance(container_or_exc, (bool, Exception)):
    686         yield container_or_exc

File ~\conda-envs\env_py39\lib\site-packages\exchangelib\services\common.py:606, in EWSService._get_element_container(self, message, name)
    604 # response_class == 'Error', or 'Success' and not 'NoError'
    605 try:
--> 606     raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml)
    607 except self.ERRORS_TO_CATCH_IN_RESPONSE as e:
    608     return e

ErrorNonExistentMailbox: No mailbox with such guid.

Additional context
For example, Python and exchangelib versions.

  • Python: 3.9
  • exchangelib: 5.2.1

This is covered by the test suite, so there must be something else going on.

Your best bet is to enable debug logging and comparing the XML requests and responses for a working 5.2.0 and a non-working exchangelib 5.2.1 version, to see how the new version queries the server differently.

I encountered that the 5.2.1 version does not work with SingleFolderQuerySet(), with 5.2.0 works perfect.

@seanslma Did you get a chance to debug this?

@ecederstrand Thanks. Was occupied by other things and pinned the version to 5.2.0.

The only difference in Request XML:
image

Version 5.2.1

<t:DistinguishedFolderId Id="sentitems"/>

Version 5.2.0

<t:DistinguishedFolderId Id="sentitems">
<t:Mailbox>
<t:EmailAddress>sender@example.com</t:EmailAddress>
<t:RoutingType>SMTP</t:RoutingType>
<t:MailboxType>Mailbox</t:MailboxType>
</t:Mailbox>
</t:DistinguishedFolderId>

Also there are more debug info in version 5.2.1:
image

Thanks for the debug info! I believe d9035d0 may fix this for you. Can you try it out?