如何使用 PHP-EWS 连接到 Office365 服务器(获取 404)



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

我使用的是最新版本的 James Armas's PHP-EWS 工具。 Jamesiarmes/php-ews

这是我们用于获取特定日期范围的事件的函数中的代码片段。

$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): jamesiarmesPhpEwsClient->processResponse(NULL) #1 /*dirs*/Client.php(670): jamesiarmesPhpEwsClient->makeRequest('FindItem', Object(jamesiarmesPhpEwsRequestFindItemType)) #2 /*dirs*/index_dev.php(64): jamesiarmesPhpEwsClient->FindItem(Object(jamesiarmesPhpEwsRequestFindItemType)) #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"肥皂客户端返回状态为 404" 我也尝试了outlook.office365.com/EWS/Exchange.asmx端点,但我仍然得到 SOAP 404。

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

我也可能走上完全错误的轨道,所以任何帮助将不胜感激!

当我们从本地 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 中的 CURL 请求选项来解决此问题.php(位于第 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);

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

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

我无法弄清楚您的代码出了什么问题,但也许以下内容有所帮助。我已成功使用此脚本定期从 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
}
}

最新更新