我目前正在尝试更新内部工具,以便将我们的Exchange服务器升级到Office 365。
我正在使用最新版本的James Armas的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): 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客户端下一步就越多)
我可能也处于完全错误的轨道上,所以任何帮助都将不胜感激!
答案 0 :(得分: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(位于第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);
答案 1 :(得分:2)
您是否尝试过使用https://github.com/jamesiarmes/php-ews/issues/196中的解决方案,例如更改
$version = Client::VERSION_2016;
$ews = new Client($server, $email, $password,$version);
答案 2 :(得分:1)
我无法确定您的代码出了什么问题,但以下内容可能会有所帮助。我正在成功使用此脚本从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
}
}