Delete old mails from Outlooks deleted items folder

The following script deletes all mails older than 30 days from Outlooks Deleted Items Folder:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os, sys
import win32com.client
from datetime import datetime
from datetime import timedelta
import pywintypes

# Microsoft Outlook Constants
# http://msdn.microsoft.com/en-us/library/aa219371(office.11).aspx
olFolderDeletedItems=3
olFolderSentMail=5
# or you can use the following command to generate
# c:\python26\python.exe c:\Python26\lib\site-packages\win32com\client\makepy.py -d
# After generated, you can use win32com.client.constants.olFolderSentMail

# http://code.activestate.com/recipes/496683-converting-ole-datetime-values-into-python-datetim/
OLE_TIME_ZERO = datetime(1899, 12, 30, 0, 0, 0)
def ole2datetime(oledt):
    return OLE_TIME_ZERO + timedelta(days=float(oledt))

if __name__ == '__main__':
    app = win32com.client.Dispatch( "Outlook.Application" )
    ns = app.GetNamespace( "MAPI" )
    folders = [
        #ns.GetDefaultFolder(olFolderSentMail),
        ns.GetDefaultFolder(olFolderDeletedItems)
    ]
    for folder in folders:
        print( "Processing %s" % folder.Name )

        past30days=datetime.now()-timedelta(days=30)
        mark2delete=[]
        #If you use makepy.py, you have to use the following codes instead of "for item in folder.Items"
        #for i in range(1,folder.Items.Count+1):
        #    item = folder.Items[i]
        for item in folder.Items:
            if ole2datetime(item.LastModificationTime)0:
            for item in mark2delete:
                print( "Removing %s" % item.Subject )
                item.Delete()
        else:
            print("No matched mails.")

Compare/Diff two word files and create a result PDF

import win32com.client
import time

app = win32com.client.Dispatch('Word.Application')

# The original document:
doc = app.Documents.Open('c:\\temp\\firstversion.doc')
# The modified document:
ret = doc.Compare('c:\\temp\\newversion.doc')

app.ActiveDocument.SaveAs('diff.doc')
app.ActiveDocument.ExportAsFixedFormat('diff.pdf', 17, False, 0, 0, 1, 1, 7, True, True, 1, True, True, True)
app.ActiveDocument.Close()
doc.Close()
app.Quit()

Get all file property informations on Windows

# DumpStorage.py - Dumps some user defined properties
# of a COM Structured Storage file.

import pythoncom
from win32com import storagecon # constants related to storage functions.

# These come from ObjIdl.h
FMTID_UserDefinedProperties = "{F29F85E0-4FF9-1068-AB91-08002B27B3D9}"

PIDSI_TITLE               = 0x00000002
PIDSI_SUBJECT             = 0x00000003
PIDSI_AUTHOR              = 0x00000004
PIDSI_CREATE_DTM          = 0x0000000c

def PrintStats(filename) :

    if sys.platform == 'win32':
        if not pythoncom.StgIsStorageFile(filename) :
            print "The file is not a storage file!"
            return
        # Open the file.
        flags = storagecon.STGM_READ | storagecon.STGM_SHARE_EXCLUSIVE
        stg_= pythoncom.StgOpenStorage(filename, None, flags )

        # Now see if the storage object supports Property Information.
        try:
            pss = stg_.QueryInterface(pythoncom.IID_IPropertySetStorage)
        except pythoncom.com_error:
            print "No summary information is available"
            return
        # Open the user defined properties.
        ps = pss.Open(FMTID_UserDefinedProperties)
        props = PIDSI_TITLE, PIDSI_SUBJECT, PIDSI_AUTHOR, PIDSI_CREATE_DTM
        data = ps.ReadMultiple( props )
        # Unpack the result into the items.
        title, subject, author, created = data
        print "Title:", title
        print "Subject:", subject
        print "Author:", author
        print "Created:", created.Format()

if __name__=='__main__':
    import sys
    if len(sys.argv)<2:
        print "Please specify a file name"
    else:
        PrintStats(sys.argv[1])

Events in Microsoft Word and Excel

