Access Exchange Web Services with PHP and cURL
Hello,
I am currently writing a client to access a Microsoft Exchange server and read contacts, appointments etc. from it.
Through days of searching I've been able to connect to the EWS via PHP's Soap client and a custom HTTPS Stream wrapper. This website helped me greatly at this point.
Everything worked fine on my Windows 7 machine using XAMPP
Now I uploaded my project to a Debian 6.0 Squeeze development machine that has exactly the same configuration as my Windows machine regarding the web-server, php settings, mysql settings etc. but it just wont work anymore
The debian machine can resolve and ping the exchange server without problems
I nailed the actual problem down to a point, where cURL isn't able to retrieve the WSDL file of the EWS
It always receives an empty response and a 401 (Unauthorized) status code
The credentials I use are correct, the same credentials work on my windows machine
I extracted the faulty piece of code and tried running it stand-alone, it looks like this:
echo "Trying to get https://".$cfg[ 'Exchange.Server' ]."/EWS/Services.wsdl<br>";
$curl = curl_init( 'https://'.$cfg[ 'Exchange.Server' ].'/EWS/Services.wsdl' );
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1 );
curl_setopt( $curl, CURLOPT_HTTPAUTH, CURLAUTH_NTLM );
curl_setopt( $curl, CURLOPT_USERPWD, $cfg[ 'Exchange.User' ].':'.$cfg[ 'Exchange.Password' ] );
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, false );
echo '<pre>';
$response = curl_exec( $curl );
$info = curl_getinfo( $curl );
var_dump( $info );
var_dump( $response );
curl_close( $curl );
The result I receive here is the mentioned 401 status code and an empty response When I call the same url in my browser or with the same code on my windows machine, I get the WSDL file I want
Actually I can't even tell if this is a linux-based problem or if I do something wrong at some point, I'm struggling with this for 2 days now.
Is there someone that may be able to find my mistake or tell me the reason why it doesn't work?
I may provide any further needed i开发者_开发百科nformation on demand
If you initialize your soap client properly, you should be able to preform any requests requests this way:
$curl = curl_init($location); //'https://'.$server_address.'/EWS/Exchange.asmx'
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); //valid soap headers with keep-alive
curl_setopt($ch, CURLOPT_POST, true );
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_USERPWD, $user.':'.$password);
$response = curl_exec($curl);
As to your code, try commenting out following line:
curl_setopt( $curl, CURLOPT_HTTPAUTH, CURLAUTH_NTLM );
Also take a look wherever this wrapper works on your setup: http://ewswrapper.lafiel.net/ If it does, take a look at SOAP classes used there - it uses php built-in as base.
Why can't you store wsdl file locally anyways?
UPDATE:
Ok, I played around with this in my Debian box and this works for me flawlessly:
$domain = 'xxxxxx';
$user = 'xxxxxx';
$password = 'xxxxxx';
$ch = curl_init('https://'.$domain.'/EWS/Services.wsdl');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_USERPWD, $user.':'.$password);
$response = curl_exec($ch);
$info = curl_getinfo( $ch );
$error = curl_error ($ch);
print_r(array($response,$info,$error));
returns
Array
(
[0] => <?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions
(...)
</wsdl:definitions>
[1] => Array
(
[url] => xxxxx/EWS/Services.wsdl
[content_type] => text/xml
[http_code] => 200
[header_size] => 250
[request_size] => 147
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 0
[total_time] => 0.60574
[namelookup_time] => 0.165249
[connect_time] => 0.268173
[pretransfer_time] => 0.474009
[size_upload] => 0
[size_download] => 55607
[speed_download] => 91800
[speed_upload] => 0
[download_content_length] => 55607
[upload_content_length] => 0
[starttransfer_time] => 0.580931
[redirect_time] => 0
[certinfo] => Array
(
)
[redirect_url] =>
)
[2] =>
)
Your first check should not use any complex scripting. Instead try opening the WDSL from a simple browser window on the Debian machine like so: https://your.exchange-server.com/EWS/Services.wsdl
If that does not work there are probably access restrictions in place that depend on the client IP or client network (e.g. your development machine being in a trusted network, your Debian not). The fact that you get a 401 ("Unauthorized" - request requires user authentication) suggests that there is no problem with contacting the server but with authentication.
Another check I suggest is that you have a look into your phpinfo() to make sure your PHP installation on Debian is capable of handling HTTP*S* requests. Make sure, OpenSSL is installed!
This article helped point me in the right direction. One thing to keep in mind is that your PHP installation may not be sharing your system's cURL / libcurl setup.
http://blog.ianty.com/ubuntu/exchange-web-services-ews-ntlmv2-and-linux/
精彩评论