Hi all,
It seems some people are using, or trying to use, Suds to connect to Exchange servers using EWS. As it's a bit convoluted, I'd like to share the working code I have (attached), in the hopes of creating at least a minimal Python EWS module in a joined effort. I have tested using Suds 0.4.
Currently, I have implemented functions to set up an Exchange object, autodetect the server version and authentication type, download and patch the Services.wsdl and xsd files. I also have functions to find, create and delete calendar items, as that's what I need myself.
If anyone's interested in improving the code or if you get any error messages, please contact me. demo.py shows how to use the module.
Thanks, Erik
Den 21/07/2010 kl. 13.28 skrev Erik Cederstrand:
Hi all,
It seems some people are using, or trying to use, Suds to connect to Exchange servers using EWS. As it's a bit convoluted, I'd like to share the working code I have (attached), in the hopes of creating at least a minimal Python EWS module in a joined effort. I have tested using Suds 0.4.
Currently, I have implemented functions to set up an Exchange object, autodetect the server version and authentication type, download and patch the Services.wsdl and xsd files. I also have functions to find, create and delete calendar items, as that's what I need myself.
If anyone's interested in improving the code or if you get any error messages, please contact me. demo.py shows how to use the module.
Sorry, last minute edit gone wrong. Here's an Exchange.py that will even compile.
Erik
Hi Erik,
Thank you so much for the great example code!
This is what I get when I run it:
Traceback (most recent call last): File "demo.py", line 11, in <module> exchange = Exchange(domain=domain, username=user, password=pw, datadir=datadir) File "/Users/jeckersley/Sites/geminiDigest/Exchange.py", line 76, in __init__ self.client = Client(url=localwsdl, transport=auth, cachingpolicy=1) File "build/bdist.macosx-10.6-universal/egg/suds/client.py", line 109, in __init__ File "build/bdist.macosx-10.6-universal/egg/suds/client.py", line 127, in set_options File "build/bdist.macosx-10.6-universal/egg/suds/properties.py", line 259, in update File "build/bdist.macosx-10.6-universal/egg/suds/properties.py", line 284, in set File "build/bdist.macosx-10.6-universal/egg/suds/properties.py", line 423, in __set File "build/bdist.macosx-10.6-universal/egg/suds/properties.py", line 245, in definition AttributeError: cachingpolicy
- Jared
On 7/21/10 1:41 AM, "Erik Cederstrand" erik@cederstrand.dk wrote:
Den 21/07/2010 kl. 13.28 skrev Erik Cederstrand:
Hi all,
It seems some people are using, or trying to use, Suds to connect to Exchange servers using EWS. As it's a bit convoluted, I'd like to share the working code I have (attached), in the hopes of creating at least a minimal Python EWS module in a joined effort. I have tested using Suds 0.4.
Currently, I have implemented functions to set up an Exchange object, autodetect the server version and authentication type, download and patch the Services.wsdl and xsd files. I also have functions to find, create and delete calendar items, as that's what I need myself.
If anyone's interested in improving the code or if you get any error messages, please contact me. demo.py shows how to use the module.
Sorry, last minute edit gone wrong. Here's an Exchange.py that will even compile.
Erik
suds mailing list suds@lists.fedoraproject.org https://admin.fedoraproject.org/mailman/listinfo/suds
On Wednesday 21 July 2010, Jared Eckersley elucidated thus:
Hi Erik,
Thank you so much for the great example code!
This is what I get when I run it:
Jared -
What version of suds are you running?
j
Hi,
I just installed .4 and ran the demo again. This is what I am getting now:
Traceback (most recent call last): File "demo.py", line 4, in <module> from Exchange import Exchange, EWSDateTime File "/Users/jeckersley/Sites/geminiDigest/Exchange.py", line 33, in <module> from suds.transport.https import WindowsHttpAuthenticated ImportError: cannot import name WindowsHttpAuthenticated
- Jared
On 7/21/10 2:04 PM, "Joshua J. Kugler" joshua@eeinternet.com wrote:
On Wednesday 21 July 2010, Jared Eckersley elucidated thus:
Hi Erik,
Thank you so much for the great example code!
This is what I get when I run it:
Jared -
What version of suds are you running?
j
On Wednesday 21 July 2010, Jared Eckersley elucidated thus:
Hi,
I just installed .4 and ran the demo again. This is what I am getting now:
Traceback (most recent call last): File "demo.py", line 4, in <module> from Exchange import Exchange, EWSDateTime File "/Users/jeckersley/Sites/geminiDigest/Exchange.py", line 33, in <module> from suds.transport.https import WindowsHttpAuthenticated ImportError: cannot import name WindowsHttpAuthenticated
Do you have the python NTLM module installed?
j
Yes - I have the current python26 trunk.
On 7/21/10 2:13 PM, "Joshua J. Kugler" joshua@eeinternet.com wrote:
On Wednesday 21 July 2010, Jared Eckersley elucidated thus:
Hi,
I just installed .4 and ran the demo again. This is what I am getting now:
Traceback (most recent call last): File "demo.py", line 4, in <module> from Exchange import Exchange, EWSDateTime File "/Users/jeckersley/Sites/geminiDigest/Exchange.py", line 33, in <module> from suds.transport.https import WindowsHttpAuthenticated ImportError: cannot import name WindowsHttpAuthenticated
Do you have the python NTLM module installed?
j
Den 22/07/2010 kl. 02.10 skrev Jared Eckersley:
Hi,
I just installed .4 and ran the demo again. This is what I am getting now:
Traceback (most recent call last): File "demo.py", line 4, in <module> from Exchange import Exchange, EWSDateTime File "/Users/jeckersley/Sites/geminiDigest/Exchange.py", line 33, in
<module> from suds.transport.https import WindowsHttpAuthenticated ImportError: cannot import name WindowsHttpAuthenticated
That's strange. I have a /python-suds-0.4/suds/transport/https.py file which defines a class WindowsHttpAuthenticated(HttpAuthenticated), whic in turn tries this:
from ntlm import HTTPNtlmAuthHandler
Can you check if that's correct in your version? If you have Suds 0.4 installed, and python is actually using it, and you have the ntlm module installed, things should just work. Which system are you on? Can you try deinstalling all previous Suds versions and installing just 0.4?
Thanks, Erik
Den 23/07/2010 kl. 09.08 skrev Erik Cederstrand:
That's strange. I have a /python-suds-0.4/suds/transport/https.py file which defines a class WindowsHttpAuthenticated(HttpAuthenticated), whic in turn tries this:
from ntlm import HTTPNtlmAuthHandler
Can you check if that's correct in your version? If you have Suds 0.4 installed, and python is actually using it, and you have the ntlm module installed, things should just work. Which system are you on? Can you try deinstalling all previous Suds versions and installing just 0.4?
Alternatively, run this in python:
import suds import ntlm print sys.modules['suds'] print sys.modules['ntlm']
and give us the output.
Thanks, Erik
I was able to manually remove the python-ntlm library and reinstall and got it working again.
Here is where I am now:
I ran this vbs script that sends an email via ews - and it worked. So at least I know the exchange server is setup correctly.
Here is the vbs script: emailaddress = "jeckersley@gemini.edu" stSubjet = "hello World" ebEmailBody = "1234567910 Blast Off" servername = "mail.gemini.edu"
smSoapMessage = "<?xml version='1.0' encoding='utf-8'?>" _ & "<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%22%22%3E" _ & "soap:Body<CreateItem MessageDisposition=""SendAndSaveCopy"" " _ & " xmlns=""http://schemas.microsoft.com/exchange/services/2006/messages%22%22%3E " _ & "<SavedItemFolderId><DistinguishedFolderId Id=""sentitems"" xmlns=""http://schemas.microsoft.com/exchange/services/2006/types%22%22/%3E" _ & "</SavedItemFolderId><Items><Message xmlns=""http://schemas.microsoft.com/exchange/services/2006/types%22%22%3E" _ & "<ItemClass>IPM.Note</ItemClass><Subject>" & stSubjet & "</Subject><Body BodyType=""Text"">" & ebEmailBody & "</Body><ToRecipients>" _ & "<Mailbox><EmailAddress>" & EmailAddress & "</EmailAddress></Mailbox></ToRecipients></Message></Items>" _ & "</CreateItem></soap:Body></soap:Envelope>" set req = createobject("microsoft.xmlhttp")
req.Open "post", "https://" & servername & "/ews/Exchange.asmx", False,"GEMINI\jeckersley", "XXX" req.setRequestHeader "Content-Type", "text/xml" req.setRequestHeader "translate", "F" req.send smSoapMessage wscript.echo req.status wscript.echo wscript.echo req.responsetext
Here is the cleaned up XML from the vbs script: 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> Hello, world </Subject> <Body BodyType="Text">"This is a test.</Body> <ToRecipients> <Mailbox> <EmailAddress>jeckersley@gemini.edu</EmailAddress> </Mailbox> </ToRecipients> </Message> </Items> </CreateItem> </soap:Body>
Then I tried to recreate this in python with suds: import suds from suds.client import Client from suds.transport.https import WindowsHttpAuthenticated
# test stuff from suds.sax.element import Element from suds.sax.attribute import Attribute
import logging logging.basicConfig(level=logging.INFO) logging.getLogger('suds.client').setLevel(logging.DEBUG)
url = "file:///Users/jeckersley/Sites/geminiDigest/Services.wsdl" user = 'GEMINI\jeckersley' password = "xxx"
ntlm = WindowsHttpAuthenticated(username=user,password=password) c = Client(url, transport=ntlm, location='https://mail.gemini.edu/EWS/Exchange.asmx')
createitem = Element('CreateItem') createitem.set('MessageDisposition', 'SendAndSaveCopy') createitem.set('xmlns','http://schemas.microsoft.com/exchange/services/2006/ messages')
saveditemfolderid = Element('SavedItemFolderId') distinguishedfolderid = Element('DistinguishedFolderId') distinguishedfolderid.set('Id', 'sentitems') distinguishedfolderid.set('xmlns','http://schemas.microsoft.com/exchange/ser vices/2006/types') saveditemfolderid.append(distinguishedfolderid) createitem.append(saveditemfolderid)
items = Element('Items') message = Element('Message') message.set('xmlns','http://schemas.microsoft.com/exchange/services/2006/typ es') itemclass = Element('ItemClass').setText('IPM.Note') message.append(itemclass) subject = Element('Subject').setText('This is a test') message.append(subject) body = Element('Body').setText('Hello World') body.set('BodyType', 'Text') message.append(body) torecipients = Element('ToRecipients') mailbox = Element('Mailbox') emailaddress = Element('EmailAddress').setText('jeckersley@gemini.edu') mailbox.append(emailaddress) torecipients.append(mailbox) message.append(torecipients) items.append(message) createitem.append(items)
attr = c.service.CreateItem(createitem)
Here is the xml this is generating: <?xml version="1.0" encoding="UTF-8"?> <document> <SOAP-ENV:Envelope xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.microsoft.com/exchange/services/2006/messages" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/%22%3E SOAP-ENV:Header/ ns0:Body ns1:CreateItem <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>This is a test</Subject> <Body BodyType="Text">Hello World</Body> <ToRecipients> <Mailbox>
<EmailAddress>jeckersley@gemini.edu</EmailAddress> </Mailbox> </ToRecipients> </Message> </Items> </CreateItem> ns1:Items/ </ns1:CreateItem> </ns0:Body> </SOAP-ENV:Envelope> </document>
This is giving me the error: suds.WebFault: Server raised fault: 'The request is invalid.'
Still stuck, but making a little progress.
- Jared
On 7/22/10 9:08 PM, "Erik Cederstrand" erik@cederstrand.dk wrote:
Den 22/07/2010 kl. 02.10 skrev Jared Eckersley:
Hi,
I just installed .4 and ran the demo again. This is what I am getting now:
Traceback (most recent call last): File "demo.py", line 4, in <module> from Exchange import Exchange, EWSDateTime File "/Users/jeckersley/Sites/geminiDigest/Exchange.py", line 33, in
<module> from suds.transport.https import WindowsHttpAuthenticated ImportError: cannot import name WindowsHttpAuthenticated
That's strange. I have a /python-suds-0.4/suds/transport/https.py file which defines a class WindowsHttpAuthenticated(HttpAuthenticated), whic in turn tries this:
from ntlm import HTTPNtlmAuthHandler
Can you check if that's correct in your version? If you have Suds 0.4 installed, and python is actually using it, and you have the ntlm module installed, things should just work. Which system are you on? Can you try deinstalling all previous Suds versions and installing just 0.4?
Thanks, Erik
Hi Jared,
Den 23/07/2010 kl. 09.22 skrev Jared Eckersley:
I was able to manually remove the python-ntlm library and reinstall and got it working again.
Great. Could you try my script again and see if it works for you?
createitem = Element('CreateItem')
[...]
attr = c.service.CreateItem(createitem)
CreateItem() takes as arguments the elements within createitem, i.e. 'saveditemfolderid' and 'items'. You shouldn't create the 'createitem' element. If you look at your XML, you have the CreateItem tag twice:
<ns1:CreateItem> <CreateItem MessageDisposition="SendAndSaveCopy"
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages%22%3E
Your namespace usage is also funky. You need to clean that up if you get more 'Invalid request' messages.
Finally, you can't use the factory methods, since CreateItem expects the attribute MessageDisposition, and Suds doesn't support that without the patch in ticket #21. Generate the full XML instead (including headers) and inject it:
c.service.CreateItem(__inject={'msg':xml})
Thanks, Erik
Hi Erik,
This is what I get when I run your script: python demo.py Traceback (most recent call last): File "demo.py", line 11, in <module> exchange = Exchange(domain=domain, username=user, password=pw, datadir=datadir) File "/Users/jeckersley/Sites/geminiDigest/Exchange.py", line 79, in __init__ self.version = self.Version(self) File "/Users/jeckersley/Sites/geminiDigest/Exchange.py", line 136, in __init__ self.minorbuildnumber = self.get() File "/Users/jeckersley/Sites/geminiDigest/Exchange.py", line 203, in get header = ElementTree.fromstring(response).find('{%s}Header' % soapns) File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xml/ etree/ElementTree.py", line 964, in XML return parser.close() File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xml/ etree/ElementTree.py", line 1254, in close self._parser.Parse("", 1) # end of data xml.parsers.expat.ExpatError: no element found: line 1, column 0
- Jared
On 7/22/10 9:49 PM, "Erik Cederstrand" erik@cederstrand.dk wrote:
Hi Jared,
Den 23/07/2010 kl. 09.22 skrev Jared Eckersley:
I was able to manually remove the python-ntlm library and reinstall and got it working again.
Great. Could you try my script again and see if it works for you?
createitem = Element('CreateItem')
[...]
attr = c.service.CreateItem(createitem)
CreateItem() takes as arguments the elements within createitem, i.e. 'saveditemfolderid' and 'items'. You shouldn't create the 'createitem' element. If you look at your XML, you have the CreateItem tag twice:
<ns1:CreateItem> <CreateItem MessageDisposition="SendAndSaveCopy"
xmlns="http://schemas.microsoft.com/exchange/services/2006/messages%22%3E
Your namespace usage is also funky. You need to clean that up if you get more 'Invalid request' messages.
Finally, you can't use the factory methods, since CreateItem expects the attribute MessageDisposition, and Suds doesn't support that without the patch in ticket #21. Generate the full XML instead (including headers) and inject it:
c.service.CreateItem(__inject={'msg':xml})
Thanks, Erik