I think this must be an example from Marc Hammond. It shows how to connect to events in Microsoft Word and Excel:

# OfficeEvents - test/demonstrate events with Word and Excel.
from win32com.client import DispatchWithEvents, Dispatch
import msvcrt, pythoncom
import time, sys
import types

import threading
stopEvent = threading.Event()

def TestExcel():
    class ExcelEvents:
        def OnNewWorkbook(self, wb):
            if type(wb) != types.InstanceType:
                raise RuntimeError, "The transformer doesnt appear to have translated this for us!"
            self.seen_events["OnNewWorkbook"] = None
        def OnWindowActivate(self, wb, wn):
            if type(wb) != types.InstanceType or type(wn) != types.InstanceType:
                raise RuntimeError, "The transformer doesnt appear to have translated this for us!"
            self.seen_events["OnWindowActivate"] = None
        def OnWindowDeactivate(self, wb, wn):
            self.seen_events["OnWindowDeactivate"] = None
        def OnSheetDeactivate(self, sh):
            self.seen_events["OnSheetDeactivate"] = None
        def OnSheetBeforeDoubleClick(self, Sh, Target, Cancel):
            if Target.Column % 2 == 0:
                print "You can double-click there..."
            else:
                print "You can not double-click there..."
            # This function is a void, so the result ends up in
            # the only ByRef - Cancel.
                return 1

    class WorkbookEvents:
        def OnActivate(self):
            print "workbook OnActivate"
        def OnBeforeRightClick(self, Target, Cancel):
            print "It's a Worksheet Event"

    e = DispatchWithEvents("Excel.Application", ExcelEvents)
    e.seen_events = {}
    e.Visible=1
    book = e.Workbooks.Add()
    book = DispatchWithEvents(book, WorkbookEvents)
    print "Have book", book
#    sheet = e.Worksheets(1)
#    sheet = DispatchWithEvents(sheet, WorksheetEvents)

    print "Double-click in a few of the Excel cells..."
    print "Press any key when finished with Excel, or wait 10 seconds..."
    if not _WaitForFinish(e, 10):
        e.Quit()
    if not _CheckSeenEvents(e, ["OnNewWorkbook", "OnWindowActivate"]):
        sys.exit(1)

def TestWord():
    class WordEvents:
        def OnDocumentChange(self):
            self.seen_events["OnDocumentChange"] = None
        def OnWindowActivate(self, doc, wn):
            self.seen_events["OnWindowActivate"] = None
        def OnQuit(self):
            self.seen_events["OnQuit"] = None
            stopEvent.set()

    w = DispatchWithEvents("Word.Application", WordEvents)
    w.seen_events = {}
    w.Visible = 1
    w.Documents.Add()
    print "Press any key when finished with Word, or wait 10 seconds..."
    if not _WaitForFinish(w, 10):
        w.Quit()
    if not _CheckSeenEvents(w, ["OnDocumentChange", "OnWindowActivate"]):
        sys.exit(1)

def _WaitForFinish(ob, timeout):
    end = time.time() + timeout
    while 1:
        if msvcrt.kbhit():
            msvcrt.getch()
            break
        pythoncom.PumpWaitingMessages()
        stopEvent.wait(.2)
        if stopEvent.isSet():
            stopEvent.clear()
            break
        try:
            if not ob.Visible:
                # Gone invisible - we need to pretend we timed
                # out, so the app is quit.
                return 0
        except pythoncom.com_error:
            # Excel is busy (eg, editing the cell) - ignore
            pass
        if time.time() > end:
            return 0
    return 1

def _CheckSeenEvents(o, events):
    rc = 1
    for e in events:
        if not o.seen_events.has_key(e):
            print "ERROR: Expected event did not trigger", e
            rc = 0
    return rc

def test():
    import sys
    if "noword" not in sys.argv[1:]:
        TestWord()
    if "noexcel" not in sys.argv[1:]:
        TestExcel()
    print "Word and Excel event tests passed."

if __name__=='__main__':
    test()

Create Outlook tasks from Taskcoach task file

This is a script which creates Outlook tasks from each task out of a Taskcoach XML-file. I saved my task to file named “My_Tasks.tsk”. Please modify it for your needs.

