paul@0 | 1 | #!/usr/bin/env python |
paul@0 | 2 | |
paul@0 | 3 | from email import message_from_file |
paul@0 | 4 | from vCalendar import parse |
paul@0 | 5 | import sys |
paul@0 | 6 | |
paul@0 | 7 | try: |
paul@0 | 8 | from cStringIO import StringIO |
paul@0 | 9 | except ImportError: |
paul@0 | 10 | from StringIO import StringIO |
paul@0 | 11 | |
paul@0 | 12 | # Postfix exit codes. |
paul@0 | 13 | |
paul@0 | 14 | EX_USAGE = 64 |
paul@0 | 15 | EX_DATAERR = 65 |
paul@0 | 16 | EX_NOINPUT = 66 |
paul@0 | 17 | EX_NOUSER = 67 |
paul@0 | 18 | EX_NOHOST = 68 |
paul@0 | 19 | EX_UNAVAILABLE = 69 |
paul@0 | 20 | EX_SOFTWARE = 70 |
paul@0 | 21 | EX_OSERR = 71 |
paul@0 | 22 | EX_OSFILE = 72 |
paul@0 | 23 | EX_CANTCREAT = 73 |
paul@0 | 24 | EX_IOERR = 74 |
paul@0 | 25 | EX_TEMPFAIL = 75 |
paul@0 | 26 | EX_PROTOCOL = 76 |
paul@0 | 27 | EX_NOPERM = 77 |
paul@0 | 28 | EX_CONFIG = 78 |
paul@0 | 29 | |
paul@0 | 30 | # Permitted iTIP content types. |
paul@0 | 31 | |
paul@0 | 32 | itip_content_types = [ |
paul@0 | 33 | "text/calendar", # from RFC 6047 |
paul@0 | 34 | "text/x-vcalendar", "application/ics", # other possibilities |
paul@0 | 35 | ] |
paul@0 | 36 | |
paul@0 | 37 | def process(f): |
paul@0 | 38 | msg = message_from_file(f) |
paul@0 | 39 | |
paul@0 | 40 | # Handle messages with iTIP parts. |
paul@0 | 41 | |
paul@0 | 42 | for part in msg.walk(): |
paul@0 | 43 | if part.get_content_type() in itip_content_types and \ |
paul@0 | 44 | part.get_param("method"): |
paul@0 | 45 | |
paul@0 | 46 | handle_itip_part(part) |
paul@0 | 47 | |
paul@0 | 48 | def get_itip_elements(elements): |
paul@0 | 49 | d = {} |
paul@0 | 50 | for name, attr, value in elements: |
paul@0 | 51 | if isinstance(value, list): |
paul@0 | 52 | d[name] = attr, get_itip_elements(value) |
paul@0 | 53 | else: |
paul@0 | 54 | d[name] = attr, value |
paul@0 | 55 | return d |
paul@0 | 56 | |
paul@0 | 57 | def get_value(d, name): |
paul@0 | 58 | if d.has_key(name): |
paul@0 | 59 | attr, value = d[name] |
paul@0 | 60 | return value |
paul@0 | 61 | else: |
paul@0 | 62 | return None |
paul@0 | 63 | |
paul@0 | 64 | def handle_itip_part(part): |
paul@0 | 65 | method = part.get_param("method") |
paul@0 | 66 | |
paul@0 | 67 | f = StringIO(part.get_payload(decode=True)) |
paul@0 | 68 | doctype, attrs, elements = parse(f, encoding=part.get_content_charset()) |
paul@0 | 69 | |
paul@0 | 70 | if doctype == "VCALENDAR": |
paul@0 | 71 | itip = get_itip_elements(elements) |
paul@0 | 72 | |
paul@0 | 73 | if get_value(itip, "METHOD") == method: |
paul@0 | 74 | for name, handler in [ |
paul@0 | 75 | ("VFREEBUSY", handle_itip_freebusy), |
paul@0 | 76 | ("VEVENT", handle_itip_event), |
paul@0 | 77 | ("VTODO", handle_itip_todo), |
paul@0 | 78 | ("VJOURNAL", handle_itip_journal), |
paul@0 | 79 | ]: |
paul@0 | 80 | |
paul@0 | 81 | obj = get_value(itip, name) |
paul@0 | 82 | if obj: |
paul@0 | 83 | uid = get_value(obj, "UID") |
paul@0 | 84 | if uid: |
paul@0 | 85 | handler(obj, method) |
paul@0 | 86 | |
paul@0 | 87 | def handle_itip_freebusy(freebusy, method): |
paul@0 | 88 | print >>open("/tmp/imip.txt", "a"), freebusy |
paul@0 | 89 | |
paul@0 | 90 | def handle_itip_event(event, method): |
paul@0 | 91 | print >>open("/tmp/imip.txt", "a"), event |
paul@0 | 92 | |
paul@0 | 93 | def handle_itip_todo(todo, method): |
paul@0 | 94 | print >>open("/tmp/imip.txt", "a"), todo |
paul@0 | 95 | |
paul@0 | 96 | def handle_itip_journal(journal, method): |
paul@0 | 97 | print >>open("/tmp/imip.txt", "a"), journal |
paul@0 | 98 | |
paul@0 | 99 | if __name__ == "__main__": |
paul@0 | 100 | process(sys.stdin) |
paul@0 | 101 | |
paul@0 | 102 | # vim: tabstop=4 expandtab shiftwidth=4 |