from __future__ import generators
# Dump every property we can find for a MAPI item

import pythoncom
import os, sys

from win32com.mapi import mapi, mapiutil
from win32com.mapi.mapitags import *

import mapi_driver

def FindDupeProps(driver, mapi_folder, prop_tag, dupe_dict):
    hr, data = mapi_folder.GetProps( (PR_DISPLAY_NAME_A,), 0)
    name = data[0][1]
    try:
        prop_tag = int(prop_tag)
    except ValueError:
        # See if a constant in mapitags.
        if prop_tag.startswith("PR_") and prop_tag in globals():
            prop_tag = globals()[prop_tag]
        else:
            props = ( (mapi.PS_PUBLIC_STRINGS, prop_tag), )
            ids = mapi_folder.GetIDsFromNames(props, 0)
            if PROP_ID(ids[0])==0:
                print "Could not resolve property '%s'" % prop_tag
                return 1
            prop_tag = PROP_TAG( PT_UNSPECIFIED, PROP_ID(ids[0]))

    num_with_prop = num_without_prop = 0
    for item in driver.GetAllItems(mapi_folder):
        hr, data = item.GetProps( (prop_tag,PR_SUBJECT_A, PR_ENTRYID), 0)
        if hr==0:
            (tag_hr, tag_data) = data[0]
            (subject_hr, subject_data) = data[1]
            (eid_hr, eid_data) = data[2]
            dupe_dict.setdefault(tag_data, []).append((eid_data, subject_data))
            num_with_prop += 1
        else:
            num_without_prop += 1
    print "Folder '%s': %d items with the property and %d items without it" \
            % (name, num_with_prop, num_without_prop)

def DumpDupes(dupe_dict):
    for val, items in dupe_dict.items():
        if len(items)>1:
            print "Found %d items with property value %r" % (len(items), val)
            for (eid, subject) in items:
                print "", subject

def usage(driver):
    folder_doc = driver.GetFolderNameDoc()
    msg = """\
Usage: %s [-f foldername] [-f ...] property_name_or_tag
-f - Search for the message in the specified folders (default = Inbox)
-n - Show top-level folder names and exit

Dumps all properties for all messages that match the subject.  Subject
matching is substring and ignore-case.

%s
Use the -n option to see all top-level folder names from all stores.""" \
    % (os.path.basename(sys.argv[0]),folder_doc)
    print msg

def main():
    driver = mapi_driver.MAPIDriver()

    import getopt
    try:
        opts, args = getopt.getopt(sys.argv[1:], "f:n")
    except getopt.error, e:
        print e
        print
        usage(driver)
        sys.exit(1)
    folder_names = []

    for opt, opt_val in opts:
        if opt == "-f":
            folder_names.append(opt_val)
        elif opt == "-n":
            driver.DumpTopLevelFolders()
            sys.exit(1)
        else:
            print "Invalid arg"
            return

    if not folder_names:
        folder_names = ["Inbox"] # Assume this exists!

    if len(args) != 1:
        print "You must specify a property tag/name"
        print
        usage(driver)
        sys.exit(1)

    dupe_dict = {}
    for folder_name in folder_names:
        try:
            folder = driver.FindFolder(folder_name)
        except ValueError, details:
            print details
            sys.exit(1)

        FindDupeProps(driver, folder, args[0], dupe_dict)
    DumpDupes(dupe_dict)

if __name__=='__main__':
    main()


syntax highlighted by Code2HTML, v. 0.9.1