【问题标题】:How to connect to an Office365 Server using PHP-EWS (Getting a 404)如何使用 PHP-EWS 连接到 Office365 服务器(获取 404)
【发布时间】:2017-12-23 20:43:49
【问题描述】:

我目前正在尝试更新一个内部工具,以处理将我们的 Exchange 服务器升级到 Office 365。

我正在使用最新版本的 James Armas 的 PHP-EWS 工具。 jamesiarmes/php-ews

这是我们用来获取特定日期范围内事件的函数内部的代码 sn-p。

$email = '*email@domain*';
$password = '*password*';
$server = 'outlook.office365.com';

// Define EWS
//$ews = EWSAutodiscover::getEWS($email, $password);

$ews = new Client($server, $email, $password);

// Set init class
$request = new FindItemType();
// Use this to search only the items in the parent directory in question or use ::SOFT_DELETED
// to identify "soft deleted" items, i.e. not visible and not in the trash can.
$request->Traversal = ItemQueryTraversalType::SHALLOW;
// This identifies the set of properties to return in an item or folder response
$request->ItemShape = new ItemResponseShapeType();
$request->ItemShape->BaseShape = DefaultShapeNamesType::ALL_PROPERTIES;

// Define the timeframe to load calendar items
$request->CalendarView = new CalendarViewType();
$request->CalendarView->StartDate = $start_date;// an ISO8601 date e.g. 2012-06-12T15:18:34+03:00
$request->CalendarView->EndDate = $end_date;// an ISO8601 date later than the above


// Only look in the "calendars folder"
$request->ParentFolderIds = new NonEmptyArrayOfBaseFolderIdsType();
$request->ParentFolderIds->DistinguishedFolderId = new DistinguishedFolderIdType();
$request->ParentFolderIds->DistinguishedFolderId->Id = DistinguishedFolderIdNameType::CALENDAR;
$request->ParentFolderIds->DistinguishedFolderId->Mailbox = new StdClass;
$request->ParentFolderIds->DistinguishedFolderId->Mailbox->EmailAddress = $email_address;

// Send request
$response = $ews->FindItem($request);

当这段代码运行时,我们从 SOAP 客户端得到一个 404:

Fatal error: Uncaught exception 'Exception' with message 'SOAP client returned status of 404.' in /*dirs*/Client.php:1650 Stack trace: #0 /*dirs*/Client.php(1633): jamesiarmes\PhpEws\Client->processResponse(NULL) #1 /*dirs*/Client.php(670): jamesiarmes\PhpEws\Client->makeRequest('FindItem', Object(jamesiarmes\PhpEws\Request\FindItemType)) #2 /*dirs*/index_dev.php(64): jamesiarmes\PhpEws\Client->FindItem(Object(jamesiarmes\PhpEws\Request\FindItemType)) #3 /*dirs*/index_dev.php(269): getEventHTML('email@domain...', '2017-07-18T02:0...', '2017-07-18T21:5...') #4 {main} thrown in /*dirs*/Client.php on line 1650

我相信我确实正确设置了连接,因为当我更改凭据时,我确实收到了 401。

我查看了这个页面:PHP-EWS “Soap client returned status of 404” 我也尝试了outlook.office365.com/EWS/Exchange.asmx 端点,但我仍然得到 SOAP 404。

因此,我认为这是一个单独的问题就足够了。 (虽然我研究得越多,REST客户端可能越是下一步)

我也可能走错了路,所以任何帮助都将不胜感激!

