首页 > 解决方案 > 501 无效请求

问题描述

我正在使用 exchangelib 对我们的邮件系统进行一些端到端的测试。目前,在提出请求时,我收到了 501。

# Tell exchangelib to use this adapter class instead of the default
BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter

...

version = Version(api_version="Exchange2013_SP1", build=Build(15, 0, 847))
credentials = Credentials(username=outlook_profile['Username'], password=outlook_profile['Password'])
config = Configuration(server="<SERVICEURL>", credentials=credentials, auth_type=NTLM, version=version)
account = Account(primary_smtp_address="<USER>@<DOMAIN>", config=config, autodiscover=False, access_type=DELEGATE)

print(account.inbox.total_count)

错误:

WARNING:exchangelib.services.common:EWS https://<SERVICEURL>/EWS/Exchange.asmx, account <USER>@<DOMAIN>: Exception in _get_elements: Traceback (most recent call last):
  File "C:\Python38\lib\site-packages\cached_property.py", line 69, in __get__
    return obj_dict[name]
KeyError: 'root'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python38\lib\site-packages\exchangelib\services\common.py", line 84, in _get_elements
    response = self._get_response_xml(payload=payload)
  File "C:\Python38\lib\site-packages\exchangelib\services\common.py", line 150, in _get_response_xml
    r, session = post_ratelimited(
  File "C:\Python38\lib\site-packages\exchangelib\util.py", line 770, in post_ratelimited
    _raise_response_errors(r, protocol, log_msg, log_vals)  # Always raises an exception
  File "C:\Python38\lib\site-packages\exchangelib\util.py", line 851, in _raise_response_errors
    raise TransportError(str('Unknown failure\n') + log_msg % log_vals)
exchangelib.errors.TransportError: Unknown failure
Retry: 0
Waited: 10
Timeout: 120
Session: 24770
Thread: 34952
Auth type: <requests_ntlm.requests_ntlm.HttpNtlmAuth object at 0x000001B2F697A310>
URL: https://<SERVICEURL>/EWS/Exchange.asmx
HTTP adapter: <exchangelib.protocol.NoVerifyHTTPAdapter object at 0x000001B2F697A0A0>
Allow redirects: False
Streaming: False
Response time: 0.0779999999795109
Status code: 501
Request headers: {'User-Agent': 'exchangelib/3.2.0 (python-requests/2.23.0)', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'Keep-Alive', 'Content-Type': 'text/xml; charset=utf-8', 'X-AnchorMailbox': '<USER>@<DOMAIN>', 'Content-Length': '1304', 'Authorization': 'NTLM <HASH>'}
Response headers: {'Date': 'Wed, 10 Jun 2020 21:38:09 GMT', 'X-Frame-Options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'X-Content-Type-Options': 'nosniff', 'Connection': 'close', 'Content-Length': '87', 'Content-Type': 'text/html'}
Request data: b'<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"><s:Header><t:RequestServerVersion Version="Exchange2013_SP1"/><t:ExchangeImpersonation><t:ConnectingSID><t:PrimarySmtpAddress><USER>@<DOMAIN></t:PrimarySmtpAddress></t:ConnectingSID></t:ExchangeImpersonation><t:TimeZoneContext><t:TimeZoneDefinition Id="UTC"/></t:TimeZoneContext></s:Header><s:Body><m:GetFolder><m:FolderShape><t:BaseShape>IdOnly</t:BaseShape><t:AdditionalProperties><t:FieldURI FieldURI="folder:FolderId"/><t:FieldURI FieldURI="folder:ChildFolderCount"/><t:FieldURI FieldURI="folder:EffectiveRights"/><t:FieldURI FieldURI="folder:FolderClass"/><t:FieldURI FieldURI="folder:DisplayName"/><t:FieldURI FieldURI="folder:ParentFolderId"/><t:FieldURI FieldURI="folder:TotalCount"/><t:FieldURI FieldURI="folder:UnreadCount"/></t:AdditionalProperties></m:FolderShape><m:FolderIds><t:DistinguishedFolderId Id="root"><t:Mailbox><t:EmailAddress><USER>@<DOMAIN></t:EmailAddress><t:RoutingType>SMTP</t:RoutingType><t:MailboxType>Mailbox</t:MailboxType></t:Mailbox></t:DistinguishedFolderId></m:FolderIds></m:GetFolder></s:Body></s:Envelope>'
Response data: b'<html><head><title>501 Invalid Request</title></head><body>Invalid Request: ??</body>\r\n'

但是,当我使用 powershell EWS 库连接(成功)到我的电子邮件系统时,我可以看到我的请求正文看起来完全不同,尤其是在soap:Envelope标签方面:

POST https://<SERVICEURL>/EWS/Exchange.asmx HTTP/1.1
Content-Type: text/xml; charset=utf-8
Accept: text/xml
User-Agent: ExchangeServicesClient/15.00.0847.030
Accept-Encoding: gzip,deflate
Authorization: NTLM <HASH>
Host: <SERVICEURL>
Content-Length: 673
Expect: 100-continue

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2013_SP1" />
  </soap:Header>
  <soap:Body>
    <m:GetFolder>
      <m:FolderShape>
        <t:BaseShape>AllProperties</t:BaseShape>
      </m:FolderShape>
      <m:FolderIds>
        <t:DistinguishedFolderId Id="inbox" />
      </m:FolderIds>
    </m:GetFolder>
  </soap:Body>
</soap:Envelope>

此外,如果我改为使用 来定位自动发现 URL exchangelib,我可以正确解析服务器,但仍会收到相同的 501 错误。因此凭据已正确配置。

如果需要,我可以提供其他信息。非常欢迎任何帮助。

更新 1

exchangelib通过拆分请求,我能够正确地验证和查询服务器,而不是使用该模块:

session = requests.Session()
session.mount('https://', adapter)
session.headers.update({'Content-Type': 'text/xml; charset=utf-8', 'Expect': '100-continue'})
session.auth = HttpNtlmAuth(domain\\username, password)
session.post('https://SERVICEURL/EWS/Exchange.asmx', verify=False)
session.post('https://SERVICEURL/EWS/Exchange.asmx', data=body, verify=False)

这是为查询收件箱而生成body的确切请求正文:excahngelib

<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">' \
  <s:Header>
    <t:RequestServerVersion Version="Exchange2013_SP1"/>
    <t:TimeZoneContext>
      <t:TimeZoneDefinition Id="UTC"/>
    </t:TimeZoneContext>
  </s:Header>
  <s:Body>
    <m:GetFolder>
      <m:FolderShape>
        <t:BaseShape>IdOnly</t:BaseShape>
        <t:AdditionalProperties>
          <t:FieldURI FieldURI="folder:FolderId"/>
          <t:FieldURI FieldURI="folder:ChildFolderCount"/>
          <t:FieldURI FieldURI="folder:EffectiveRights"/>
          <t:FieldURI FieldURI="folder:FolderClass"/>
          <t:FieldURI FieldURI="folder:DisplayName"/>
          <t:FieldURI FieldURI="folder:ParentFolderId"/>
          <t:FieldURI FieldURI="folder:TotalCount"/>
          <t:FieldURI FieldURI="folder:UnreadCount"/>
        </t:AdditionalProperties>
      </m:FolderShape>
      <m:FolderIds>
        <t:DistinguishedFolderId Id="root">
          <t:Mailbox>
            <t:EmailAddress>username@domain</t:EmailAddress>      
            <t:RoutingType>SMTP</t:RoutingType> 
            <t:MailboxType>Mailbox</t:MailboxType>
          </t:Mailbox>
        </t:DistinguishedFolderId>
      </m:FolderIds>
    </m:GetFolder>
  </s:Body>
</s:Envelope>

标签: pythonsoapexchangelib

解决方案


推荐阅读