diff --git a/wallace/module_resources.py b/wallace/module_resources.py --- a/wallace/module_resources.py +++ b/wallace/module_resources.py @@ -170,7 +170,10 @@ return filepath recipients = [address for displayname,address in getaddresses(message.get_all('X-Kolab-To'))] - sender_email = [address for displayname,address in getaddresses(message.get_all('X-Kolab-From'))][0] + + sender_email = [ + address for displayname,address in getaddresses(message.get_all('X-Kolab-From')) + ][0] any_itips = False any_resources = False @@ -181,8 +184,8 @@ # is an iTip message by checking the length of this list. try: itip_events = events_from_message(message, ['REQUEST', 'REPLY', 'CANCEL']) - except Exception, e: - log.error(_("Failed to parse iTip events from message: %r" % (e))) + except Exception, errmsg: + log.error(_("Failed to parse iTip events from message: %r" % (errmsg))) itip_events = [] if not len(itip_events) > 0: @@ -226,9 +229,14 @@ if any_resources: if not any_itips: - log.debug(_("Not an iTip message, but sent to resource nonetheless. Reject message"), level=5) + log.debug( + _("Not an iTip message, but sent to resource nonetheless. Reject message"), + level=5 + ) + reject(filepath) return False + else: # Continue. Resources and iTips. We like. pass @@ -246,9 +254,15 @@ # check if resource attendees match the envelope recipient if len(resource_dns) == 0: - log.info(_("No resource attendees matching envelope recipient %s, Reject message") % (resource_recipient)) + log.info( + _("No resource attendees matching envelope recipient %s, Reject message") % ( + resource_recipient + ) + ) + log.debug("%r" % (itip_events), level=8) reject(filepath) + return False @@ -269,23 +283,43 @@ # find initial reservation referenced by the reply if reference_uid: - (event, master) = find_existing_event(reference_uid, itip_event['recurrence-id'], receiving_resource) - log.debug(_("iTip REPLY to %r, %r; matches %r") % (reference_uid, itip_event['recurrence-id'], type(event)), level=8) + (event, master) = find_existing_event( + reference_uid, + itip_event['recurrence-id'], + receiving_resource + ) + + log.debug( + _("iTip REPLY to %r, %r; matches %r") % ( + reference_uid, + itip_event['recurrence-id'], + type(event) + ), + level=8 + ) if event: try: sender_attendee = itip_event['xml'].get_attendee_by_email(sender_email) owner_reply = sender_attendee.get_participant_status() - log.debug(_("Sender Attendee: %r => %r") % (sender_attendee, owner_reply), level=8) + log.debug( + _("Sender Attendee: %r => %r") % (sender_attendee, owner_reply), + level=8 + ) + except Exception, e: log.error(_("Could not find envelope sender attendee: %r") % (e)) continue # compare sequence number to avoid outdated replies if not itip_event['sequence'] == event.get_sequence(): - log.info(_("The iTip reply sequence (%r) doesn't match the referred event version (%r). Ignoring.") % ( - itip_event['sequence'], event.get_sequence() - )) + log.info( + _("The iTip reply sequence (%r) doesn't match the referred event version (%r). Ignoring.") % ( + itip_event['sequence'], + event.get_sequence() + ) + ) + continue # forward owner response comment @@ -306,7 +340,11 @@ sender_attendee.get_participant_status(True), reference_uid )) else: - log.info(_("Event referenced by this REPLY (%r) not found in resource calendar") % (reference_uid)) + log.info( + _("Event referenced by this REPLY (%r) not found in resource calendar") % ( + reference_uid + ) + ) else: log.info(_("No event reference found in this REPLY. Ignoring.")) @@ -317,30 +355,72 @@ # else: try: - receiving_attendee = itip_event['xml'].get_attendee_by_email(receiving_resource['mail']) - log.debug(_("Receiving Resource: %r; %r") % (receiving_resource, receiving_attendee), level=8) + receiving_attendee = itip_event['xml'].get_attendee_by_email( + receiving_resource['mail'] + ) + + log.debug( + _("Receiving Resource: %r; %r") % (receiving_resource, receiving_attendee), + level=8 + ) + except Exception, e: log.error(_("Could not find envelope attendee: %r") % (e)) continue # ignore updates and cancellations to resource collections who already delegated the event - if len(receiving_attendee.get_delegated_to()) > 0 or receiving_attendee.get_role() == kolabformat.NonParticipant: + _radt = receiving_attendee.get_delegated_to() + _rar = receiving_attendee.get_role() + + if len(_radt) > 0 or _rar == kolabformat.NonParticipant: done = True - log.debug(_("Recipient %r is non-participant, ignoring message") % (receiving_resource['mail']), level=8) + + log.debug( + _("Recipient %r is non-participant, ignoring message") % ( + receiving_resource['mail'] + ), + level=8 + ) # process CANCEL messages if not done and itip_event['method'] == "CANCEL": for resource in resource_dns: - if resources[resource]['mail'] in [a.get_email() for a in itip_event['xml'].get_attendees()] \ - and resources[resource].has_key('kolabtargetfolder'): - (event, master) = find_existing_event(itip_event['uid'], itip_event['recurrence-id'], resources[resource]) + r_emails = [a.get_email() for a in itip_event['xml'].get_attendees()] + _resource = resources[resource] + + if _resource['mail'] in r_emails and 'kolabtargetfolder' in _resource: + (event, master) = find_existing_event( + itip_event['uid'], + itip_event['recurrence-id'], + _resource + ) + + if not event: + continue + # remove entire event - if event and master is None: - log.debug(_("Cancellation for entire event %r: deleting") % (itip_event['uid']), level=8) - delete_resource_event(itip_event['uid'], resources[resource], event._msguid) + if master is None: + log.debug( + _("Cancellation for entire event %r: deleting") % (itip_event['uid']), + level=8 + ) + + delete_resource_event( + itip_event['uid'], + resources[resource], + event._msguid + ) + # just cancel one single occurrence: add exception with status=cancelled - elif master is not None: - log.debug(_("Cancellation for a single occurrence %r of %r: updating...") % (itip_event['recurrence-id'], itip_event['uid']), level=8) + else: + log.debug( + _("Cancellation for a single occurrence %r of %r: updating...") % ( + itip_event['recurrence-id'], + itip_event['uid'] + ), + level=8 + ) + event.set_status('CANCELLED') event.set_transparency(True) _itip_event = dict(xml=event, uid=event.get_uid(), _master=master) @@ -356,7 +436,12 @@ # do the magic for the receiving attendee - (available_resource, itip_event) = check_availability(itip_events, resource_dns, resources, receiving_attendee) + (available_resource, itip_event) = check_availability( + itip_events, + resource_dns, + resources, + receiving_attendee + ) _reject = False resource = None @@ -364,10 +449,12 @@ # accept reservation if available_resource is not None: - if available_resource['mail'] in [a.get_email() for a in itip_event['xml'].get_attendees()]: + atts = [a.get_email() for a in itip_event['xml'].get_attendees()] + if available_resource['mail'] in atts: # check if reservation was delegated - if available_resource['mail'] != receiving_resource['mail'] and receiving_attendee.get_participant_status() == kolabformat.PartDelegated: - original_resource = receiving_resource + if available_resource['mail'] != receiving_resource['mail']: + if receiving_attendee.get_participant_status() == kolabformat.PartDelegated: + original_resource = receiving_resource resource = available_resource else: @@ -377,20 +464,33 @@ if available_resource.has_key('memberof'): original_resource = resources[available_resource['memberof']] - if original_resource['mail'] in [a.get_email() for a in itip_event['xml'].get_attendees()]: + atts = [a.get_email() for a in itip_event['xml'].get_attendees()] + + if original_resource['mail'] in atts: # # Delegate: # - delegator: the original resource collection # - delegatee: the target resource # - itip_event['xml'].delegate(original_resource['mail'], available_resource['mail'], available_resource['cn']) + itip_event['xml'].delegate( + original_resource['mail'], + available_resource['mail'], + available_resource['cn'] + ) # set delegator to NON-PARTICIPANT and RSVP=FALSE delegator = itip_event['xml'].get_attendee_by_email(original_resource['mail']) delegator.set_role(kolabformat.NonParticipant) delegator.set_rsvp(False) - log.debug(_("Delegate invitation for resource collection %r to %r") % (original_resource['mail'], available_resource['mail']), level=8) + log.debug( + _("Delegate invitation for resource collection %r to %r") % ( + original_resource['mail'], + available_resource['mail'] + ), + level=8 + ) + resource = available_resource # Look for ACT_REJECT policy @@ -405,11 +505,32 @@ break if resource is not None and not _reject: - log.debug(_("Accept invitation for individual resource %r / %r") % (resource['dn'], resource['mail']), level=8) - accept_reservation_request(itip_event, resource, original_resource, False, invitationpolicy) + log.debug( + _("Accept invitation for individual resource %r / %r") % ( + resource['dn'], + resource['mail'] + ), + level=8 + ) + + accept_reservation_request( + itip_event, + resource, + original_resource, + False, + invitationpolicy + ) + else: resource = resources[resource_dns[0]] # this is the receiving resource record - log.debug(_("Decline invitation for individual resource %r / %r") % (resource['dn'], resource['mail']), level=8) + log.debug( + _("Decline invitation for individual resource %r / %r") % ( + resource['dn'], + resource['mail'] + ), + level=8 + ) + decline_reservation_request(itip_event, resource) cleanup()