diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index 6aeb4dee..a1550d76 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -3000,13 +3000,13 @@ class calendar extends rcube_plugin $calendar = $this->get_default_calendar($event['sensitivity'], $calendars); $metadata = array( - 'uid' => $event['uid'], + 'uid' => $event['uid'], '_instance' => $event['_instance'], - 'changed' => is_object($event['changed']) ? $event['changed']->format('U') : 0, - 'sequence' => intval($event['sequence']), - 'fallback' => strtoupper($status), - 'method' => $event['_method'], - 'task' => 'calendar', + 'changed' => is_object($event['changed']) ? $event['changed']->format('U') : 0, + 'sequence' => intval($event['sequence']), + 'fallback' => strtoupper($status), + 'method' => $event['_method'], + 'task' => 'calendar', ); // update my attendee status according to submitted method @@ -3033,9 +3033,9 @@ class calendar extends rcube_plugin if (!$reply_sender) { $sender_identity = $this->rc->user->list_emails(true); $event['attendees'][] = array( - 'name' => $sender_identity['name'], - 'email' => $sender_identity['email'], - 'role' => 'OPT-PARTICIPANT', + 'name' => $sender_identity['name'], + 'email' => $sender_identity['email'], + 'role' => 'OPT-PARTICIPANT', 'status' => strtoupper($status), ); $metadata['attendee'] = $sender_identity['email']; @@ -3061,23 +3061,27 @@ class calendar extends rcube_plugin // only update attendee status if ($event['_method'] == 'REPLY') { // try to identify the attendee using the email sender address - $existing_attendee = -1; + $existing_attendee = -1; $existing_attendee_emails = array(); + foreach ($existing['attendees'] as $i => $attendee) { $existing_attendee_emails[] = $attendee['email']; if ($this->itip->compare_email($attendee['email'], $event['_sender'], $event['_sender_utf'])) { $existing_attendee = $i; } } - $event_attendee = null; + + $event_attendee = null; $update_attendees = array(); + foreach ($event['attendees'] as $attendee) { if ($this->itip->compare_email($attendee['email'], $event['_sender'], $event['_sender_utf'])) { - $event_attendee = $attendee; - $update_attendees[] = $attendee; + $event_attendee = $attendee; + $update_attendees[] = $attendee; $metadata['fallback'] = $attendee['status']; $metadata['attendee'] = $attendee['email']; - $metadata['rsvp'] = $attendee['rsvp'] || $attendee['role'] != 'NON-PARTICIPANT'; + $metadata['rsvp'] = $attendee['rsvp'] || $attendee['role'] != 'NON-PARTICIPANT'; + if ($attendee['status'] != 'DELEGATED') { break; } @@ -3103,6 +3107,23 @@ class calendar extends rcube_plugin } } + // Accept sender as a new participant (different email in From: and the iTip) + // Use ATTENDEE entry from the iTip with replaced email address + if (!$event_attendee) { + // remove the organizer + $itip_attendees = array_filter($event['attendees'], function($item) { return $item['role'] != 'ORGANIZER'; }); + + // there must be only one attendee + if (is_array($itip_attendees) && count($itip_attendees) == 1) { + $event_attendee = $itip_attendees[key($itip_attendees)]; + $event_attendee['email'] = $event['_sender']; + $update_attendees[] = $event_attendee; + $metadata['fallback'] = $event_attendee['status']; + $metadata['attendee'] = $event_attendee['email']; + $metadata['rsvp'] = $event_attendee['rsvp'] || $event_attendee['role'] != 'NON-PARTICIPANT'; + } + } + // found matching attendee entry in both existing and new events if ($existing_attendee >= 0 && $event_attendee) { $existing['attendees'][$existing_attendee] = $event_attendee; @@ -3113,6 +3134,9 @@ class calendar extends rcube_plugin $existing['attendees'][] = $event_attendee; $success = $this->driver->update_attendees($existing, $update_attendees); } + else if (!$event_attendee) { + $error_msg = $this->gettext('errorunknownattendee'); + } else { $error_msg = $this->gettext('newerversionexists'); } diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc index b5504182..3bbca608 100644 --- a/plugins/calendar/localization/en_US.inc +++ b/plugins/calendar/localization/en_US.inc @@ -249,6 +249,7 @@ $labels['nowritecalendarfound'] = 'No calendar found to save the event'; $labels['importedsuccessfully'] = 'The event was successfully added to \'$calendar\''; $labels['updatedsuccessfully'] = 'The event was successfully updated in \'$calendar\''; $labels['attendeupdateesuccess'] = 'Successfully updated the participant\'s status'; +$labels['errorunknownattendee'] = 'Failed to find the participant information.'; $labels['itipsendsuccess'] = 'Invitation sent to participants.'; $labels['itipresponseerror'] = 'Failed to send the response to this event invitation'; $labels['itipinvalidrequest'] = 'This invitation is no longer valid'; diff --git a/plugins/libcalendaring/lib/libcalendaring_itip.php b/plugins/libcalendaring/lib/libcalendaring_itip.php index ec3ba00c..f6ddff39 100644 --- a/plugins/libcalendaring/lib/libcalendaring_itip.php +++ b/plugins/libcalendaring/lib/libcalendaring_itip.php @@ -613,6 +613,20 @@ class libcalendaring_itip } } + // It may happen that sender's address is different in From: and the attached iTip + // In such case use the ATTENDEE entry with the address from From: header + if (empty($metadata['attendee']) && !empty($event['_sender'])) { + // remove the organizer + $itip_attendees = array_filter($event['attendees'], function($item) { return $item['role'] != 'ORGANIZER'; }); + + // there must be only one attendee + if (is_array($itip_attendees) && count($itip_attendees) == 1) { + $event_attendee = $itip_attendees[key($itip_attendees)]; + $metadata['attendee'] = $event['_sender']; + $rsvp_status = strtoupper($event_attendee['status']); + } + } + // 1. update the attendee status on our copy $update_button = html::tag('input', array( 'type' => 'button',