0001 ### BITPIM 0002 ### 0003 ### Copyright (C) 2004 Roger Binns <rogerb@rogerbinns.com> 0004 ### 0005 ### This program is free software; you can redistribute it and/or modify 0006 ### it under the terms of the BitPim license as detailed in the LICENSE file. 0007 ### 0008 ### $Id: outlook.py 3022 2006-03-31 03:21:24Z djpham $ 0009 0010 "Be at one with Outlook" 0011 0012 # Reject if not on Windows 0013 import sys 0014 if sys.platform!="win32": 0015 raise ImportError() 0016 0017 import common 0018 0019 # See this recipe on ASPN for how this code started 0020 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/173216 0021 # Chris Somerlot also gave some insights 0022 0023 import outlook_com 0024 0025 import pywintypes 0026 0027 # This is the complete list of field names available 0028 ## Account 0029 ## AssistantName 0030 ## AssistantTelephoneNumber 0031 ## BillingInformation 0032 ## Body 0033 ## Business2TelephoneNumber 0034 ## BusinessAddress 0035 ## BusinessAddressCity 0036 ## BusinessAddressCountry 0037 ## BusinessAddressPostOfficeBox 0038 ## BusinessAddressPostalCode 0039 ## BusinessAddressState 0040 ## BusinessAddressStreet 0041 ## BusinessFaxNumber 0042 ## BusinessHomePage 0043 ## BusinessTelephoneNumber 0044 ## CallbackTelephoneNumber 0045 ## CarTelephoneNumber 0046 ## Categories 0047 ## Children 0048 ## Class 0049 ## Companies 0050 ## CompanyAndFullName 0051 ## CompanyLastFirstNoSpace 0052 ## CompanyLastFirstSpaceOnly 0053 ## CompanyMainTelephoneNumber 0054 ## CompanyName 0055 ## ComputerNetworkName 0056 ## ConversationIndex 0057 ## ConversationTopic 0058 ## CustomerID 0059 ## Department 0060 ## Email1Address 0061 ## Email1AddressType 0062 ## Email1DisplayName 0063 ## Email1EntryID 0064 ## Email2Address 0065 ## Email2AddressType 0066 ## Email2DisplayName 0067 ## Email2EntryID 0068 ## Email3Address 0069 ## Email3AddressType 0070 ## Email3DisplayName 0071 ## Email3EntryID 0072 ## EntryID 0073 ## FTPSite 0074 ## FileAs 0075 ## FirstName 0076 ## FullName 0077 ## FullNameAndCompany 0078 ## Gender 0079 ## GovernmentIDNumber 0080 ## Hobby 0081 ## Home2TelephoneNumber 0082 ## HomeAddress 0083 ## HomeAddressCity 0084 ## HomeAddressCountry 0085 ## HomeAddressPostOfficeBox 0086 ## HomeAddressPostalCode 0087 ## HomeAddressState 0088 ## HomeAddressStreet 0089 ## HomeFaxNumber 0090 ## HomeTelephoneNumber 0091 ## ISDNNumber 0092 ## Importance 0093 ## Initials 0094 ## InternetFreeBusyAddress 0095 ## JobTitle 0096 ## Journal 0097 ## Language 0098 ## LastFirstAndSuffix 0099 ## LastFirstNoSpace 0100 ## LastFirstNoSpaceCompany 0101 ## LastFirstSpaceOnly 0102 ## LastFirstSpaceOnlyCompany 0103 ## LastName 0104 ## LastNameAndFirstName 0105 ## MailingAddress 0106 ## MailingAddressCity 0107 ## MailingAddressCountry 0108 ## MailingAddressPostOfficeBox 0109 ## MailingAddressPostalCode 0110 ## MailingAddressState 0111 ## MailingAddressStreet 0112 ## ManagerName 0113 ## MessageClass 0114 ## MiddleName 0115 ## Mileage 0116 ## MobileTelephoneNumber 0117 ## NetMeetingAlias 0118 ## NetMeetingServer 0119 ## NickName 0120 ## NoAging 0121 ## OfficeLocation 0122 ## OrganizationalIDNumber 0123 ## OtherAddress 0124 ## OtherAddressCity 0125 ## OtherAddressCountry 0126 ## OtherAddressPostOfficeBox 0127 ## OtherAddressPostalCode 0128 ## OtherAddressState 0129 ## OtherAddressStreet 0130 ## OtherFaxNumber 0131 ## OtherTelephoneNumber 0132 ## OutlookInternalVersion 0133 ## OutlookVersion 0134 ## PagerNumber 0135 ## PersonalHomePage 0136 ## PrimaryTelephoneNumber 0137 ## Profession 0138 ## RadioTelephoneNumber 0139 ## ReferredBy 0140 ## Saved 0141 ## SelectedMailingAddress 0142 ## Sensitivity 0143 ## Size 0144 ## Spouse 0145 ## Subject 0146 ## Suffix 0147 ## TTYTDDTelephoneNumber 0148 ## TelexNumber 0149 ## Title 0150 ## UnRead 0151 ## User1 0152 ## User2 0153 ## User3 0154 ## User4 0155 ## UserCertificate 0156 ## WebPage 0157 ## YomiCompanyName 0158 ## YomiFirstName 0159 ##YomiLastName 0160 0161 def getcontacts(folder, keys=None): 0162 """Returns a list of dicts""" 0163 0164 # There is a gross hack to only return email addresses if they are for SMTP 0165 0166 res=[] 0167 for oc in range(folder.Items.Count): 0168 contact=folder.Items.Item(oc+1) 0169 if contact.Class == outlook_com.constants.olContact: 0170 record={} 0171 if keys is None: 0172 keys=[] 0173 for key in contact._prop_map_get_: 0174 # work out if it is a property or a method (last field is None for properties) 0175 if contact._prop_map_get_[key][-1] is None: 0176 keys.append(key) 0177 for key in keys: 0178 v=getattr(contact, key) 0179 if v not in (None, "", "\x00\x00"): 0180 if isinstance(v, pywintypes.TimeType): # convert from com time 0181 try: 0182 v=int(v) 0183 except ValueError: 0184 # illegal time value 0185 continue 0186 if key=="Categories": 0187 # for some idiotic reason Outlook uses comma 0188 # space seperators for this field despite using 0189 # semi-colon elsewhere for the same field so we 0190 # munge the data 0191 v=";".join([x.strip() for x in v.split(",")]) 0192 if key.startswith("Email") and key.endswith("Address"): 0193 keytype=key+"Type" 0194 if keytype not in keys: 0195 if getattr(contact, keytype)!="SMTP": 0196 continue 0197 0198 record[key]=v 0199 res.append(record) 0200 return res 0201 0202 def getitemdata(item, record, keys, client): 0203 for k, k_out, convertor_func in keys: 0204 v=getattr(item, k) 0205 if v is None or v=="\x00\x00": 0206 v='' 0207 if convertor_func is not None: 0208 # run through convertor func 0209 try: 0210 v=convertor_func(record, v, client) 0211 except: 0212 # failed conversion, skip this field 0213 raise 0214 # assign in dict if specified 0215 if k_out is not None: 0216 record[k_out]=v 0217 return record 0218 0219 def getdata(folder, keys=None, preset_dict={}, client=None, post_func=None): 0220 """Returns a list of dicts""" 0221 res=[] 0222 import_errors=[] 0223 if not folder.Items.Count: 0224 # empty folder, just return 0225 return res, import_errors 0226 # prefill keys if necessary 0227 if keys is None: 0228 keys=[] 0229 item=folder.Items.Item(1) 0230 for k in item._prop_map_get_: 0231 if item._prop_map_get_[k][-1] is None: 0232 keys.append((k, k, None)) 0233 # go through the folder and read the data 0234 for i in range(folder.Items.Count): 0235 item=folder.Items.Item(i+1) 0236 record=preset_dict.copy() 0237 try: 0238 getitemdata(item, record, keys, client) 0239 if post_func is None or post_func(item, record, client): 0240 res.append(record) 0241 except: 0242 import_errors.append(record) 0243 return res, import_errors 0244 0245 def getfolderfromid(id, default=False, default_type='contacts'): 0246 """Returns a folder object from the supplied id 0247 0248 @param id: The id of the folder 0249 @param default: If true and the folder can't be found, then return the default""" 0250 onMAPI = getmapinamespace() 0251 try: 0252 folder=onMAPI.GetFolderFromID(id) 0253 except pywintypes.com_error,e: 0254 folder=None 0255 0256 # ::TODO:: should be supplied default type (contacts, calendar etc) 0257 if default and not folder: 0258 if default_type=='calendar': 0259 default_folder=outlook_com.constants.olFolderCalendar 0260 elif default_type=='notes': 0261 default_folder=outlook_com.constants.olFolderNotes 0262 elif default_type=='tasks': 0263 default_folder=outlook_com.constants.olFolderTasks 0264 else: 0265 # default to contacts, works as before 0266 default_folder=outlook_com.constants.olFolderContacts 0267 folder=onMAPI.GetDefaultFolder(default_folder) 0268 return folder 0269 0270 def getfoldername(folder): 0271 n=[] 0272 while folder: 0273 try: 0274 n=[folder.Name]+n 0275 except AttributeError: 0276 break # namespace object has no 'Name' 0277 folder=folder.Parent 0278 return " / ".join(n) 0279 0280 def getfolderid(folder): 0281 return str(folder.EntryID) # de-unicodify it 0282 0283 def pickfolder(): 0284 return getmapinamespace().PickFolder() 0285 0286 _outlookappobject=None 0287 def getoutlookapp(): 0288 global _outlookappobject 0289 if _outlookappobject is None: 0290 _outlookappobject=outlook_com.Application() 0291 return _outlookappobject 0292 0293 _mapinamespaceobject=None 0294 def getmapinamespace(): 0295 global _mapinamespaceobject 0296 if _mapinamespaceobject is None: 0297 _mapinamespaceobject=getoutlookapp().GetNamespace("MAPI") 0298 return _mapinamespaceobject 0299 0300 def releaseoutlook(): 0301 global _mapinamespaceobject 0302 global _outlookappobject 0303 _mapinamespaceobject=None 0304 _outlookappobject=None 0305 0306 0307 if __name__=='__main__': 0308 oOutlookApp=outlook_com.Application() 0309 onMAPI = oOutlookApp.GetNamespace("MAPI") 0310 0311 import guihelper # needed for common.strorunicode symbol 0312 0313 res=onMAPI.PickFolder() 0314 print res 0315 0316 contacts=getcontacts(res) 0317 keys={} 0318 for item in contacts: 0319 for k in item.keys(): 0320 keys[k]=1 0321 keys=keys.keys() 0322 keys.sort() 0323 0324 # Print out keys so they can be pasted in elsewhere 0325 for k in keys: 0326 print " ('%s', )," % (k,) 0327 0328 import wx 0329 import wx.grid 0330 0331 app=wx.PySimpleApp() 0332 import wx.lib.colourdb 0333 wx.lib.colourdb.updateColourDB() 0334 0335 0336 f=wx.Frame(None, -1, "Outlookinfo") 0337 g=wx.grid.Grid(f, -1) 0338 g.CreateGrid(len(contacts)+1,len(keys)) 0339 g.SetColLabelSize(0) 0340 g.SetRowLabelSize(0) 0341 g.SetMargins(1,0) 0342 g.BeginBatch() 0343 attr=wx.grid.GridCellAttr() 0344 attr.SetBackgroundColour(wx.GREEN) 0345 attr.SetFont(wx.Font(10,wx.SWISS, wx.NORMAL, wx.BOLD)) 0346 attr.SetReadOnly(True) 0347 for k in range(len(keys)): 0348 g.SetCellValue(0, k, keys[k]) 0349 g.SetRowAttr(0,attr) 0350 # row attributes 0351 oddattr=wx.grid.GridCellAttr() 0352 oddattr.SetBackgroundColour("OLDLACE") 0353 oddattr.SetReadOnly(True) 0354 evenattr=wx.grid.GridCellAttr() 0355 evenattr.SetBackgroundColour("ALICE BLUE") 0356 evenattr.SetReadOnly(True) 0357 for row in range(len(contacts)): 0358 item=contacts[row] 0359 for col in range(len(keys)): 0360 key=keys[col] 0361 v=item.get(key, "") 0362 v=common.strorunicode(v) 0363 g.SetCellValue(row+1, col, v) 0364 g.SetRowAttr(row+1, (evenattr,oddattr)[row%2]) 0365 0366 g.AutoSizeColumns() 0367 g.AutoSizeRows() 0368 g.EndBatch() 0369 0370 f.Show(True) 0371 app.MainLoop() 0372
Generated by PyXR 0.9.4