from xml.dom import minidom
import win32com.client
from datetime import datetime
try:
   oOutlookApp = win32com.client.gencache.EnsureDispatch("Outlook.Application")
except:
   print "MSOutlook: unable to load Outlook"

# this should use more try/except blocks or nested blocks
#onMAPI = oOutlookApp.GetNamespace("MAPI")
#ofTasks = onMAPI.GetDefaultFolder(win32com.client.constants.olFolderTasks)


xml = r'My_Tasks.tsk'

xmldoc = minidom.parse(xml)
tcTasks = xmldoc.getElementsByTagName('task')
print 'Creating %s tasks'%len(tcTasks)

for tcTask in tcTasks:
    print 'Saving %s [%s]' % (tcTask.getAttribute('subject'), tcTask.getAttribute('status'))
    newtask = oOutlookApp.CreateItem(win32com.client.constants.olTaskItem)
    if tcTask.getAttribute('expandedContexts') != 'Dummy': #Todo: Unsichere Ecke
        newtask.Subject = tcTask.getAttribute('subject')
        for note in tcTask.getElementsByTagName('note'):
            newnote = oOutlookApp.CreateItem(win32com.client.constants.olNoteItem)
            newnote.Body += note.getAttribute('subject') + ':\n'
            for nodetext in note.getElementsByTagName('description'):
                newnote.Body += nodetext.firstChild.data
            newnote.Save()
            #newtask.Links.Add(newnote)

        for tasktext in tcTask.getElementsByTagName('description'):
                newtask.Body += tasktext.firstChild.data
        for attachment in tcTask.getElementsByTagName('attachment'):
            newtask.Body += 'File attachment %s:\n%s\n' % (attachment.getAttribute('subject'), attachment.getAttribute('location'))

        if tcTask.getAttribute('duedate') not in ['', None]:
            newtask.DueDate = tcTask.getAttribute('duedate')
        if tcTask.getAttribute('startdate') not in ['', None]:
            newtask.StartDate = tcTask.getAttribute('startdate')
        #elif tcTask.getAttribute('percentageComplete') in ['0', 0]:
            #newtask.Status = 0
            #newtask.PercentComplete = 0
        if tcTask.getAttribute('percentageComplete') in ['100', 100]:
            newtask.Status = 2
            newtask.PercentComplete = 100
        if tcTask.getAttribute('percentageComplete') not in ['', None, '100', 100]:
            newtask.PercentComplete = int(tcTask.getAttribute('percentageComplete'))
            newtask.Status = 5
        newtask.Save()

Get all adressbook entries

import codecs, win32com.client

# This example dumps the items in the default address book

# needed for converting Unicode->Ansi (in local system codepage)
DecodeUnicodeString = lambda x: codecs.latin_1_encode(x)[0]

def DumpDefaultAddressBook():
    # Create instance of Outlook
    o = win32com.client.Dispatch("Outlook.Application")
    mapi = o.GetNamespace("MAPI")
    folder = mapi.GetDefaultFolder(win32com.client.constants.olFolderContacts)
    print "The default address book contains",folder.Items.Count,"items"

    # see Outlook object model for more available properties on ContactItem objects
    attributes = [ 'FullName', 'Email1Address']    
    for i in range(1,folder.Items.Count+1):
        print "~~~ Entry %d ~~~" % i
        item = folder.Items[i]
        for attribute in attributes:
            print attribute, eval('item.%s' % attribute)
        
    o = None

DumpDefaultAddressBook()  

Form extractor from word to Excel

Konrads Smelkovs had a bunch of filled out word documents with word forms in them and neded them in Excel. Initially he tried CSV but it didn’t play nice with encodings. So he decided to write directly to XLS:

"""
Copyright 2009 Konrads Smelkovs 
UTF8Recorder and UnicodeWriter come from python docs
"""

import sys,os,csv
import win32com.client
import pywintypes


