wallace/module_resources.py

Jeroen van Meeuwen vanmeeuwen at kolabsys.com
Tue Jul 17 12:35:14 CEST 2012


 wallace/module_resources.py |  214 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 162 insertions(+), 52 deletions(-)

New commits:
commit a4770fcb2d67e144e1b4a63bb5d0f0fb20ab391a
Author: Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen at kolabsys.com>
Date:   Tue Jul 17 10:34:34 2012 +0200

    Reduce code footprint for itip/resource detection,
    Reduce code footprint for event updates and methods other than requests

diff --git a/wallace/module_resources.py b/wallace/module_resources.py
index c5b145f..525cc3b 100644
--- a/wallace/module_resources.py
+++ b/wallace/module_resources.py
@@ -126,6 +126,9 @@ def execute(*args, **kw):
 
     message = message_from_file(open(filepath, 'r'))
 
+    any_itips = False
+    any_resources = False
+
     # An iTip message may contain multiple events. Later on, test if the message
     # is an iTip message by checking the length of this list.
     itip_events = itip_events_from_message(message)
@@ -136,19 +139,51 @@ def execute(*args, **kw):
                     "(valid) iTip.")
             )
 
-        accept(filepath)
-        return
-
     else:
+        any_itips = True
+
         log.debug(
                 _("iTip events attached to this message contain the " + \
                     "following information: %r") % (itip_events),
                 level=9
             )
 
-    # See if a resource is actually being allocated
-    if len([x['resources'] for x in itip_events if x.has_key('resources')]) == 0:
-        if len([x['attendees'] for x in itip_events if x.has_key('attendees')]) == 0:
+    if any_itips:
+        # See if any iTip actually allocates a resource.
+        if len([x['resources'] for x in itip_events if x.has_key('resources')]) == 0:
+            if len([x['attendees'] for x in itip_events if x.has_key('attendees')]) == 0:
+                any_resources = False
+            else:
+                any_resources = True
+        else:
+            any_resources = False
+    else:
+        recipients = {
+                "To": getaddresses(message.get_all('To', [])),
+                "Cc": getaddresses(message.get_all('Cc', []))
+                # TODO: Are those all recipient addresses?
+            }
+        log.debug("Recipients: %r" % recipients)
+
+        for recipient in recipients['Cc'] + recipients['To']:
+            if not len(resource_record_from_email_address(recipient[1])) == 0:
+                any_resources = True
+
+    if any_resources:
+        if not any_itips:
+            log.debug(_("Not an iTip message, but sent to resource nonetheless. Reject message"), level=5)
+            reject(filepath)
+            return
+        else:
+            # Continue. Resources and iTips. We like.
+            pass
+    else:
+        if not any_itips:
+            log.debug(_("No itips, no resources, pass along"), level=5)
+            accept(filepath)
+            return
+        else:
+            log.debug(_("iTips, but no resources, pass along"), level=5)
             accept(filepath)
             return
 
