2

Im trying to send an email via Exchange Web Services using suds 0.4.1:

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 

I'm able to authenticate fine, however I keep getting the following error:

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

Any advice would be much appreciated. Thanks

Imran Azad
  • 21
  • 1
  • 2
  • Turn on full SUDS logging to find out exactly what URL causes the error. I had a similar problem, turned out an overloaded www.w3.org server was the problem. The solution was to use a static cache for the www.w3.org schemas. See this answer: http://stackoverflow.com/a/8562410/3571 – codeape Dec 19 '11 at 14:11

1 Answers1

1

I've also been experiencing this issue. However, I only get this error intermittently. I found another post referring to a possible solution, and it helps some (I get the error less) but it hasn't fixed the issue completely.

The problem seems to be that the Exchange server closes the connection before sending a valid response. If anyone else can add more I would greatly appreciate it. This one has been driving me crazy.

Perhaps this may help you: urllib2 is throwing an error for an url , while it's opening properly in browser

I'm not sure if you're doing it already, but I needed to setup my script to download the messages.xsd, types.xsd, and the services.wsdl locally and patch it. with the following:

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

Hopefully this will point you in the right direction. Simply talking to Exchange with suds has been a major challenge. I found some help here, as well as the sample code that has provided the base for my project:

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

Update: Sending the correct SOAP headers with RequestServerVersion:

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

I've truncated the xml for brevity.

Community
  • 1
  • 1
serialworm
  • 761
  • 3
  • 13
  • I found the link to the demo.py and Exchange.py scripts that I used for my project. [link] http://web.archiveorange.com/archive/v/QOiOM0hVaQTkgK3oowG6 – serialworm Sep 22 '11 at 14:17
  • I found out why this is happening. It looks like when a suds client is initialized, it downloads the schema definition from http://www.w3.org/2001/xml.xsd. Due to the increase in web applications that need to get schema files from w3.org, the server is timing out and returning an empty response. Caching the schema definition locally has been suggested. Hope this helps. http://lists.w3.org/Archives/Public/site-comments/2011Apr/0026.html – serialworm Sep 23 '11 at 16:40
  • Thanks a lot I really appreciate all the information you have provided. I have been struggling with this for days. Thanks for the code but I'm already using it. I got it from the same link you suggested for demo.py and Exchange.py. Problem is I'm always getting the BadStatusLine, it's not worked once for me. – Imran Azad Sep 23 '11 at 17:36
  • 1
    Do you have a delay before the script fails? – serialworm Sep 23 '11 at 17:41
  • 1
    Yes there's a delay of about 35 seconds. – Imran Azad Sep 23 '11 at 18:14
  • I've managed to get past the BadStatusLine it was due to an unavailable reference to w3.org/2001/xml.xsd. However now I'm getting the following error:raise Exception('No versioninfo in response: %s' % response) xml.parsers.expat.ExpatError: no element found: line 1, column 0 – Imran Azad Sep 23 '11 at 19:38
  • I've narrowed it down further to this line:response = trans.geturl(url=url, authtype=authtype, data=xml) The problem seems to be that the server isn't returning a response header it just returns an empty response when a soap request is made for the server version. Any ideas why it's not returning anything? – Imran Azad Sep 23 '11 at 21:05
  • The SOAP headers that are sent to Exchange require the version info. Valid types are Exchange2007, Exchange2007_SP1, and Exchange2010. I've edited my answer above to include an example. – serialworm Sep 23 '11 at 21:15