def handle_msg(uidpath,rfc822):
    global l_timedep_tasks

    print "In handle_msg for "+uidpath
    sys.stdout.flush()
    
    #Ignore reflections except for MID dictionary processing
    if uidpath in mirror:
        print "Found in mirror."
        #Examine References header and update msg_dict
        msg_dict.process_msg(email.parser.Parser().parsestr(rfc822),uidpath)
        print "removing from mirror: done."
        mirror.remove(uidpath)
        print "mirror: "+repr(mirror)
        sys.stdout.flush()
        return

    #Ignore specified accounts
    for acct in ignored_accounts:
        if uidpath.find(acct+"/")==0:
            print "In ignored account: done."
            sys.stdout.flush()
            return
    
    msg = email.parser.Parser().parsestr(rfc822)
    
    #We need to handle an updated Task, following protocol
    if uidpath.find("Tasks")==0:
        task_revised = False
        if msg['X-MailTask-Completion-Status']=="Incomplete" and uidpath!="Tasks/BLACKHOLE":
            if 'X-MailTask-Virgin' not in msg and (type(msg.get_payload())==str or len(msg.get_payload())==1) or 'X-MailTask-Forced-Complete' in msg:
                del msg['X-MailTask-Completion-Status']
                msg['X-MailTask-Completion-Status']="Completed"
                task_revised = True
            elif 'X-MailTask-Virgin' in msg and len(msg.get_payload())>1:
                del msg['X-MailTask-Virgin']
                task_revised = True
        elif msg['X-MailTask-Completion-Status']=="Completed":
            del msg['X-MailTask-Forced-Complete']
            del msg['X-MailTask-Completion-Status']
            msg['X-MailTask-Completion-Status']="Incomplete"
            if 'X-MailTask-Virgin' not in msg and (type(msg.get_payload())==str or len(msg.get_payload())==1):
                msg['X-MailTask-Virgin']=""
            task_revised = True
        elif msg['X-MailTask-Completion-Status']=="Time-Dependent":
            l_timedep_tasks[uidpath]=msg
        elif uidpath!="Tasks/BLACKHOLE":
            print "*BUG!*: We found a Task with no or invalid X-MailTask-Completion-Status."
            sys.stdout.flush()

        #Examine References header and update msg_dict
        msg_dict.process_msg(msg,uidpath)

        #If necessary, update task
        if task_revised:
            nsync.node_update(uidpath,msg.as_string())
            mirror.add(uidpath)
            print "handle_msg: update "+uidpath+" and add to mirror"
            print "mirror: "+repr(mirror)
            sys.stdout.flush()
    else: #not a Task: scan email headers and, if appropriate, create a new related task or update an existing one
        if 'From' not in msg or 'Message-ID' not in msg or client.get_email_addr_from_header(msg['From']) in ignored_senders:
            print "handle_msg: "+uidpath+" is from an ignored sender."
            sys.stdout.flush()
            return
        #Okay, now, first check if there is a Task out there that refers to a Message-ID that is also referred to by this message
        task_mid = None
        if 'References' in msg:
            print "handle_msg: searching "+uidpath+" related_mids for referring Task"
            sys.stdout.flush()
            related_mids = msg['References'].replace("\r","").replace("\n",",").replace("\t",",").replace(" ",",")
            print "handle_msg: "+repr(related_mids)
            sys.stdout.flush()
            for rmid_ in related_mids.split(","):
                rmid = rmid_.strip()
                if rmid=="":
                    continue
                print "handle_msg: examining "+rmid
                sys.stdout.flush()
                if rmid in msg_dict.rev_mid_dict:
                    print "handle_msg: msg_dict.rev_mid_dict["+rmid+"]: "+repr(msg_dict.rev_mid_dict[rmid])
                    sys.stdout.flush()
                    for referring_mid in msg_dict.rev_mid_dict[rmid]:
                        if referring_mid.find("Tasks/")==0:
                            task_mid = referring_mid
                            break
                    if task_mid!=None:
                        break
        
        #We found one: update its References and Date headers and completion status.
        if task_mid!=None:
            print "handle_msg: Updating reference header of task "+task_mid
            sys.stdout.flush()
            task_msg = email.parser.Parser().parse(open(os.path.join(client.cachedir,task_mid)))

            #Update related IDs
            relmids = mt_utils.get_related_ids(task_msg)
            relmids.append(msg['Message-ID'])
            mt_utils.set_related_ids(task_msg,relmids)

            #Update task_msg Date field
            del task_msg['Date']
            task_msg['Date']=email.utils.formatdate(localtime=True)

            #Update task completion status
            del task_msg['X-MailTask-Forced-Complete']
            del task_msg['X-MailTask-Completion-Status']
            task_msg['X-MailTask-Completion-Status']="Incomplete"
            
            nsync.node_update(task_mid,task_msg.as_string())
            mirror.add(task_mid)
        else: #No existing task, so we must make one
            print "handle_msg: Creating new task referencing MID "+msg['Message-ID']
            sys.stdout.flush()
            newtask=email.message.Message()
            nt_body = email.message.Message()
            nt_body['Content-Type'] = "text/plain"
            payload=""
            if client.get_email_addr_from_header(msg['From']) in email_info:
                payload=email_info[client.get_email_addr_from_header(msg['From'])]
            elif client.get_nick_from_header(msg['From']) in email_info:
                payload=email_info[client.get_nick_from_header(msg['From'])]
            nt_body.set_payload(payload)
            mt_utils.attach_payload(newtask,nt_body)
            newtask['Content-Type']="multipart/x.MailTask"
            newtask['Date']=email.utils.formatdate(localtime=True)
            newtask['Subject'] = client.get_nick_from_header(msg['From'])+": "+msg['Subject'] if 'Subject' in msg and 'From' in msg else "New Task"
            newtask['X-MailTask-Type'] = "Checklist"
            newtask['X-MailTask-Completion-Status'] = "Incomplete"
            newtask['X-MailTask-Virgin'] = "Yes"
            mt_utils.set_related_ids(newtask,[msg['Message-ID']])
            nsync.node_update("Tasks/NEWMESSAGE",newtask.as_string())
