示例#1
0
 /**
  * Variables required in form input:
  *   - identity (TODO: ? Code uses it, but it is never set anywhere)
  *   - imple_submit: itip_action(s)
  *   - mime_id
  *   - muid
  *
  * @return boolean  True on success.
  */
 protected function _handle(Horde_Variables $vars)
 {
     global $injector, $notification, $registry;
     $actions = (array) $vars->imple_submit;
     $result = false;
     $vCal = new Horde_Icalendar();
     /* Retrieve the calendar data from the message. */
     try {
         $contents = $injector->getInstance('IMP_Factory_Contents')->create(new IMP_Indices_Mailbox($vars));
         $mime_part = $contents->getMIMEPart($vars->mime_id);
         if (empty($mime_part)) {
             throw new IMP_Exception(_("Cannot retrieve calendar data from message."));
         } elseif (!$vCal->parsevCalendar($mime_part->getContents(), 'VCALENDAR', $mime_part->getCharset())) {
             throw new IMP_Exception(_("The calendar data is invalid"));
         }
         $components = $vCal->getComponents();
     } catch (Exception $e) {
         $notification->push($e, 'horde.error');
         $actions = array();
     }
     foreach ($actions as $key => $action) {
         $pos = strpos($key, '[');
         $key = substr($key, $pos + 1, strlen($key) - $pos - 2);
         switch ($action) {
             case 'delete':
                 // vEvent cancellation.
                 if ($registry->hasMethod('calendar/delete')) {
                     $guid = $components[$key]->getAttribute('UID');
                     $recurrenceId = null;
                     try {
                         // This is a cancellation of a recurring event instance.
                         $recurrenceId = $components[$key]->getAttribute('RECURRENCE-ID');
                         $atts = $components[$key]->getAttribute('RECURRENCE-ID', true);
                         $range = null;
                         foreach ($atts as $att) {
                             if (array_key_exists('RANGE', $att)) {
                                 $range = $att['RANGE'];
                             }
                         }
                     } catch (Horde_Icalendar_Exception $e) {
                     }
                     try {
                         $registry->call('calendar/delete', array($guid, $recurrenceId, $range));
                         $notification->push(_("Event successfully deleted."), 'horde.success');
                         $result = true;
                     } catch (Horde_Exception $e) {
                         $notification->push(sprintf(_("There was an error deleting the event: %s"), $e->getMessage()), 'horde.error');
                     }
                 } else {
                     $notification->push(_("This action is not supported."), 'horde.warning');
                 }
                 break;
             case 'update':
                 // vEvent reply.
                 if ($registry->hasMethod('calendar/updateAttendee')) {
                     try {
                         $from = $contents->getHeader()->getOb('from');
                         $registry->call('calendar/updateAttendee', array($components[$key], $from[0]->bare_address));
                         $notification->push(_("Respondent Status Updated."), 'horde.success');
                         $result = true;
                     } catch (Horde_Exception $e) {
                         $notification->push(sprintf(_("There was an error updating the event: %s"), $e->getMessage()), 'horde.error');
                     }
                 } else {
                     $notification->push(_("This action is not supported."), 'horde.warning');
                 }
                 break;
             case 'import':
             case 'accept-import':
                 // vFreebusy reply.
                 // vFreebusy publish.
                 // vEvent request.
                 // vEvent publish.
                 // vTodo publish.
                 // vJournal publish.
                 switch ($components[$key]->getType()) {
                     case 'vEvent':
                         $result = $this->_handlevEvent($key, $components, $mime_part);
                         // Must check for exceptions.
                         foreach ($components as $k => $component) {
                             try {
                                 if ($component->getType() == 'vEvent' && $component->getAttribute('RECURRENCE-ID')) {
                                     $uid = $component->getAttribute('UID');
                                     if ($uid == $components[$key]->getAttribute('UID')) {
                                         $this->_handlevEvent($k, $components, $mime_part);
                                     }
                                 }
                             } catch (Horde_Icalendar_Exception $e) {
                             }
                         }
                         break;
                     case 'vFreebusy':
                         // Import into Kronolith.
                         if ($registry->hasMethod('calendar/import_vfreebusy')) {
                             try {
                                 $registry->call('calendar/import_vfreebusy', array($components[$key]));
                                 $notification->push(_("The user's free/busy information was sucessfully stored."), 'horde.success');
                                 $result = true;
                             } catch (Horde_Exception $e) {
                                 $notification->push(sprintf(_("There was an error importing user's free/busy information: %s"), $e->getMessage()), 'horde.error');
                             }
                         } else {
                             $notification->push(_("This action is not supported."), 'horde.warning');
                         }
                         break;
                     case 'vTodo':
                         // Import into Nag.
                         if ($registry->hasMethod('tasks/import')) {
                             try {
                                 $guid = $registry->call('tasks/import', array($components[$key], $mime_part->getType()));
                                 $url = Horde::url($registry->link('tasks/show', array('uid' => $guid)));
                                 $notification->push(_("The task has been added to your tasklist.") . '&nbsp;' . Horde::link($url, _("View task"), null, '_blank') . Horde_Themes_Image::tag('mime/icalendar.png', array('alt' => _("View task"))) . '</a>', 'horde.success', array('content.raw'));
                                 $result = true;
                             } catch (Horde_Exception $e) {
                                 $notification->push(sprintf(_("There was an error importing the task: %s"), $e->getMessage()), 'horde.error');
                             }
                         } else {
                             $notification->push(_("This action is not supported."), 'horde.warning');
                         }
                         break;
                     case 'vJournal':
                     default:
                         $notification->push(_("This action is not supported."), 'horde.warning');
                 }
                 if ($action == 'import') {
                     break;
                 }
                 // Fall-through for 'accept-import'
             // Fall-through for 'accept-import'
             case 'accept':
             case 'deny':
             case 'tentative':
                 // vEvent request.
                 if (isset($components[$key]) && $components[$key]->getType() == 'vEvent') {
                     $vEvent = $components[$key];
                     $resource = new Horde_Itip_Resource_Identity($injector->getInstance('IMP_Identity'), $vEvent->getAttribute('ATTENDEE'), $vars->identity);
                     switch ($action) {
                         case 'accept':
                         case 'accept-import':
                             $type = new Horde_Itip_Response_Type_Accept($resource);
                             break;
                         case 'deny':
                             $type = new Horde_Itip_Response_Type_Decline($resource);
                             break;
                         case 'tentative':
                             $type = new Horde_Itip_Response_Type_Tentative($resource);
                             break;
                     }
                     try {
                         // Send the reply.
                         Horde_Itip::factory($vEvent, $resource)->sendMultiPartResponse($type, new Horde_Core_Itip_Response_Options_Horde('UTF-8', array()), $injector->getInstance('IMP_Mail'));
                         $notification->push(_("Reply Sent."), 'horde.success');
                         $result = true;
                     } catch (Horde_Itip_Exception $e) {
                         $notification->push(sprintf(_("Error sending reply: %s."), $e->getMessage()), 'horde.error');
                     }
                 } else {
                     $notification->push(_("This action is not supported."), 'horde.warning');
                 }
                 break;
             case 'send':
             case 'reply':
             case 'reply2m':
                 // vfreebusy request.
                 if (isset($components[$key]) && $components[$key]->getType() == 'vFreebusy') {
                     $vFb = $components[$key];
                     // Get the organizer details.
                     try {
                         $organizer = parse_url($vFb->getAttribute('ORGANIZER'));
                     } catch (Horde_Icalendar_Exception $e) {
                         break;
                     }
                     $organizerEmail = $organizer['path'];
                     $organizer = $vFb->getAttribute('ORGANIZER', true);
                     $organizerFullEmail = new Horde_Mail_Rfc822_Address($organizerEmail);
                     if (isset($organizer['cn'])) {
                         $organizerFullEmail->personal = $organizer['cn'];
                     }
                     if ($action == 'reply2m') {
                         $startStamp = time();
                         $endStamp = $startStamp + 60 * 24 * 3600;
                     } else {
                         try {
                             $startStamp = $vFb->getAttribute('DTSTART');
                         } catch (Horde_Icalendar_Exception $e) {
                             $startStamp = time();
                         }
                         try {
                             $endStamp = $vFb->getAttribute('DTEND');
                         } catch (Horde_Icalendar_Exception $e) {
                         }
                         if (!$endStamp) {
                             try {
                                 $duration = $vFb->getAttribute('DURATION');
                                 $endStamp = $startStamp + $duration;
                             } catch (Horde_Icalendar_Exception $e) {
                                 $endStamp = $startStamp + 60 * 24 * 3600;
                             }
                         }
                     }
                     $vfb_reply = $registry->call('calendar/getFreeBusy', array($startStamp, $endStamp));
                     // Find out who we are and update status.
                     $identity = $injector->getInstance('IMP_Identity');
                     $email = $identity->getFromAddress();
                     // Build the reply.
                     $msg_headers = new Horde_Mime_Headers();
                     $vCal = new Horde_Icalendar();
                     $vCal->setAttribute('PRODID', '-//The Horde Project//' . $msg_headers->getUserAgent() . '//EN');
                     $vCal->setAttribute('METHOD', 'REPLY');
                     $vCal->addComponent($vfb_reply);
                     $message = _("Attached is a reply to a calendar request you sent.");
                     $body = new Horde_Mime_Part();
                     $body->setType('text/plain');
                     $body->setCharset('UTF-8');
                     $body->setContents(Horde_String::wrap($message, 76));
                     $ics = new Horde_Mime_Part();
                     $ics->setType('text/calendar');
                     $ics->setCharset('UTF-8');
                     $ics->setContents($vCal->exportvCalendar());
                     $ics->setName('icalendar.ics');
                     $ics->setContentTypeParameter('METHOD', 'REPLY');
                     $mime = new Horde_Mime_Part();
                     $mime->addPart($body);
                     $mime->addPart($ics);
                     // Build the reply headers.
                     $msg_headers->addReceivedHeader(array('dns' => $injector->getInstance('Net_DNS2_Resolver'), 'server' => $conf['server']['name']));
                     $msg_headers->addMessageIdHeader();
                     $msg_headers->addHeader('Date', date('r'));
                     $msg_headers->addHeader('From', $email);
                     $msg_headers->addHeader('To', $organizerFullEmail);
                     $identity->setDefault($vars->identity);
                     $replyto = $identity->getValue('replyto_addr');
                     if (!empty($replyto) && !$email->match($replyto)) {
                         $msg_headers->addHeader('Reply-To', $replyto);
                     }
                     $msg_headers->addHeader('Subject', _("Free/Busy Request Response"));
                     // Send the reply.
                     try {
                         $mime->send($organizerEmail, $msg_headers, $injector->getInstance('IMP_Mail'));
                         $notification->push(_("Reply Sent."), 'horde.success');
                         $result = true;
                     } catch (Exception $e) {
                         $notification->push(sprintf(_("Error sending reply: %s."), $e->getMessage()), 'horde.error');
                     }
                 } else {
                     $notification->push(_("Invalid Action selected for this component."), 'horde.warning');
                 }
                 break;
             case 'nosup':
                 // vFreebusy request.
             // vFreebusy request.
             default:
                 $notification->push(_("This action is not supported."), 'horde.warning');
                 break;
         }
     }
     return $result;
 }
