开发者

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/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