1
4

3 回答 3

3

当我们从本地 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 中的 CURL 请求选项(位于第 180 行附近),我能够解决该问题。

原始代码:

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);
于 2017-09-13T04:42:02.143 回答
2

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

主机和用户是这样的:

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
  }
}
于 2019-04-24T13:53:28.187 回答
2

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

$version = Client::VERSION_2016; 
$ews = new Client($server, $email, $password,$version);
于 2017-07-18T21:51:13.657 回答