示例#2
0
 private function _getItip($invitation = null)
 {
     if ($invitation === null) {
         $invitation = $this->_getInvitation();
     }
     return Horde_Itip::factory($invitation, $this->_getResource());
 }
示例#3
0
文件: Kronolith.php 项目: horde/horde
 /**
  * Sends out iTip event notifications to all attendees of a specific
  * event.
  *
  * Can be used to send event invitations, event updates as well as event
  * cancellations.
  *
  * @param Kronolith_Event $event
  *        The event in question.
  * @param Horde_Notification_Handler $notification
  *        A notification object used to show result status.
  * @param integer $action
  *        The type of notification to send. One of the Kronolith::ITIP_*
  *        values.
  * @param Horde_Date $instance
  *        If cancelling a single instance of a recurring event, the date of
  *        this instance.
  * @param  string $range  The range parameter if this is a recurring event.
  *                        Possible values are self::RANGE_THISANDFUTURE
  * @param Kronolith_Attendee_List $cancellations  If $action is 'CANCEL',
  *                                                but it is due to removing
  *                                                attendees and not
  *                                                canceling the entire
  *                                                event, these are the
  *                                                uninvited attendees and
  *                                                are the ONLY people that
  *                                                will receive the CANCEL
  *                                                iTIP.  @since 4.2.10
  */
 public static function sendITipNotifications(Kronolith_Event $event, Horde_Notification_Handler $notification, $action, Horde_Date $instance = null, $range = null, Kronolith_Attendee_List $cancellations = null)
 {
     global $injector, $prefs, $registry;
     if (!count($event->attendees) || $prefs->getValue('itip_silent')) {
         return;
     }
     $ident = $injector->getInstance('Horde_Core_Factory_Identity')->create($event->creator);
     if (!$ident->getValue('from_addr')) {
         $notification->push(sprintf(_("You do not have an email address configured in your Personal Information Preferences. You must set one %shere%s before event notifications can be sent."), $registry->getServiceLink('prefs', 'kronolith')->add(array('app' => 'horde', 'group' => 'identities'))->link(), '</a>'), 'horde.error', array('content.raw'));
         return;
     }
     // Generate image mime part first and only once, because we
     // need the Content-ID.
     $image = self::getImagePart('big_invitation.png');
     $share = $injector->getInstance('Kronolith_Shares')->getShare($event->calendar);
     $view = new Horde_View(array('templatePath' => KRONOLITH_TEMPLATES . '/itip'));
     new Horde_View_Helper_Text($view);
     $view->identity = $ident;
     $view->event = $event;
     $view->imageId = $image->getContentId();
     if ($action == self::ITIP_CANCEL && count($cancellations)) {
         $mail_attendees = $cancellations;
     } elseif ($event->organizer && !self::isUserEmail($event->creator, $event->organizer)) {
         /* Only send updates to organizer if the user is not the
          * organizer */
         if (isset($event->attendees['email:' . $event->organizer])) {
             $organizer = $event->attendees['email:' . $event->organizer];
         } else {
             $organizer = new Kronolith_Attendee(array('email' => $event->organizer));
         }
         $mail_attendees = new Kronolith_Attendee_List(array($organizer));
     } else {
         $mail_attendees = $event->attendees;
     }
     foreach ($mail_attendees as $attendee) {
         /* Don't send notifications to the ORGANIZER if this is the
          * ORGANIZER's copy of the event. */
         if (!$event->organizer && Kronolith::isUserEmail($event->creator, $attendee->email)) {
             continue;
         }
         /* Don't bother sending an invitation/update if the recipient does
          * not need to participate, or has declined participating, or
          * doesn't have an email address. */
         if (strpos($attendee->email, '@') === false || $attendee->response == self::RESPONSE_DECLINED) {
             continue;
         }
         /* Determine all notification-specific strings. */
         switch ($action) {
             case self::ITIP_CANCEL:
                 /* Cancellation. */
                 $method = 'CANCEL';
                 $filename = 'event-cancellation.ics';
                 $view->subject = sprintf(_("Cancelled: %s"), $event->getTitle());
                 if (empty($instance)) {
                     $view->header = sprintf(_("%s has cancelled \"%s\"."), $ident->getName(), $event->getTitle());
                 } else {
                     $view->header = sprintf(_("%s has cancelled an instance of the recurring \"%s\"."), $ident->getName(), $event->getTitle());
                 }
                 break;
             case self::ITIP_REPLY:
                 $filename = 'event-reply.ics';
                 $events = $event->toiCalendar(new Horde_Icalendar());
                 $vEvent = array_shift($events);
                 $itipIdentity = new Horde_Itip_Resource_Identity($ident, $vEvent->getAttribute('ATTENDEE'), (string) $ident->getFromAddress());
                 /* Find which of the creator's mail addresses is used here */
                 foreach ($event->attendees as $attendee) {
                     if (self::isUserEmail($event->creator, $attendee->email)) {
                         switch ($attendee->response) {
                             case self::RESPONSE_ACCEPTED:
                                 $type = new Horde_Itip_Response_Type_Accept($itipIdentity);
                                 break;
                             case self::RESPONSE_DECLINED:
                                 $type = new Horde_Itip_Response_Type_Decline($itipIdentity);
                                 break;
                             case self::RESPONSE_TENTATIVE:
                                 $type = new Horde_Itip_Response_Type_Tentative($itipIdentity);
                                 break;
                             default:
                                 return;
                         }
                         try {
                             // Send the reply.
                             Horde_Itip::factory($vEvent, $itipIdentity)->sendMultiPartResponse($type, new Horde_Core_Itip_Response_Options_Horde('UTF-8', array()), $injector->getInstance('Horde_Mail'));
                         } catch (Horde_Itip_Exception $e) {
                             $notification->push(sprintf(_("Error sending reply: %s."), $e->getMessage()), 'horde.error');
                         }
                     }
                 }
                 return;
             case self::ITIP_REQUEST:
             default:
                 $method = 'REQUEST';
                 if ($attendee->response == self::RESPONSE_NONE) {
                     /* Invitation. */
                     $filename = 'event-invitation.ics';
                     $view->subject = $event->getTitle();
                     $view->header = sprintf(_("%s wishes to make you aware of \"%s\"."), $ident->getName(), $event->getTitle());
                 } else {
                     /* Update. */
                     $filename = 'event-update.ics';
                     $view->subject = sprintf(_("Updated: %s."), $event->getTitle());
                     $view->header = sprintf(_("%s wants to notify you about changes of \"%s\"."), $ident->getName(), $event->getTitle());
                 }
                 break;
         }
         $view->organizer = $registry->convertUserName($event->creator, false);
         if ($action == self::ITIP_REQUEST) {
             $attend_link = Horde::url('attend.php', true, -1)->add(array('c' => $event->calendar, 'e' => $event->id, 'u' => $attendee->email));
             $view->linkAccept = (string) $attend_link->add('a', 'accept');
             $view->linkTentative = (string) $attend_link->add('a', 'tentative');
             $view->linkDecline = (string) $attend_link->add('a', 'decline');
         }
         /* Build the iCalendar data */
         $iCal = new Horde_Icalendar();
         $iCal->setAttribute('METHOD', $method);
         $iCal->setAttribute('X-WR-CALNAME', $share->get('name'));
         $vevent = $event->toiCalendar($iCal);
         if ($action == self::ITIP_CANCEL && !empty($instance)) {
             // Recurring event instance deletion, need to specify the
             // RECURRENCE-ID but NOT the EXDATE.
             foreach ($vevent as &$ve) {
                 try {
                     $uid = $ve->getAttribute('UID');
                 } catch (Horde_Icalendar_Exception $e) {
                     continue;
                 }
                 if ($event->uid == $uid) {
                     $ve->setAttribute('RECURRENCE-ID', $instance);
                     if (!empty($range)) {
                         $ve->setParameter('RECURRENCE-ID', array('RANGE' => $range));
                     }
                     $ve->setAttribute('DTSTART', $instance, array(), false);
                     $diff = $event->end->timestamp() - $event->start->timestamp();
                     $end = clone $instance;
                     $end->sec += $diff;
                     $ve->setAttribute('DTEND', $end, array(), false);
                     $ve->removeAttribute('EXDATE');
                     break;
                 }
             }
         }
         $iCal->addComponent($vevent);
         /* text/calendar part */
         $ics = new Horde_Mime_Part();
         $ics->setType('text/calendar');
         $ics->setContents($iCal->exportvCalendar());
         $ics->setName($filename);
         $ics->setContentTypeParameter('method', $method);
         $ics->setCharset('UTF-8');
         $ics->setEOL("\r\n");
         /* application/ics part */
         $ics2 = clone $ics;
         $ics2->setType('application/ics');
         /* multipart/mixed part */
         $multipart = new Horde_Mime_Part();
         $multipart->setType('multipart/mixed');
         $inner = self::buildMimeMessage($view, 'notification', $image);
         $inner->addPart($ics);
         $multipart->addPart($inner);
         $multipart->addPart($ics2);
         $recipient = $attendee->addressObject;
         $mail = new Horde_Mime_Mail(array('Subject' => $view->subject, 'To' => $recipient, 'From' => $ident->getDefaultFromAddress(true), 'User-Agent' => 'Kronolith ' . $registry->getVersion()));
         $mail->setBasePart($multipart);
         try {
             $mail->send($injector->getInstance('Horde_Mail'));
             $notification->push(sprintf(_("The event notification to %s was successfully sent."), $recipient), 'horde.success');
         } catch (Horde_Mime_Exception $e) {
             $notification->push(sprintf(_("There was an error sending an event notification to %s: %s"), $recipient, $e->getMessage(), $e->getCode()), 'horde.error');
         }
     }
 }