Example #2
0
def handle_msg(uidpath,rfc822,mirror_flag):
    global l_timedep_tasks

    print "In handle_msg for "+uidpath
    sys.stdout.flush()
    
    #Ignore reflections except for MID dictionary processing
    if mirror_flag:
        print "Found in mirror."
        #Examine References header and update msg_dict
        msg_dict.process_msg(email.parser.Parser().parsestr(rfc822),uidpath)
        print "mirror: "+repr(nsync.mirror)
        sys.stdout.flush()
        return

    msg = email.parser.Parser().parsestr(rfc822)
    
    #Ignore specified accounts, unless sender in unignored_senders
    if 'From' in msg and client.get_email_addr_from_header(msg['From']) not in unignored_senders and client.get_nick_from_header(msg['From']) not in unignored_senders:
        for acct in ignored_accounts:
            if uidpath.find(acct+"/")==0:
                print "In ignored account: done."
                sys.stdout.flush()
                return
    else:
        print "Sender in unignored_senders or not in ignored account."
    
    #We need to handle an updated Task, following protocol
    if uidpath.find("Tasks")==0:
        task_revised = False
        if msg['X-MailTask-Completion-Status']=="Incomplete" and uidpath!="Tasks/BLACKHOLE":
            if 'X-MailTask-Virgin' not in msg and (type(msg.get_payload())==str or len(msg.get_payload())==1) or 'X-MailTask-Forced-Complete' in msg:
                del msg['X-MailTask-Completion-Status']
                msg['X-MailTask-Completion-Status']="Completed"
                task_revised = True
            elif 'X-MailTask-Virgin' in msg and len(msg.get_payload())>1:
                del msg['X-MailTask-Virgin']
                task_revised = True
        elif msg['X-MailTask-Completion-Status']=="Completed":
            del msg['X-MailTask-Forced-Complete']
            del msg['X-MailTask-Completion-Status']
            msg['X-MailTask-Completion-Status']="Incomplete"
            if 'X-MailTask-Virgin' not in msg and (type(msg.get_payload())==str or len(msg.get_payload())==1):
                msg['X-MailTask-Virgin']=""
            task_revised = True
        elif msg['X-MailTask-Completion-Status']=="Time-Dependent":
            l_timedep_tasks[uidpath]=msg
        elif uidpath!="Tasks/BLACKHOLE":
            print "*BUG!*: We found a Task with no or invalid X-MailTask-Completion-Status."
            sys.stdout.flush()

        #Examine References header and update msg_dict
        msg_dict.process_msg(msg,uidpath)

        #Handle Google Calendar Sync
        try:
            if do_gcal:
                dinfo = None
                gcal_id = msg['X-MailTask-GCalID']
                subject_str = "MailTask: "+msg.get('Subject',"No Subject")
                body_str = mt_utils.get_body(msg).get_payload()
                if 'X-MailTask-Date-Info' in msg:
                    dinfo = mt_utils.gtstfxmdis(msg['X-MailTask-Date-Info'])
                    if len(dinfo)==1:
                        dinfo = (dinfo[0],dinfo[0])

                if not gcal_id and 'X-MailTask-Date-Info' in msg:
                    gcal_id = mt_gcal_sync.insert_gcal_event((subject_str,body_str,dinfo[0],dinfo[1]))
                    msg['X-MailTask-GCalID']=gcal_id
                    task_revised = True
                elif gcal_id and 'X-MailTask-Date-Info' not in msg:
                    mt_gcal_sync.delete_gcal_event(gcal_id)
                    del msg['X-MailTask-GCalID']
                    task_revised = True
                elif gcal_id and 'X-MailTask-Date-Info' in msg:
                    mt_gcal_sync.update_gcal_event(gcal_id,(subject_str,body_str,dinfo[0],dinfo[1]))
        except Exception as e:
            print "WARNING: Google Calendar Error: "+e.message

        #If necessary, update task
        if task_revised:
            nsync.node_update(uidpath,msg.as_string())
            print "handle_msg: update "+uidpath+" and add to mirror"
            print "mirror: "+repr(nsync.mirror)
            sys.stdout.flush()
    else: #not a Task: scan email headers and, if appropriate, create a new related task or update an existing one
        if 'From' not in msg or 'Message-ID' not in msg or client.get_email_addr_from_header(msg['From']) in ignored_senders:
            print "handle_msg: "+uidpath+" is from an ignored sender."
            sys.stdout.flush()
            return

        #If we're doing the calendar thing, check for the codeword in the subject
        if do_gcal and 'Subject' in msg and msg['Subject'].find(mt_gcal_sync.codeword)!=-1:
            chronos_tuples = []
            def scan_component(component):
                result = mt_chronos.extract_calendar_event(component.get_payload(decode=True))
                if result!=None:
                    chronos_tuples.append(result)

            try:
                mt_utils.walk_attachments(msg,scan_component)
                for entry in chronos_tuples:
                    mt_gcal_sync.insert_gcal_event(entry)
                return
            except Exception as e:
                print "ERROR: Attempted to schedule calendar event and failed; probable bug."
                print "The exception: "+repr(e)
                sys.stdout.flush()
        
        #Okay, now, first check if there is a Task out there that refers to a Message-ID that is also referred to by this message
        task_mid = None
        if 'References' in msg:
            print "handle_msg: searching "+uidpath+" related_mids for referring Task"
            sys.stdout.flush()
            related_mids = msg['References'].replace("\r","").replace("\n",",").replace("\t",",").replace(" ",",")
            print "handle_msg: "+repr(related_mids)
            sys.stdout.flush()
            for rmid_ in related_mids.split(","):
                rmid = rmid_.strip()
                if rmid=="":
                    continue
                print "handle_msg: examining "+rmid
                sys.stdout.flush()
                if rmid in msg_dict.rev_mid_dict:
                    print "handle_msg: msg_dict.rev_mid_dict["+rmid+"]: "+repr(msg_dict.rev_mid_dict[rmid])
                    sys.stdout.flush()
                    for referring_mid in msg_dict.rev_mid_dict[rmid]:
                        if referring_mid.find("Tasks/")==0:
                            task_mid = referring_mid
                            break
                    if task_mid!=None:
                        break
        
        #We found one: update its References and Date headers and completion status.
        if task_mid!=None:
            print "handle_msg: Updating reference header of task "+task_mid
            sys.stdout.flush()
            task_msg = email.parser.Parser().parse(open(os.path.join(client.cachedir,task_mid)))

            #Update related IDs
            relmids = mt_utils.get_related_ids(task_msg)
            relmids.append(msg['Message-ID'])
            mt_utils.set_related_ids(task_msg,relmids)

            #Update task_msg Date field
            del task_msg['Date']
            task_msg['Date']=email.utils.formatdate(localtime=True)

            #Update task completion status
            del task_msg['X-MailTask-Forced-Complete']
            del task_msg['X-MailTask-Completion-Status']
            task_msg['X-MailTask-Completion-Status']="Incomplete"
            
            nsync.node_update(task_mid,task_msg.as_string())
        else: #No existing task, so we must make one
            print "handle_msg: Creating new task referencing MID "+msg['Message-ID']
            sys.stdout.flush()
            newtask=email.message.Message()
            nt_body = email.message.Message()
            nt_body['Content-Type'] = "text/plain"
            payload=""
            if client.get_email_addr_from_header(msg['From']) in email_info:
                payload=email_info[client.get_email_addr_from_header(msg['From'])]
            elif client.get_nick_from_header(msg['From']) in email_info:
                payload=email_info[client.get_nick_from_header(msg['From'])]
            nt_body.set_payload(payload)
            mt_utils.attach_payload(newtask,nt_body)
            newtask['Content-Type']="multipart/x.MailTask"
            newtask['Date']=email.utils.formatdate(localtime=True)
            newtask['Subject'] = client.get_nick_from_header(msg['From'])+": "+msg['Subject'] if 'Subject' in msg and 'From' in msg and client.get_nick_from_header(msg['From']) else "New Task"
            newtask['X-MailTask-Type'] = "Checklist"
            newtask['X-MailTask-Completion-Status'] = "Incomplete"
            newtask['X-MailTask-Virgin'] = "Yes"
            mt_utils.set_related_ids(newtask,[msg['Message-ID']])
            nsync.node_update("Tasks/NEWMESSAGE",newtask.as_string())