jamesiarmes / php-ews

PHP Exchange Web Services
http://jamesarmes.com/php-ews/
MIT License
566 stars 304 forks source link

How to access all shared calendar events? #524

Open Vectrex opened 6 years ago

Vectrex commented 6 years ago

Problem (which seems super-simple, but I haven't found any feasible solution, yet): The Outlook web frontend shows both own calendars and all shared calendars. When accessing this account with php-ews I see my previously generated own events, but not the shared ones.

The code uses the find.php example

$start_date = new DateTime('January 1 00:00:00');
$end_date = new DateTime('December 31 23:59:59');
$timezone = 'Eastern Standard Time';

$host = '...';
$username = '...';
$password = '...';
$version = Client::VERSION_2016;
$email = '...';
$client = new Client($host, $username, $password, $version);
$client->setCurlOptions(array(CURLOPT_SSL_VERIFYPEER => false));

/* impersonation files due to privilege restrictions */

//$ei = new ExchangeImpersonationType();
//$sid = new ConnectingSIDType();
//$sid->PrimarySmtpAddress = $email;
//$ei->ConnectingSID = $sid;
//$client->setImpersonation($ei);

$request = new FindItemType();
$request->ParentFolderIds = new NonEmptyArrayOfBaseFolderIdsType();

// Return all event properties.
$request->ItemShape = new ItemResponseShapeType();
$request->ItemShape->BaseShape = DefaultShapeNamesType::ALL_PROPERTIES;

$folder_id = new DistinguishedFolderIdType();
$folder_id->Id = DistinguishedFolderIdNameType::CALENDAR;

// just trying whether this changes anything - it doesn't
$folder_id->Mailbox = new EmailAddressType();
$folder_id->Mailbox->EmailAddress = $email;
//
$request->ParentFolderIds->DistinguishedFolderId[] = $folder_id;

$request->CalendarView = new CalendarViewType();
$request->CalendarView->StartDate = $start_date->format('c');
$request->CalendarView->EndDate = $end_date->format('c');

$response = $client->FindItem($request);

// Iterate over the results, printing any error messages or event ids.
$response_messages = $response->ResponseMessages->FindItemResponseMessage;

// [...]

Yields

Found event AQMkADZkNTUAMjVjNC00MDU5LTQwN2QtYjBkMC03ODYxMDNmNmNhZTQARgAAAwtxEv8929NPtEk0JknPNKwHAGjzGlPBx/xOkoTj5hA9j/kAAAIBDQAAAGjzGlPBx/xOkoTj5hA9j/kAAAIRBwAAAA==
  Change Key: DwAAABYAAABo8xpTwcf8TpKE4+YQPY/5AAAAABaG
  Title: EWS Test Event 2
  Start: Thursday, July 12th, 2018 11:00am
  End:   Thursday, July 12th, 2018 12:30pm

but no trace of any shared calendar events.

I suppose it must be simple - but so far I'm stuck.

phlisg commented 5 years ago

Did you find a solution since then?

I have a user who owns 4 calendars, but I don't find a way to list the events

phlisg commented 5 years ago

Using @jamesiarmes answer, I have a user who is the owner of the calendars I need, then I use their .local address to list their meetings, I just need to loop over their address in this fashion:

// I'm using a wrapping class around, so $this->client represents the user mentionned above
$client = $this->client;

// $this->meetingRooms is a simple array: ["room1@company.local", "room2@company.local"]
foreach($this->meetingRooms as $meetingRoom) {

    $folder_id = new DistinguishedFolderIdType();
    $folder_id->Id = DistinguishedFolderIdNameType::CALENDAR;

    $folder_id->Mailbox = new EmailAddressType();
    // refreshing the Mailbox for current room iteration
    $folder_id->Mailbox->EmailAddress = $meetingRoom; 

    $this->request->ParentFolderIds->DistinguishedFolderId[] = $folder_id;

    $response = $client->FindItem($this->request);
    $responses = $response->ResponseMessages->FindItemResponseMessage;

    // method that wraps the final return response we see in the examples (the foreach part).
    $this->print($responses);
}

And I get all the different meetings. Some few issues like some events being printed multiple times I need to investigate why.

Vectrex commented 5 years ago

I replaced James' library with Gareth's: https://github.com/Garethp/php-ews

There events and calendars are separate "things" and when retrieving events one doesn't need to know about calendars at all. (It took some time for me to figure out, that I don't retrieve calendars first and access the assigned events with these calendar items.) The code with garethp/php-ews looks like this:

$api = API::withUsernameAndPassword(
  $host,
  $username,
  $password
  [
      'primarySmtpEmailAddress' => $emailAddressCalendarsGetSharedWith,
   ]
);

$items = $api->getCalendarItems(
  (new \DateTime())->add(new \DateInterval('PT1S')),
  (new \DateTime())->add(new \DateInterval('P1D')),
  ['ParentFolderIds' => [
    'DistinguishedFolderId' => [
      'id' => 'calendar',
        'Mailbox' => [
          'EmailAddress' => $email
        ]
      ]
    ]]
  );
Commifreak commented 1 month ago

Since we moved on to shared mailboxes instead of public calendars, this also made me cry... We also use garethp php-ews and as of now the above code needs a bit of an adjustment. I go now with this:

$start = new \DateTime();
        $end   = clone $start;
        $end->modify('+1 month');

        $api = API::withUsernameAndPassword('owa.address', 'username', 'password', [
            'timezone' => 'W. Europe Standard Time',
            'version' => Enumeration\ExchangeVersionType::EXCHANGE_2013_SP1,
        ]);

        $request = new API\Message\FindItemType();
        $request->setParentFolderIds(new API\Type\NonEmptyArrayOfBaseFolderIdsType());

        // Return all event properties.
        $request->setItemShape(new API\Type\ItemResponseShapeType());
        $request->getItemShape()->setBaseShape(Enumeration\DefaultShapeNamesType::ALL_PROPERTIES);

        $folder_id = new API\Type\DistinguishedFolderIdType();
        $folder_id->setId(Enumeration\DistinguishedFolderIdNameType::CALENDAR);

        $folder_id->setMailbox(new API\Type\EmailAddressType());
        $folder_id->getMailbox()->setEmailAddress('shmb_mailbox@organization.tld');

        $request->getParentFolderIds()->setDistinguishedFolderId([$folder_id]);

        $request->setCalendarView(new API\Type\CalendarViewType());
        $request->getCalendarView()->setStartDate($start);
        $request->getCalendarView()->setEndDate($end);

        $response = $api->getClient()->FindItem($request);

        $items = $response;