from __future__ import generators
# Do the best we can to completely obliterate a field from Outlook!
from win32com.client import Dispatch, constants
import pythoncom
import os, sys
from win32com.mapi import mapi
from win32com.mapi.mapitags import *
import mapi_driver
def DeleteField_Outlook(folder, name):
name = name.lower()
entries = folder.Items
num_outlook = 0
entry = entries.GetFirst()
while entry is not None:
up = entry.UserProperties
num_props = up.Count
for i in range(num_props):
if up[i+1].Name.lower()==name:
num_outlook += 1
entry.UserProperties.Remove(i+1)
entry.Save()
break
entry = entries.GetNext()
return num_outlook
def DeleteField_MAPI(driver, folder, name):
# OK - now try and wipe the field using MAPI.
propIds = folder.GetIDsFromNames(((mapi.PS_PUBLIC_STRINGS,name),), 0)
if PROP_TYPE(propIds[0])==PT_ERROR:
print "No such field '%s' in folder" % (name,)
return 0
assert propIds[0] == PROP_TAG( PT_UNSPECIFIED, PROP_ID(propIds[0]))
num_mapi = 0
for item in driver.GetAllItems(folder):
# DeleteProps always says"success" - so check to see if it
# actually exists just so we can count it.
hr, vals = item.GetProps(propIds)
if hr==0: # We actually have it
hr, probs = item.DeleteProps(propIds)
if hr == 0:
item.SaveChanges(mapi.MAPI_DEFERRED_ERRORS)
num_mapi += 1
return num_mapi
def DeleteField_Folder(driver, folder, name):
propIds = folder.GetIDsFromNames(((mapi.PS_PUBLIC_STRINGS,name),), 0)
if PROP_TYPE(propIds[0])!=PT_ERROR:
hr, vals = folder.GetProps(propIds)
if hr==0: # We actually have it
hr, probs = folder.DeleteProps(propIds)
if hr == 0:
folder.SaveChanges(mapi.MAPI_DEFERRED_ERRORS)
return 1
return 0
def CountFields(folder):
fields = {}
entries = folder.Items
entry = entries.GetFirst()
while entry is not None:
ups = entry.UserProperties
num_props = ups.Count
for i in range(num_props):
name = ups.Item(i+1).Name
fields[name] = fields.get(name, 0)+1
entry = entries.GetNext()
for name, num in fields.items():
print name, num
def ShowFields(folder, field_name):
field_name = field_name.lower()
entries = folder.Items
entry = entries.GetFirst()
while entry is not None:
ups = entry.UserProperties
num_props = ups.Count
for i in range(num_props):
up = ups[i+1]
name = up.Name
if name.lower()==field_name:
subject = entry.Subject.encode("mbcs", "replace")
print "%s: %s (%d)" % (subject, up.Value, up.Type)
entry = entries.GetNext()
def usage(driver):
folder_doc = driver.GetFolderNameDoc()
msg = """\
Usage: %s [-f foldername -f ...] [-d] [-s] [FieldName ...]
-f - Run over the specified folders (default = Inbox)
-d - Delete the named fields
--no-outlook - Don't delete via the Outlook UserProperties API
--no-mapi - Don't delete via the extended MAPI API
--no-folder - Don't attempt to delete the field from the folder itself
-s - Show message subject and field value for all messages with field
-n - Show top-level folder names and exit
If no options are given, prints a summary of field names in the folders.
%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:],
"dnsf:",
["no-mapi", "no-outlook", "no-folder"])
except getopt.error, e:
print e
print
usage(driver)
sys.exit(1)
delete = show = False
do_mapi = do_outlook = do_folder = True
folder_names = []
for opt, opt_val in opts:
if opt == "-d":
delete = True
elif opt == "-s":
show = True
elif opt == "-f":
folder_names.append(opt_val)
elif opt == "--no-mapi":
do_mapi = False
elif opt == "--no-outlook":
do_outlook = False
elif opt == "--no-folder":
do_folder = False
elif opt == "-n":
driver.DumpTopLevelFolders()
sys.exit(1)
else:
print "Invalid arg"
return
if not folder_names:
folder_names = ["Inbox"] # Assume this exists!
if not args:
print "No args specified - dumping all unique UserProperty names,"
print "and the count of messages they appear in"
outlook = None
for folder_name in folder_names:
try:
folder = driver.FindFolder(folder_name)
except ValueError, details:
print details
print "Ignoring folder '%s'" % (folder_name,)
continue
print "Processing folder '%s'" % (folder_name,)
if not args:
outlook_folder = driver.GetOutlookFolder(folder)
CountFields(outlook_folder)
continue
for field_name in args:
if show:
outlook_folder = driver.GetOutlookFolder(folder)
ShowFields(outlook_folder, field_name)
if delete:
print "Deleting field", field_name
if do_outlook:
outlook_folder = driver.GetOutlookFolder(folder)
num = DeleteField_Outlook(outlook_folder, field_name)
print "Deleted", num, "field instances from Outlook"
if do_mapi:
num = DeleteField_MAPI(driver, folder, field_name)
print "Deleted", num, "field instances via MAPI"
if do_folder:
num = DeleteField_Folder(driver, folder, field_name)
if num:
print "Deleted property from folder"
else:
print "Could not find property to delete in the folder"
## item = folder.Items.Add()
## props = item.UserProperties
## prop=props.Add("TestInt",3 , True, 1)
## prop.Value=66
## item.Save()
if __name__=='__main__':
main()
syntax highlighted by Code2HTML, v. 0.9.1