Skip to main content
 首页 » 编程设计

python之Exchange Web 服务 (EWS)之通过 suds 的 Exchange 2010 soap 调用

2025年05月04日7飞鱼

我正在尝试使用 suds 0.4.1 通过 Exchange Web 服务发送电子邮件:

import suds  
from suds.client import Client  
from suds.transport.https import WindowsHttpAuthenticated 
 
url = "file:///C:/Services.wsdl"  
user = 'domain\\user'  
password = "hardtoguess" 
 
ntlm = WindowsHttpAuthenticated(username=user,password=password)  
c = Client(url, transport=ntlm) 
 
xml = ''' <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <CreateItem      
MessageDisposition="SendAndSaveCopy" 
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages"> 
<SavedItemFolderId> <DistinguishedFolderId Id="sentitems" 
xmlns="http://schemas.microsoft.com/exchange/services/2006/types"/>  
</SavedItemFolderId> <Items> <Message 
xmlns="http://schemas.microsoft.com/exchange/services/2006/types">   
<ItemClass>IPM.Note</ItemClass> <Subject>Sent via Python->Exchange->EWS</Subject>   
<Body BodyType="Text">This message has been sent to you via Python, 
Exchange and EWS :)</Body> <ToRecipients> <Mailbox>  
<EmailAddress>imran.azad@localhost</EmailAddress> </Mailbox> </ToRecipients>    
</Message> </Items>  
</CreateItem> </soap:Body></soap:Envelope>'''  
 
attr = c.service.CreateItem(__inject={'msg':xml}) 
 
xml = ''' <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"> <soap:Body>   
<ResolveNames 
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages" 
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" 
ReturnFullContactData="true"> <UnresolvedEntry>azadi</UnresolvedEntry>  
</ResolveNames> </soap:Body> </soap:Envelope> '''  
 
attr = c.service.ResolveNames(__inject={'msg':t}) 
 
 print attr  

我能够很好地进行身份验证,但是我不断收到以下错误:

Traceback (most recent call last): 
  File "soap.py", line 10, in <module> 
    c = Client(url, transport=ntlm) 
  File "build\bdist.win32\egg\suds\client.py", line 112, in __init__ 
  File "build\bdist.win32\egg\suds\reader.py", line 152, in open 
  File "build\bdist.win32\egg\suds\wsdl.py", line 159, in __init__ 
  File "build\bdist.win32\egg\suds\wsdl.py", line 220, in build_schema 
  File "build\bdist.win32\egg\suds\xsd\schema.py", line 93, in load 
  File "build\bdist.win32\egg\suds\xsd\schema.py", line 305, in open_imports 
  File "build\bdist.win32\egg\suds\xsd\sxbasic.py", line 542, in open 
  File "build\bdist.win32\egg\suds\xsd\sxbasic.py", line 563, in download 
  File "build\bdist.win32\egg\suds\xsd\schema.py", line 397, in instance 
  File "build\bdist.win32\egg\suds\xsd\schema.py", line 226, in __init__ 
  File "build\bdist.win32\egg\suds\xsd\schema.py", line 305, in open_imports 
  File "build\bdist.win32\egg\suds\xsd\sxbasic.py", line 542, in open 
  File "build\bdist.win32\egg\suds\xsd\sxbasic.py", line 563, in download 
  File "build\bdist.win32\egg\suds\xsd\schema.py", line 397, in instance 
  File "build\bdist.win32\egg\suds\xsd\schema.py", line 226, in __init__ 
  File "build\bdist.win32\egg\suds\xsd\schema.py", line 305, in open_imports 
  File "build\bdist.win32\egg\suds\xsd\sxbasic.py", line 542, in open 
  File "build\bdist.win32\egg\suds\xsd\sxbasic.py", line 560, in download 
  File "build\bdist.win32\egg\suds\reader.py", line 79, in open 
  File "build\bdist.win32\egg\suds\reader.py", line 95, in download 
  File "build\bdist.win32\egg\suds\transport\https.py", line 60, in open 
  File "build\bdist.win32\egg\suds\transport\http.py", line 62, in open 
  File "build\bdist.win32\egg\suds\transport\http.py", line 118, in u2open 
  File "C:\Python26\lib\urllib2.py", line 391, in open 
    response = self._open(req, data) 
  File "C:\Python26\lib\urllib2.py", line 409, in _open 
    '_open', req) 
  File "C:\Python26\lib\urllib2.py", line 369, in _call_chain 
    result = func(*args) 
  File "C:\Python26\lib\urllib2.py", line 1170, in http_open 
    return self.do_open(httplib.HTTPConnection, req) 
  File "C:\Python26\lib\urllib2.py", line 1143, in do_open 
    r = h.getresponse() 
  File "C:\Python26\lib\httplib.py", line 990, in getresponse 
    response.begin() 
  File "C:\Python26\lib\httplib.py", line 391, in begin 
    version, status, reason = self._read_status() 
  File "C:\Python26\lib\httplib.py", line 355, in _read_status 
    raise BadStatusLine(line) 