示例#4
0
文件: Driver.php 项目: horde/horde
 /**
  * Handle meeting responses.
  *
  * @param array $response  The response data. Contains:
  *   - requestid: The identifier of the meeting request. Used by the server
  *                to fetch the original meeting request details.
  *   - response:  The user's response to the request. One of the response
  *                code constants.
  *   - folderid:  The collection id that contains the meeting request.
  *   -
  *
  * @return string  The UID of any created calendar entries, otherwise false.
  * @throws Horde_ActiveSync_Exception, Horde_Exception_NotFound
  */
 public function meetingResponse(array $response)
 {
     global $injector;
     if (empty($response['folderid']) || empty($response['requestid']) || empty($response['response'])) {
         throw new Horde_ActiveSync_Exception('Invalid meeting response.');
     }
     // First thing we need is to obtain the meeting request.
     $imap_message = $this->_imap->getImapMessage($response['folderid'], $response['requestid']);
     if (empty($imap_message)) {
         throw new Horde_Exception_NotFound();
     }
     $imap_message = $imap_message[$response['requestid']];
     // Find the request
     if (!($part = $imap_message->hasiCalendar())) {
         $this->_logger->err('Unable to find the meeting request.');
         throw new Horde_Exception_NotFound();
     }
     // Parse the vCal
     $vCal = new Horde_Icalendar();
     $data = $part->getContents();
     if (!$vCal->parsevCalendar($data, 'VCALENDAR', $part->getCharset())) {
         throw new Horde_ActiveSync_Exception('Unknown error parsing vCal data.');
     }
     if (!($vEvent = $vCal->findComponent('vEvent'))) {
         throw new Horde_ActiveSync_Exception('Unknown error locating vEvent.');
     }
     // Update the vCal so the response will be reflected when imported.
     $ident = $injector->getInstance('Horde_Core_Factory_Identity')->create($this->_user);
     $cn = $ident->getValue('fullname');
     $email = $ident->getValue('from_addr');
     switch ($response['response']) {
         case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_ACCEPTED:
             $itip_response = 'ACCEPTED';
             break;
         case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_TENTATIVE:
             $itip_response = 'TENTATIVE';
             break;
         case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_DECLINED:
             $itip_response = 'DECLINED';
     }
     $vEvent->updateAttendee($email, $itip_response);
     // Create an event from the vEvent.
     // Note we don't use self::changeMessage since we don't want to treat
     // this as an incoming message addition from the PIM. Otherwise, the
     // message may not get synched back to the PIM.
     try {
         $uid = $this->_connector->calendar_import_vevent($vEvent);
     } catch (Horde_Exception $e) {
         $this->_logger->err($e->getMessage());
         throw new Horde_ActiveSync_Exception($e);
     }
     if (!empty($response['sendresponse'])) {
         if ($response['sendresponse'] !== true) {
             $comment = $response['sendresponse']->data;
             if ($response['sendresponse']->type == Horde_ActiveSync::BODYPREF_TYPE_HTML) {
                 $comment = Horde_Text_Filter::filter($comment, 'Html2text', array('charset' => 'UTF-8', 'nestingLimit' => 1000));
             }
         } else {
             $comment = '';
         }
         // Start building the iTip response email.
         try {
             $organizer = parse_url($vEvent->getAttribute('ORGANIZER'));
             $organizer = $organizer['path'];
         } catch (Horde_Icalendar_Exception $e) {
             $this->_logger->err('Unable to find organizer.');
             throw new Horde_ActiveSync_Exception($e);
         }
         $ident = $injector->getInstance('Horde_Core_Factory_Identity')->create($event->creator);
         if (!$ident->getValue('from_addr')) {
             throw new Horde_ActiveSync_Exception(_("You do not have an email address configured in your Personal Information Preferences."));
         }
         $resource = new Horde_Itip_Resource_Identity($ident, $vEvent->getAttribute('ATTENDEE'), (string) $ident->getFromAddress());
         switch ($response['response']) {
             case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_ACCEPTED:
                 $type = new Horde_Itip_Response_Type_Accept($resource, $comment);
                 break;
             case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_DECLINED:
                 $type = new Horde_Itip_Response_Type_Decline($resource, $comment);
                 break;
             case Horde_ActiveSync_Request_MeetingResponse::RESPONSE_TENTATIVE:
                 $type = new Horde_Itip_Response_Type_Tentative($resource, $comment);
                 break;
         }
         try {
             // Send the reply.
             Horde_Itip::factory($vEvent, $resource)->sendMultiPartResponse($type, new Horde_Core_Itip_Response_Options_Horde('UTF-8', array()), $injector->getInstance('Horde_Mail'));
             $this->_logger->info('Reply sent.');
         } catch (Horde_Itip_Exception $e) {
             $this->_logger->err(sprintf(_("Error sending reply: %s."), $e->getMessage()), 'horde.error');
         }
     }
     // Delete the original request. EAS Specs require this. Most clients
     // will remove the email from the UI as soon as the response is sent.
     // Failure to remove it from the server will result in an inconsistent
     // sync state.
     try {
         $this->_imap->deleteMessages(array($response['requestid']), $response['folderid']);
     } catch (Horde_ActiveSync_Exception $e) {
         $this->_logger->err($e->getMessage());
     }
     return $uid;
 }