【问题讨论】:

    标签: php web-services soap exchangewebservices php-ews


    【解决方案1】:

    当我们从本地 Exchange 服务器迁移到 Office 365 并设法将问题追溯到 php-ntlm 下的 SoapClient.php 时,我遇到了类似的问题。

    从您的请求中引发的错误出发:

    Fatal error: Uncaught exception 'Exception' with message 'SOAP client returned status of 404.' .... thrown in /*dirs*/Client.php on line 1650
    

    如果我们查看 Client.php 中的那一行,异常似乎来自调用上述 SoapClient.php 脚本的函数。

    protected function processResponse($response)
    {
        // If the soap call failed then we need to throw an exception.
        $code = $this->soap->getResponseCode();
        if ($code != 200) {
            throw new \Exception(
                "SOAP client returned status of $code.",
                $code
            );
        }
    
        return $response;
    }
    

    我能够通过修改 SoapClient.php(位于第 180 行附近)中的 CURL 请求选项来解决该问题。

    原代码:

    protected function curlOptions($action, $request)
    {
        $options = $this->options['curlopts'] + array(
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => $this->buildHeaders($action),
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_HTTPAUTH => CURLAUTH_BASIC | CURLAUTH_NTLM,
            CURLOPT_USERPWD => $this->options['user'] . ':'
                               . $this->options['password'],
        );
        // We shouldn't allow these options to be overridden.
        $options[CURLOPT_HEADER] = true;
        $options[CURLOPT_POST] = true;
        $options[CURLOPT_POSTFIELDS] = $request;
        return $options;
    }
    

    修改代码:

    protected function curlOptions($action, $request)
    {
        $cOpts = array(
            CURLOPT_PROXY => "my.proxy.com:8080",
            CURLOPT_PROXYUSERPWD => $this->options['user'] . ':'
                               . $this->options['password'],
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => $this->buildHeaders($action),
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_HTTPAUTH => CURLAUTH_BASIC | CURLAUTH_NTLM,
            CURLOPT_USERPWD => $this->options['user'] . ':'
                               . $this->options['password'],
        );
        $options = $this->options['curlopts'] + $cOpts;
        // We shouldn't allow these options to be overridden.
        $options[CURLOPT_HEADER] = true;
        $options[CURLOPT_POST] = true;
        $options[CURLOPT_POSTFIELDS] = $request;
    
        return $options;
    }
    

    我将 CURLOPT_SSL_VERIFYPEER 设置为 false,并在请求中添加了代理选项,因为连接是从需要代理身份验证才能访问任何外部站点的公司网络内部进行的。

    在我的邮件 PHP 脚本中,我使用以下代码创建客户端:

    $server = 'outlook.office365.com';
    $username = 'user@domain.com';
    $password = 'myPassword';
    $version = Client::VERSION_2016;
    $client = new Client($server, $username, $password, $version);
    

    【讨论】:

      【解决方案2】:

      您是否尝试过使用https://github.com/jamesiarmes/php-ews/issues/196 的解决方案,例如更改

      $version = Client::VERSION_2016; 
      $ews = new Client($server, $email, $password,$version);
      

      【讨论】:

      • 不幸的是我有。无论 $version 变量是否存在,我仍然会遇到相同的错误。不过感谢您的帮助!
      • 在 Office365 上,您应该使用的身份验证是基本的,如果您有不同的 UPN 到电子邮件地址,那么您应该使用 UPN 作为用户名而不是电子邮件。您可以尝试使用 EWSEditor ewseditor.codeplex.com 进行一些测试,以验证要使用的正确详细信息
      【解决方案3】:

      我无法弄清楚您的代码有什么问题,但以下内容可能会有所帮助。我正在使用此脚本成功地从 o365 定期导出我的日历。

      Host 和 User 是这样的:

      host = "outlook.office365.com"
      username = "user@domain.com"
      

      脚本:

      $start_date = new Datetime('today -1 months');
      $end_date = new Datetime('today +1 months');
      
      $timezone = 'W. Europe Standard Time';
      
      $ini_array = parse_ini_file($credentials_ini);
      $host = $ini_array['host'];
      $username = $ini_array['username'];
      $password = $ini_array['password'];
      $version = Client::VERSION_2016;
      
      $client = new Client($host, $username, $password, $version);
      
      $client->setTimezone($timezone);
      
      $request = new FindItemType();
      $request->ParentFolderIds = new NonEmptyArrayOfBaseFolderIdsType();
      
      $request->ItemShape = new ItemResponseShapeType();
      $request->ItemShape->BaseShape = DefaultShapeNamesType::ALL_PROPERTIES;
      $folder_id = new DistinguishedFolderIdType();
      $folder_id->Id = DistinguishedFolderIdNameType::CALENDAR;
      $request->ParentFolderIds->DistinguishedFolderId[] = $folder_id;
      $request->Traversal = ItemQueryTraversalType::SHALLOW;
      $request->CalendarView = new CalendarViewType();
      $request->CalendarView->StartDate = $start_date->format('c');
      $request->CalendarView->EndDate = $end_date->format('c');
      $request->ConnectionTimeout = 60;
      
      $response = $client->FindItem($request);
      
      $response_messages = $response->ResponseMessages->FindItemResponseMessage;
      foreach ($response_messages as $response_message) {
        $items = $response_message->RootFolder->Items->CalendarItem;
      
        foreach ($items as $event){
          $id = $event->ItemId->Id;
          $subject = $event->Subject;
          $location = $event->Location;
          // ...
      
          // do something with it
        }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-27
        • 2020-11-20
        • 2013-07-22
        • 2018-01-25
        • 2020-07-13
        • 2014-04-06
        • 1970-01-01
        • 2018-10-27
        相关资源
        最近更新 更多