httplib.BadStatusLine 

如有任何建议,我们将不胜感激。谢谢

请您参考如下方法:

我也遇到过这个问题。但是,我只是间歇性地收到此错误。我找到了另一篇提到可能解决方案的帖子,它对一些人有所帮助(我得到的错误更少),但它并没有完全解决问题。

问题似乎是 Exchange 服务器在发送有效响应之前关闭了连接。如果其他人可以添加更多,我将不胜感激。这个一直让我发疯。

也许这可以帮助你: urllib2 is throwing an error for an url , while it's opening properly in browser

我不确定您是否已经这样做了,但我需要设置脚本以在本地下载 messages.xsd、types.xsd 和 services.wsdl 并对其进行修补。具有以下内容:

def setup(self): 
    '''Patches the WSDL file to include a service tag. Returns path to 
    local WSDL file.''' 
    trans = self.transport 
    try: 
        makedirs(self.localdir) 
    except OSError: 
        # Directory already exists 
        pass 
 
    # Download messags.xsd file 
    messages_url = '%s/messages.xsd' % self.urlprefix 
    with open('%s/%s' % (self.localdir, 'messages.xsd'), 'w') as msg_xsd: 
        msg_xsd.write(trans.geturl(messages_url, trans.authtype)) 
 
    # Download types.xsd file 
    types_url = '%s/types.xsd' % self.urlprefix 
    with open('%s/%s' % (self.localdir, 'types.xsd'), 'w') as types_xsd: 
        types_xsd.write(trans.geturl(types_url, trans.authtype)) 
 
    # Modify WSDL to add service description 
    service_url = '%s/Exchange.asmx' % self.urlprefix 
    servicexml = ''' 
        <wsdl:service name="ExchangeServices"> 
            <wsdl:port name="ExchangeServicePort" binding="tns:ExchangeServiceBinding"> 
                  <soap:address location="%s"/> 
                </wsdl:port> 
          </wsdl:service> 
        </wsdl:definitions>''' % service_url 
    localwsdl = '%s/%s' % (self.localdir, 'Services.wsdl') 
    wsdlxml = trans.geturl(self.wsdl, trans.authtype) 
    with open(localwsdl, 'w') as wsdl: 
        wsdl.write(wsdlxml.replace('</wsdl:definitions>', servicexml)) 
 
    return localwsdl 

希望这会为您指明正确的方向。简单地用泡沫与 Exchange 交谈一直是一个重大挑战。我在这里找到了一些帮助,以及为我的项目提供基础的示例代码:

http://lists.fedoraproject.org/pipermail/suds/2010-September/001144.html

更新: 使用 RequestServerVersion 发送正确的 SOAP header :

<?xml version="1.0" encoding="utf-8"?> 
  <soap:Envelope> 
    <soap:Header> 
      <t:RequestServerVersion Version="Exchange2010"/> 
    </soap:Header> 
    <soap:Body> 
    </soap:Body> 
 </soap:Envelope> 

为简洁起见,我截断了 xml。