can't get the Talking SOAP With Exchange to work

Discussion in 'HOWTO-Related Questions' started by eescudier, Jan 27, 2009.

  1. jmclen

    jmclen New Member

    Workaround

    Hi,

    I thought I would post my temporary workaround. It seems to me that the problem is with the PHP5 soap client. It doesn't seem to handle inheritance too well, at least not in this case. The abstract class "path" is not supposed to be referenced directly, it is used in types.xsd to refer to whichever path you are using be it FieldURI, IndexedFieldURI or ExtendedFieldURI. Just for UpdateItem alone, I created an alternate types.xsd and change line 689 from path to FieldURI or IndexedFieldURI depending on which one I needed to use.

    This is obviously a hack that could cause problems down the road, but it allows me to finally update items for now. If anyone has more understanding about PHP5 soap and inheritance I would appreciate your thoughts or experiences.
     
  2. eoasis

    eoasis New Member

    No longer getting the Path error but still failing schema validation

    I formed this XML, but still have a schema error. It might be something simple, but it's not obvious to me. I haven't looked at your xsd work-around.


    // Updating Calendar Subjects
    $UpdateItem->ConflictResolution = "AutoResolve";
    $UpdateItem->MessageDisposition = "SaveOnly";
    $UpdateItem->ItemChanges->ItemChange->ItemId->Id = $itemids[1];
    $UpdateItem->ItemChanges->ItemChange->ItemId->ChangeKey = $changekey[1];

    $UpdateItem->ItemChanges->ItemChange->Updates->SetItemField->Path['FieldURI'] = "item:Subject";
    $UpdateItem->ItemChanges->ItemChange->Updates->SetItemField->Path['type'] = "PathToUnindexedFieldType";
    $UpdateItem->ItemChanges->ItemChange->Updates->SetItemField->CalendarItem->Subject = "Your New Subject";

    print_r($UpdateItem);
    $result = $client->UpdateItem($UpdateItem);


    Fatal error: Uncaught SoapFault exception: [Client] The request failed schema validation.
     
  3. syn1234

    syn1234 New Member

    After fighting with this solution: http://www.howtoforge.com/talking-soap-with-exchange

    and getting it to work ( it was a cURL lib problem ).

    I found all this patching of other classes/lib's etc hard to figure out when there is a problem. Otherwise its works great!

    anyways this is pure no extra classes or SOAP ( so the wsdl problems doesn't come into play at all ) you don't need to download any files.

    This code should drop a new message in your inbox. I have only tested on my server but I find this way its quicker to figure out what the problem is.

    The only down side is you have to generate your own XML, sometimes i find it easier ;)

    One point is have have to say that figuring out NTLM would have taken me a while but thanks to Manuel Lemos @ http://www.phpclasses.org/browse/package/1888.html i was able to use this NTLM class to do the hard work for me.

    Code:
    <?php
    define("SASL_NTLM_STATE_START",             0);
    define("SASL_NTLM_STATE_IDENTIFY_DOMAIN",   1);
    define("SASL_NTLM_STATE_RESPOND_CHALLENGE", 2);
    define("SASL_NTLM_STATE_DONE",              3);
    
    
    
    $NTLM = new ntlm_sasl_client_class;
    echo "<PRE>";
    
    $realm='<IP ADDRESS OF EXCHANGE>';
    $workstation='';
    $login='<LOGIN NAME>';
    $password='<PASSWORD>';
    $send_email_to = "[email protected]";
    
    $message=base64_encode(($NTLM->TypeMsg1($realm,$workstation)));
    
    # Get the 1st NTLM message from the server
    $fp = fsockopen("ssl://" . $realm, 443, $errno, $errstr, 30);
    $httpsend  = "GET /EWS/Exchange.asmx HTTP/1.1\r\n";
    $httpsend .= "Host: " . $realm . "\r\n";
    $httpsend .= "Connection: Keep-Alive\r\n";
    $httpsend .= "Accept: */*\r\n";
    $httpsend .= "User-Agent: PHP-SOAP-CURL\r\n";
    $httpsend .= "Authorization: NTLM " . $message . "\r\n\r\n";
    
    fwrite($fp, $httpsend);
    $data = "";
    while (strpos($data,"\r\n\r\n") == 0) { $data .= fgets($fp, 128); }
    
    
    
    # Get NTLM string
    $ntlm = trim(substr($data,strpos($data,"WWW-Authenticate: NTLM ")+22,strpos($data,"\r\n",strpos($data,"WWW-Authenticate: NTLM"))-strpos($data,"WWW-Authenticate: NTLM")-22    ));
    
    
    $ntlm_response=$NTLM->NTLMResponse(substr(base64_decode($ntlm),24,8),$password);
    $message=base64_encode($NTLM->TypeMsg3($ntlm_response,$login,$realm,$workstation));
    
    $xml = '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://schemas.microsoft.com/exchange/services/2006/types" xmlns:ns2="http://schemas.microsoft.com/exchange/services/2006/messages"><SOAP-ENV:Body>	<ns2:CreateItem MessageDisposition="SendOnly">		<ns2:SavedItemFolderId>			<ns1:DistinguishedFolderId Id="inbox"/>		</ns2:SavedItemFolderId><ns2:Items><ns1:Message><ns1:ItemClass>IPM.Note</ns1:ItemClass><ns1:Subject>YOUR SUBJECT</ns1:Subject><ns1:Body BodyType="Text">YOUR BODY TEXT</ns1:Body><ns1:ToRecipients><ns1:Mailbox><ns1:EmailAddress>' . $send_email_to . '</ns1:EmailAddress></ns1:Mailbox></ns1:ToRecipients><ns1:IsRead>true</ns1:IsRead></ns1:Message></ns2:Items></ns2:CreateItem></SOAP-ENV:Body></SOAP-ENV:Envelope>';
    $httpsend  = "POST /EWS/Exchange.asmx HTTP/1.1\r\n";
    $httpsend .= "Host: " . $realm . "\r\n";
    $httpsend .= "Connection: Keep-Alive\r\n";
    $httpsend .= "Accept: */*\r\n";
    $httpsend .= "User-Agent: PHP-SOAP-CURL\r\n";
    $httpsend .= "Content-Length: " . strlen($xml) . "\r\n";
    $httpsend .= "Content-Type: text/xml; charset=utf-8\r\n";
    $httpsend .= "Authorization: NTLM " . $message . "\r\n\r\n";
    $httpsend .= $xml;
    
    
    fwrite($fp, $httpsend);
    $data = "";
    while (strpos($data,"\r\n\r\n") == 0) { $data .= fgets($fp, 128); }
    
    echo $data;
    
    class ntlm_sasl_client_class
    /*
    Copyright (c) 2001-2005, Manuel Lemos
    All rights reserved.
    
    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are
    met:
    
        * Redistributions of source code must retain the above copyright
          notice, this list of conditions and the following disclaimer.
        * Redistributions in binary form must reproduce the above copyright
          notice, this list of conditions and the following disclaimer in the
          documentation and/or other materials provided with the distribution.
        * Neither the name of the Manuel Lemos nor the names of its
          contributors may be used to endorse or promote products derived from
          this software without specific prior written permission.
    
    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
    {
    	Function ASCIIToUnicode($ascii)
    	{
    		for($unicode="",$a=0;$a<strlen($ascii);$a++)
    			$unicode.=substr($ascii,$a,1).chr(0);
    		return($unicode);
    	}
    	Function TypeMsg1($domain,$workstation)
    	{
    		$domain_length=strlen($domain);
    		$workstation_length=strlen($workstation);
    		$workstation_offset=32;
    		$domain_offset=$workstation_offset+$workstation_length;
    		return(
    			"NTLMSSP\0".
    			"\x01\x00\x00\x00".
    			"\x07\x32\x00\x00".
    			pack("v",$domain_length).
    			pack("v",$domain_length).
    			pack("V",$domain_offset).
    			pack("v",$workstation_length).
    			pack("v",$workstation_length).
    			pack("V",$workstation_offset).
    			$workstation.
    			$domain
    		);
    	}
    	Function NTLMResponse($challenge,$password)
    	{
    		$unicode=$this->ASCIIToUnicode($password);
    		$md4=mhash(MHASH_MD4,$unicode);
    		$padded=$md4.str_repeat(chr(0),21-strlen($md4));
    		$iv_size=mcrypt_get_iv_size(MCRYPT_DES,MCRYPT_MODE_ECB);
    		$iv=mcrypt_create_iv($iv_size,MCRYPT_RAND);
    		for($response="",$third=0;$third<21;$third+=7)
    		{
    			for($packed="",$p=$third;$p<$third+7;$p++)
    				$packed.=str_pad(decbin(ord(substr($padded,$p,1))),8,"0",STR_PAD_LEFT);
    			for($key="",$p=0;$p<strlen($packed);$p+=7)
    			{
    				$s=substr($packed,$p,7);
    				$b=$s.((substr_count($s,"1") % 2) ? "0" : "1");
    				$key.=chr(bindec($b));
    			}
    			$ciphertext=mcrypt_encrypt(MCRYPT_DES,$key,$challenge,MCRYPT_MODE_ECB,$iv);
    			$response.=$ciphertext;
    		}	
    		return $response;
    	}
    
    	Function TypeMsg3($ntlm_response,$user,$domain,$workstation)
    	{
    		$domain_unicode=$this->ASCIIToUnicode($domain);
    		$domain_length=strlen($domain_unicode);
    		$domain_offset=64;
    		$user_unicode=$this->ASCIIToUnicode($user);
    		$user_length=strlen($user_unicode);
    		$user_offset=$domain_offset+$domain_length;
    		$workstation_unicode=$this->ASCIIToUnicode($workstation);
    		$workstation_length=strlen($workstation_unicode);
    		$workstation_offset=$user_offset+$user_length;
    		$lm="";
    		$lm_length=strlen($lm);
    		$lm_offset=$workstation_offset+$workstation_length;
    		$ntlm=$ntlm_response;
    		$ntlm_length=strlen($ntlm);
    		$ntlm_offset=$lm_offset+$lm_length;
    		$session="";
    		$session_length=strlen($session);
    		$session_offset=$ntlm_offset+$ntlm_length;
    		return(
    			"NTLMSSP\0".
    			"\x03\x00\x00\x00".
    			pack("v",$lm_length).
    			pack("v",$lm_length).
    			pack("V",$lm_offset).
    			pack("v",$ntlm_length).
    			pack("v",$ntlm_length).
    			pack("V",$ntlm_offset).
    			pack("v",$domain_length).
    			pack("v",$domain_length).
    			pack("V",$domain_offset).
    			pack("v",$user_length).
    			pack("v",$user_length).
    			pack("V",$user_offset).
    			pack("v",$workstation_length).
    			pack("v",$workstation_length).
    			pack("V",$workstation_offset).
    			pack("v",$session_length).
    			pack("v",$session_length).
    			pack("V",$session_offset).
    			"\x01\x02\x00\x00".
    			$domain_unicode.
    			$user_unicode.
    			$workstation_unicode.
    			$lm.
    			$ntlm
    		);
    	}
    
    };
    
    ?>
    
    
    
     
    Last edited: Apr 22, 2009
  4. eboosted

    eboosted New Member

    My Changes

    Hopefully this will help someone...

    I use Intermedia Managed Exchange. I was Having trouble with the WSDL File caching all the time. Add this line to your code to disable WSDL Caching -

    ini_set("soap.wsdl_cache_enabled", "0");

    In the WSDL file I removed the last line - "</wsdl:definitions>" and then pasted Eric's code as per his great tutorial -
    "<wsdl:service name="ExchangeServices">
    <wsdl:port name="ExchangeServicePort" binding="tns:ExchangeServiceBinding">
    <soap:address location="https://exchange.example.com/EWS/Exchange.asmx"/>
    </wsdl:port>
    </wsdl:service>
    </wsdl:definitions>"

    Dont forget to change the SOAP:ADDRESS LOCATION to https://<yourexchangeOWAdomain>/EWS/Exchange.asmx
     
  5. avallach

    avallach New Member

    Any Update on UpdateItem

    Greetings,

    I've tried a whole bunch of things wrt UpdateItem, but no success like I see here.

    jmclen what did you change the types.xsd file line 689 to? I've tried a few variations and can not make it work.

    Thanks!

    UPDATE: jmclen's solution worked for me, I had something caching which was throwing me off, just replacing the t:path with t:FieldURI is what I needed.
     
    Last edited: Jun 10, 2009
  6. stalin

    stalin New Member

    Not able to Fetch emails

    Hello ,

    I am a newbie to this forum, first i would like to thank for great artical on How to talk to Exchange using SOAP.

    Here i am able to send emails using Exchange web service. but my requirment is to fetch emails from particular user and display from address, Body and subject line.

    When i tried to filter get folder details it throws following error;

    error is on the line marked with bold and blue color.

    This is very urgent as i am working towards a dedline for a customer. any help would be appriciated.

    Thanks for your help in advance. :)
    This is my code.


    $FindFolder->Traversal = 'Shallow';
    $FindFolder->FolderShape->BaseShape = 'AllProperties';
    $FindFolder->Traversal->ParentFolderIds->DistinguishedFolderId->Id = 'root';

    $result = $client->FindFolder($FindFolder);
    $folders = $result->ResponseMessages->FindFolderResponseMessage->RootFolder->Folders->Folder;
    foreach ($folders as $folder)
    {
    if ('Top of Information Store' == $folder->DisplayName)
    {
    $tois_folder = $folder;
    }
    }


    Fatal error: Uncaught SoapFault exception: [soap11:Client] The request failed schema validation: The element 'FindFolder' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages' has incomplete content. List of possible elements expected: 'IndexedPageFolderView, FractionalPageFolderView, Restriction, ParentFolderIds' in namespace 'http://schemas.microsoft.com/exchange/services/2006/messages'. in C:\opensource_project_zone\ews\index.php:154 Stack trace: #0 [internal function]: SoapClient->__call('FindFolder', Array) #1 C:\opensource_project_zone\ews\index.php(154): ExchangeNTLMSoapClient->FindFolder(Object(stdClass)) #2 {main} thrown in C:\opensource_project_zone\ews\index.php on line 154
     
  7. redwerner

    redwerner New Member

    Hello,

    first, sorry for my bad english :rolleyes:

    the second.

    thanks für the great class to connect exchange2007 with php. it works great, but....

    .... how can i list the inbox of my mailbox.

    a list of the calendar
    PHP:
    $FindItem->Traversal "Shallow";
    $FindItem->ItemShape->BaseShape "AllProperties";
    $FindItem->ParentFolderIds->DistinguishedFolderId->Id "calendar";
    $FindItem->CalendarView->StartDate     $s_start;
    $FindItem->CalendarView->EndDate     $s_ende;
    $result $client->FindItem($FindItem);
    $calendaritems $result->ResponseMessages->FindItemResponseMessage->RootFolder->Items->CalendarItem;
    if(
    $debug) { print_r($calendaritems); }

    foreach(
    $calendaritems as $item) {

    echo 
    $item->Subject

    }
    can anyone tell me the code for the list of inbox?

    best regards

    Werner
     
  8. marv

    marv New Member

    Hi,

    sorry for pulling out this old thread, but I have a problem with passing the body attributes for CreateItem: I have successfully made a connection to the Exchange-server and was able to create an appointment (with the code from the tutorial). But there is the problem: I wrote a simple test script for this and after the test I put this into a class. In the testscript everything was fine and working, but in the class where I added a addAppointment()-function, I'm getting an error at this line:
    PHP:
    $CreateItem->Items->CalendarItem[0]->Body[_] = $text;
    Error: Use of undefined constant _ - assumed '_'.
    This is the function:
    PHP:
    public function addAppointment$path$title$text$start$end,
        
    $allday false$busystatus 'Free'$location ''$category '' )
      {
        
    // get ids for directory
        
    $ids $this->getFolderIDsByPath($path);// <simple function for getting id/changekey for given path, not interesting here

        
    if ( $ids )
        {
          
          
    $CreateItem->SavedItemFolderId->FolderId->Id $ids['Id'];
          
    $CreateItem->SavedItemFolderId->FolderId->ChangeKey $ids['ChangeKey'];
          
    $CreateItem->Items->CalendarItem = array();
          
    $CreateItem->SendMeetingInvitations "SendToNone";

          
    $CreateItem->Items->CalendarItem[0]->Subject $title;
          
    $CreateItem->Items->CalendarItem[0]->Start $start# ISO date format. Z denotes UTC time
          
    $CreateItem->Items->CalendarItem[0]->End $end;
          
    $CreateItem->Items->CalendarItem[0]->Body[_] = $text// < error here
          
    $CreateItem->Items->CalendarItem[0]->Body['BodyType']="Text";
          
    $CreateItem->Items->CalendarItem[0]->IsAllDayEvent $allday;
          
    $CreateItem->Items->CalendarItem[0]->LegacyFreeBusyStatus $busystatus;
          
    $CreateItem->Items->CalendarItem[0]->Location $location;
          
    $CreateItem->Items->CalendarItem[0]->Categories->String $category;
          
    $result $this->client->CreateItem($CreateItem); // < $this->client holds SOAP-client object
          
    print_r($result);
          if ( 
    $result->ResponseMessages->CreateItemResponseMessage->ResponseClass == 'Success' )
          {
            
    // return id/changekey for saving somewhere to be able to edit the appointment
            
    return array(
              
    'Id' =>  $result->ResponseMessages->CreateItemResponseMessage->Items->CalendarItem->ItemId->Id,
              
    'ChangeKey' => $result->ResponseMessages->CreateItemResponseMessage->Items->CalendarItem->ItemId->ChangeKey,
            );
          }
          return 
    null;
        }
      }
    Can somebody tell me whats wrong? Why is this working in the one script and not in the other? Both are on the same server (Ubuntu 9.04, Apache 2.2.11, PHP 5.2.6). How can I get this working? I'm looking at this all the day but I couldn't figure it out.

    Thank you in advance for your help!

    EDIT:
    OK, found something: if I change
    PHP:
    $CreateItem->Items->CalendarItem[0]->Body[_] = $text;
    to
    PHP:
    $CreateItem->Items->CalendarItem[0]->Body[] = $text;
    it works and the appointment appears in the calendar, but the body is not saved :(.

    best regards

    marv
    hope my english is not to bad :)
     
    Last edited: Apr 27, 2010
  9. feuxx

    feuxx New Member

    Hi,

    I come to you because I have a big problem that is urgent, for one of my projects at work.

    I'm stuck and it becomes very urgent, I seek a way to list all the emails in my inbox from an Exchange server and read the emails and their headers ,....

    I use the EWS Class an LDAP connection with the exchange server, I can send emails, sort and add events to the calendar and enter in the inbox (I have the number of mail and the total number of mail unread)

    Could you please help me

    Thank you in advance
     
  10. DrZboczek

    DrZboczek New Member

    Thanks for that topic, I find it very interesting.
     

Share This Page