@@ -400,73 +435,148 @@ def itip_events_from_message(message):
         Obtain the iTip payload from email.message <message>
     """
 
+    # Placeholder for any itip_events found in the message.
     itip_events = []
 
+    # iTip methods we are actually interested in. Other methods will be ignored.
+    itip_methods = [ "REQUEST", "REPLY", "ADD", "CANCEL" ]
+
     # TODO: Are all iTip messages multipart? RFC 6047, section 2.4 states "A
     # MIME body part containing content information that conforms to this
     # document MUST have (...)" but does not state whether an iTip message must
     # therefore also be multipart.
     if message.is_multipart():
+
         # Check each part
         for part in message.walk():
+
             # The iTip part MUST be Content-Type: text/calendar (RFC 6047,
             # section 2.4)
             if part.get_content_type() == "text/calendar":
-
-                if part.get_param('method') == "REQUEST":
-                    # Python iCalendar prior to 3.0 uses "from_string".
-                    itip_payload = part.get_payload(decode=True)
-                    if hasattr(icalendar.Calendar, 'from_ical'):
-                        cal = icalendar.Calendar.from_ical(itip_payload)
-                    elif hasattr(icalendar.Calendar, 'from_string'):
-                        cal = icalendar.Calendar.from_string(itip_payload)
-                    else:
-                        log.error(_("Could not read iTip from message."))
-                        return []
-
-                    for c in cal.walk():
-                        itip = {}
-                        if c.name == "VEVENT":
-                            # From the event, take the following properties:
-                            #
-                            # - start
-                            # - end (if any)
-                            # - duration (if any)
-                            # - organizer
-                            # - attendees (if any)
-                            # - resources (if any)
-                            # - TODO: recurrence rules (if any)
-                            #   Where are these stored actually?
-                            #
-                            if c.has_key('dtend'):
-                                itip['start'] = c['dtstart']
-                            else:
-                                log.error(_("iTip event without a start"))
-                                return []
-
-                            if c.has_key('dtend'):
-                                itip['end'] = c['dtend']
-                            if c.has_key('duration'):
-                                itip['duration'] = c['duration']
-                            itip['organizer'] = c['organizer']
-                            itip['attendees'] = c['attendee']
-                            if c.has_key('resources'):
-                                itip['resources'] = c['resources']
-                            itip['raw'] = itip_payload
-                            itip['xml'] = event_from_ical(c.to_ical())
-                            itip_events.append(itip)
-                else:
+                if not part.get_param('method') in itip_methods:
                     log.error(
-                            _("Method %r not yet implemented") % (
+                            _("Method %r not really interesting for us.") % (
                                     part.get_param('method')
                                 )
                         )
 
-    else:
+                # Get the itip_payload
+                itip_payload = part.get_payload(decode=True)
+
+                log.debug(_("Raw iTip payload: %s") % (itip_payload))
+
+                # Python iCalendar prior to 3.0 uses "from_string".
+                if hasattr(icalendar.Calendar, 'from_ical'):
+                    cal = icalendar.Calendar.from_ical(itip_payload)
+                elif hasattr(icalendar.Calendar, 'from_string'):
+                    cal = icalendar.Calendar.from_string(itip_payload)
+
+                # If we can't read it, we're out
+                else:
+                    log.error(_("Could not read iTip from message."))
+                    return []
+
+                for c in cal.walk():
+                    if c.name == "VEVENT":
+                        # From the event, take the following properties:
+                        #
+                        # - start
+                        # - end (if any)
+                        # - duration (if any)
+                        # - organizer
+                        # - attendees (if any)
+                        # - resources (if any)
+                        # - TODO: recurrence rules (if any)
+                        #   Where are these stored actually?
+                        #
+
+                        if c.has_key('dtstart'):
+                            itip['start'] = c['dtstart']
+                        else:
+                            log.error(_("iTip event without a start"))
+                            continue
+
+                        if c.has_key('dtend'):
+                            itip['end'] = c['dtend']
+
+                        if c.has_key('duration'):
+                            itip['duration'] = c['duration']
+
+                        itip['organizer'] = c['organizer']
+
+                        itip['attendees'] = c['attendee']
+
+                        if c.has_key('resources'):
+                            itip['resources'] = c['resources']
+
+                        itip['raw'] = itip_payload
+                        itip['xml'] = event_from_ical(c.to_ical())
+
+                        itip_events.append(itip)
+
+                    # end if c.name == "VEVENT"
+
+                # end for c in cal.walk()
+
+            # end if part.get_content_type() == "text/calendar"
+
+        # end for part in message.walk()
+
+    else: # if message.is_multipart()
         log.debug(_("Message is not an iTip message (non-multipart message)"), level=5)
 
     return itip_events
 
+def reject(filepath):
+    new_filepath = os.path.join(
+            mybasepath,
+            'REJECT',
+            os.path.basename(filepath)
+        )
+
+    os.rename(filepath, new_filepath)
+    filepath = new_filepath
+    exec('modules.cb_action_REJECT(%r, %r)' % ('resources',filepath))
+
+def resource_record_from_email_address(email_address):
+    auth = Auth()
+    auth.connect()
+    resource_records = []
+
+    log.debug(
+            _("Checking if email address %r belongs to a resource (collection)") % (
+                    email_address
+                ),
+            level=8
+        )
+
+    resource_records = auth.find_resource(email_address)
+
+    if isinstance(resource_records, list):
+        if len(resource_records) == 0:
+            log.debug(
+                    _("No resource (collection) records found for %r") % (
+                            email_address
+                        ),
+                    level=9
+                )
+
+        else:
+            log.debug(
+                    _("Resource record(s): %r") % (resource_records),
+                    level=8
+                )
+
+    elif isinstance(resource_records, basestring):
+        log.debug(
+                _("Resource record: %r") % (resource_records),
+                level=8
+            )
+
+        resource_records = [ resource_records ]
+
+    return resource_records
+
 def resource_records_from_itip_events(itip_events):
     """
         Given a list of itip_events, determine which resources have been





More information about the commits mailing list