class ExcelWriter(object):
    def __init__(self,excelfile):
        self.excelapp=win32com.client.DispatchEx('Excel.Application')
        self.excelapp.Visible=0
        self.excelapp.Application.AskToUpdateLinks=0
        self.workbook=self.excelapp.Workbooks.Add()
        os.unlink(excelfile) #TODO: remove for release
        self.workbook.SaveAs(excelfile)
        # Only worksheet 1 is used.
        self.worksheet=self.workbook.Worksheets.Item(1)
        self.currentrow=1

    def _getrow(self,row):
        """Convert integer row index to Alphabetical:
        1 -> A
        2 -> B
        ...
        """
        if row<27:
            return chr(ord('A')-1 + row)
        else:
            first=row / 26
            return chr(ord('A')-1 + first) +  chr(ord('A')-1 + row % 26)
        
    def __del__(self):
        self.workbook.Save()
        self.workbook.Close()
        self.excelapp.Quit()

    def writerow(self,data):
        for col in xrange(1,len(data)+1):
            range=self._getrow(col)+str(self.currentrow)
            print >>sys.stderr,"Range: %s"  % range
            cell=self.worksheet.Range(range)
            cell.Value=data[col-1]
        self.currentrow+=1
        
def main():
 if len(sys.argv)<3:
    print "Usage: %s  " % sys.argv[0]
    print "Where  - directory containing word docs with forms"
    print "and  - file where to put results"
    sys.exit(-1)
 directory=os.path.abspath(sys.argv[1])
 wordapp = win32com.client.Dispatch("Word.Application")
 wordapp.Visible=0 # Hide word app
 results=[]
 for docfile in os.listdir(directory):
     thisdocresults=[]
     if docfile.endswith(".doc") or docfile.endswith(".docx"):
         print >> sys.stderr, "Processing %s" % docfile
         worddoc=wordapp.Documents.Open(os.path.join(directory,docfile))
         for i in range(1,worddoc.FormFields.Count+1):
            try:
                form=worddoc.FormFields.Item(i)
                name=form.Name
                value=form.Result
                thisdocresults.append((name,value))
                try:
                    print >>sys.stderr, "%s: %s" % (name,value)
                except UnicodeEncodeError,e:
                    print >>sys.stderr, "Error decoding charset,%s" % e
            except pywintypes.com_error,e:
                print >>sys.stderr, "Exception: %s" % str(e)
         results.append(thisdocresults)
         worddoc.Close()
 wordapp.Quit()
 writer=ExcelWriter(os.path.abspath(sys.argv[2]))
 print >>sys.stderr,"Writing to Excel"
 for docres in results:
     data=[]
     for (n,v) in docres:
         data.append(v)
     writer.writerow(data)
 
if __name__=="__main__":
    main()

Let merlin think (MS Agent automation)

import win32com.client
ag=win32com.client.Dispatch("Agent.Control")
ag.Connected=1
ag.Characters.Load("Merlin")
ag.Characters("Merlin").Show()
text = raw_input("please type something...")
ag.Characters("Merlin").Think(text)

Outlook Web Access via Python

Adrian Holovaty wrote a small Python script to access Microsoft Outlook Web Access. It can do some actions by commandline via screen scraping. The script lets you access your emails (in raw format, with all headers) from the Microsoft Outlook’s webmail interface.

It works by screen-scraping the interface. Possible actions are:

  • Log into a Microsoft Outlook Web Access account with a given username and password
  • Retrieve all email IDs from the first page of Inbox
  • Retrieve full, raw source of the email with a given ID
  • Delete an email with a given ID (move to”Deleted Items” folder)

Download the script

Send email with Outlook and Python

A simple example to send emails via Outlook and Python win32com.

import win32com.client

s = win32com.client.Dispatch("Mapi.Session")
o = win32com.client.Dispatch("Outlook.Application")
s.Logon("Outlook2003")
    
Msg = o.CreateItem(0)
Msg.To = "recipient@domain.com"
    
Msg.CC = "more email addresses here"
Msg.BCC = "more email addresses here"
    
Msg.Subject = "The subject of you mail"
Msg.Body = "The main body text of you mail"
    
attachment1 = "Path to attachment no. 1"
attachment2 = "Path to attachment no. 2"
Msg.Attachments.Add(attachment1)
Msg.Attachments.Add(attachment2)
 
Msg.Send()