summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2014-08-06 16:39:22 (GMT)
committerThomas Bruederli <bruederli@kolabsys.com>2014-08-06 16:39:22 (GMT)
commit9febaa9596bff65c25f81688283fbf5940a4bdef (patch)
treeb3cb6f02eac7717736dd47fa2f439bfacda47cfb
parent9151feafa799c0795845f2a020d38da4f45b4437 (diff)
downloadpykolab-9febaa9596bff65c25f81688283fbf5940a4bdef.tar.gz
Fix iTip REPLY when an attendee delegated to another: both attendees shall be listed (RFC 5546, Section 3.2.2.3.)
-rw-r--r--pykolab/xml/attendee.py18
-rw-r--r--pykolab/xml/event.py15
-rw-r--r--tests/unit/test-003-event.py36
3 files changed, 60 insertions, 9 deletions
diff --git a/pykolab/xml/attendee.py b/pykolab/xml/attendee.py
index 4a30622..c4ccb96 100644
--- a/pykolab/xml/attendee.py
+++ b/pykolab/xml/attendee.py
@@ -61,6 +61,8 @@ class Attendee(kolabformat.Attendee):
'rsvp': 'rsvp',
'partstat': 'get_participant_status',
'cutype': 'get_cutype',
+ 'delegated-to': 'get_delegated_to',
+ 'delegated-from': 'get_delegated_from',
}
def __init__(
@@ -157,11 +159,17 @@ class Attendee(kolabformat.Attendee):
return self._translate_value(cutype, self.cutype_map)
return cutype
- def get_delegated_from(self):
- return self.delegatedFrom()
-
- def get_delegated_to(self):
- return self.delegatedTo()
+ def get_delegated_from(self, translated=False):
+ delegators = []
+ for cr in self.delegatedFrom():
+ delegators.append(cr.email() if translated else ContactReference(cr))
+ return delegators
+
+ def get_delegated_to(self, translated=False):
+ delegatees = []
+ for cr in self.delegatedTo():
+ delegatees.append(cr.email() if translated else ContactReference(cr))
+ return delegatees
def get_email(self):
return self.contactreference.get_email()
diff --git a/pykolab/xml/event.py b/pykolab/xml/event.py
index ca23694..eac764d 100644
--- a/pykolab/xml/event.py
+++ b/pykolab/xml/event.py
@@ -87,7 +87,7 @@ class Event(object):
"summary": "summary",
"description": "description",
"priority": "priority",
- "status": "get_status",
+ "status": "get_ical_status",
"location": "location",
"organizer": "organizer",
"attendee": "get_attendees",
@@ -1012,16 +1012,16 @@ class Event(object):
msg['To'] = self.get_organizer().email()
attendees = self.get_attendees()
+ reply_attendees = []
- # TODO: There's an exception here for delegation (partstat DELEGATED)
+ # There's an exception here for delegation (partstat DELEGATED)
for attendee in attendees:
if attendee.get_email() == from_address:
# Only the attendee is supposed to be listed in a reply
attendee.set_participant_status(participant_status)
attendee.set_rsvp(False)
- self._attendees = [attendee]
- self.event.setAttendees(self._attendees)
+ reply_attendees.append(attendee)
name = attendee.get_name()
email = attendee.get_email()
@@ -1031,6 +1031,13 @@ class Event(object):
else:
msg_from = '"%s" <%s>' % (name, email)
+ elif from_address in attendee.get_delegated_from(True):
+ reply_attendees.append(attendee)
+
+ # keep only replying (and delegated) attendee(s)
+ self._attendees = reply_attendees
+ self.event.setAttendees(self._attendees)
+
if msg_from == None:
organizer = self.get_organizer()
email = organizer.email()
diff --git a/tests/unit/test-003-event.py b/tests/unit/test-003-event.py
index 1f54419..4736b19 100644
--- a/tests/unit/test-003-event.py
+++ b/tests/unit/test-003-event.py
@@ -428,6 +428,42 @@ END:VEVENT
self.assertEqual(event['X-CUSTOM'], "check")
self.assertIsInstance(event['dtstamp'].dt, datetime.datetime)
+ def test_019_to_message_itip(self):
+ self.event = Event()
+ self.event.set_summary("test")
+ self.event.set_start(datetime.datetime(2014, 05, 23, 11, 00, 00, tzinfo=pytz.timezone("Europe/London")))
+ self.event.set_end(datetime.datetime(2014, 05, 23, 12, 30, 00, tzinfo=pytz.timezone("Europe/London")))
+ self.event.set_organizer("me@kolab.org")
+ self.event.add_attendee("john@doe.org")
+ self.event.add_attendee("jane@doe.org")
+
+ message = self.event.to_message_itip("john@doe.org", method="REPLY", participant_status="ACCEPTED")
+ itip_event = None
+ for part in message.walk():
+ if part.get_content_type() == "text/calendar":
+ ical = icalendar.Calendar.from_ical(part.get_payload(decode=True))
+ itip_event = ical.walk('VEVENT')[0]
+ break
+
+ self.assertEqual(itip_event['uid'], self.event.get_uid())
+ self.assertEqual(itip_event['attendee'].lower(), 'mailto:john@doe.org')
+
+ # delegate jane => jack
+ self.event.delegate("jane@doe.org", "jack@ripper.com", "Jack")
+
+ message = self.event.to_message_itip("jane@doe.org", method="REPLY", participant_status="DELEGATED")
+ itip_event = None
+ for part in message.walk():
+ if part.get_content_type() == "text/calendar":
+ ical = icalendar.Calendar.from_ical(part.get_payload(decode=True))
+ itip_event = ical.walk('VEVENT')[0]
+ break
+
+ self.assertEqual(len(itip_event['attendee']), 2)
+ self.assertEqual(itip_event['attendee'][0].lower(), 'mailto:jane@doe.org')
+ self.assertEqual(itip_event['attendee'][1].lower(), 'mailto:jack@ripper.com')
+
+
def test_020_calendaring_recurrence(self):
rrule = kolabformat.RecurrenceRule()
rrule.setFrequency(kolabformat.RecurrenceRule.Monthly)