diff --git a/lib/ext/Syncroton/Command/Sync.php b/lib/ext/Syncroton/Command/Sync.php --- a/lib/ext/Syncroton/Command/Sync.php +++ b/lib/ext/Syncroton/Command/Sync.php @@ -651,7 +651,7 @@ if(is_array($collectionData->syncState->pendingdata)) { $serverModifications = $collectionData->syncState->pendingdata; if ($this->_logger instanceof Zend_Log) { - $this->_logger->info(__METHOD__ . '::' . __LINE__ . " restored from sync state: (added/changed/deleted) " . count($serverModifications['added']) . '/' . count($serverModifications['changed']) . '/' . count($serverModifications['deleted']) . ' entries for sync from server to client'); + $this->_logger->info(__METHOD__ . '::' . __LINE__ . " restored from sync state: (added/changed/deleted) " . count($serverModifications['added']) . '/' . count($serverModifications['changed']) . '/' . count($serverModifications['deleted']) . ' entries for sync from server to client'); } } else { try { @@ -777,7 +777,7 @@ if ($this->_logger instanceof Zend_Log) { $this->_logger->info(__METHOD__ . '::' . __LINE__ . " Processing collection " . $collectionData->collectionId); } - + // send reponse for newly added entries if(!empty($clientModifications['added'])) { foreach($clientModifications['added'] as $entryData) { diff --git a/lib/kolab_sync_data_email.php b/lib/kolab_sync_data_email.php --- a/lib/kolab_sync_data_email.php +++ b/lib/kolab_sync_data_email.php @@ -393,7 +393,7 @@ $result['messageClass'] = 'IPM.Note.SMIME.MultipartSigned'; } elseif ($headers->ctype == 'application/pkcs7-mime' || $headers->ctype == 'application/x-pkcs7-mime') { $result['messageClass'] = 'IPM.Note.SMIME'; - } elseif ($event = $this->get_invitation_event_from_message($message)) { + } elseif ($event = $this->get_invitation_event_from_message($message, true)) { // Note: Depending on MessageClass a client will display a proper set of buttons // Either Accept/Maybe/Decline (REQUEST), or "Remove from Calendar" (CANCEL) or none (REPLY). $result['messageClass'] = 'IPM.Schedule.Meeting.Request'; @@ -1461,26 +1461,38 @@ /** * Returns calendar event data from the iTip invitation attached to a mail message */ - public function get_invitation_event_from_message($message) + public function get_invitation_event_from_message($message, $ignoreErrors = false) { - // Parse the message and find iTip attachments - $libcal = libcalendaring::get_instance(); - $libcal->mail_message_load(['object' => $message]); - $ical_objects = $libcal->get_mail_ical_objects(); - - // Skip methods we do not support here - if (!in_array($ical_objects->method, ['REQUEST', 'CANCEL', 'REPLY'])) { - return null; - } + try { + // Parse the message and find iTip attachments + $libcal = libcalendaring::get_instance(); + $libcal->mail_message_load(['object' => $message]); + $ical_objects = $libcal->get_mail_ical_objects(); + + // Skip methods we do not support here + if (!in_array($ical_objects->method, ['REQUEST', 'CANCEL', 'REPLY'])) { + return null; + } - // We support only one event in the iTip - foreach ($ical_objects as $mime_id => $event) { - if ($event['_type'] == 'event') { - $event['_method'] = $ical_objects->method; - $event['_mime_id'] = $ical_objects->mime_id; + // We support only one event in the iTip + foreach ($ical_objects as $mime_id => $event) { + if ($event['_type'] == 'event') { + $event['_method'] = $ical_objects->method; + $event['_mime_id'] = $ical_objects->mime_id; - return $event; + return $event; + } + } + } catch (\Exception $e) { + // To minimize occurrence of fatal errors while syncing, which would stop the whole process, + // we ignore any exceptions on parsing iTips. This allows the email message to be syncrotnized + // anyway, without stopping the sync process. We make it optional as there are cases which should throw. + if (!$ignoreErrors) { + throw $e; } + + $id = kolab_sync::get_instance()->get_user_name() . '/' . $message->folder . '/' . $message->uid; + rcube::raise_error("Failed to parse iTip message in {$id}. " . $e->getMessage(), true); } return null;