3

I have a list of names, some of them complete, some truncated. I would like to search the Outlook address list for matches for these names.

The closest I have come is this Python code which came from ActiveState Code, but it does not search the global addresses, only my (local?) list, which has 3 addresses in it, which is obviously not right. There should be thousands of records.

Any hints welcome. I have googled and read dozens of pages, but nothing conclusive. I'd rather not connect to the LDAP directly, I think that is a policy violation in my org and besides I am not sure it's possible. Would like to do this via the Outlook API if possible.

DEBUG=1

class MSOutlook:
    def __init__(self):
        self.outlookFound = 0
        try:
            self.oOutlookApp = \
                win32com.client.gencache.EnsureDispatch("Outlook.Application")
            self.outlookFound = 1
        except:
            print("MSOutlook: unable to load Outlook")

        self.records = []


    def loadContacts(self, keys=None):
        if not self.outlookFound:
            return

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

        if DEBUG:
            print("number of contacts:", len(ofContacts.Items))

        for oc in range(len(ofContacts.Items)):
            contact = ofContacts.Items.Item(oc + 1)
            if contact.Class == win32com.client.constants.olContact:
                if keys is None:
                    # if we were't give a set of keys to use
                    # then build up a list of keys that we will be
                    # able to process
                    # I didn't include fields of type time, though
                    # those could probably be interpreted
                    keys = []
                    for key in contact._prop_map_get_:
                        if isinstance(getattr(contact, key), (int, str, unicode)):
                            keys.append(key)
                    if DEBUG:
                        keys.sort()
                        print("Fields\n======================================")
                        for key in keys:
                            print(key)
                record = {}
                for key in keys:
                    record[key] = getattr(contact, key)
                if DEBUG:
                    print(oc, record['FullName'])
                self.records.append(record)

Random links:

If anyone can come up with a solution I don't mind if it's C++, VB, Perl, Python, etc.

Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
  • So what you have done so far to solve this problem is to find an old Stack Overflow solution that youu think might be close and feed it back into another question, in the hope that someone will write the code for you. Have you actually written *any* code yourself, and do you have a *specific* problem? – Borodin Aug 25 '15 at 14:51

3 Answers3

8

Your code above deals with the contacts in the default Contacts folder. If you want to check if a given name is in Outlook (either as a contact or in GAL), simply call Application.Session.CreateRecipient followed by Recipient.Resolve. If the call returns true, you can read the Recipient.Address and various other properties.

bastelflp
  • 9,362
  • 7
  • 32
  • 67
Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
  • 1
    I am honored by your presence! I tried OutlookSpy, but I could not figure out how to use it. But I am sure it is very powerful, looks like it can traverse everything. I will try your suggestion now. – Prof. Falken Aug 25 '15 at 18:06
  • No idea why you got a downvote here, your answer was exactly to the point. – Prof. Falken Aug 25 '15 at 21:32
7

Problem solved!

Thanks to Dmitry's answers I could produce this minimal Python code which demonstrates what I wanted to achieve:

from __future__ import print_function
import win32com.client

search_string = 'Doe John'

outlook = win32com.client.gencache.EnsureDispatch('Outlook.Application')
recipient = outlook.Session.CreateRecipient(search_string)
recipient.Resolve()
print('Resolved OK: ', recipient.Resolved)
print('Is it a sendable? (address): ', recipient.Sendable)
print('Name: ', recipient.Name)

ae = recipient.AddressEntry
email_address = None

if 'EX' == ae.Type:
    eu = ae.GetExchangeUser()
    email_address = eu.PrimarySmtpAddress

if 'SMTP' == ae.Type:
    email_address = ae.Address

print('Email address: ', email_address)
Community
  • 1
  • 1
Prof. Falken
  • 24,226
  • 19
  • 100
  • 173
3

The method in @Prof.Falken's solution doesn't always work when there are multiple matches for the search string. I found another solution, which is more robust as it uses exact match of the displayname.

It's inspired by How to fetch exact match of addressEntry object from GAL (Global Address List).

import win32com.client

search_string = 'Doe John'

outlook = win32com.client.gencache.EnsureDispatch('Outlook.Application')
gal = outlook.Session.GetGlobalAddressList()
entries = gal.AddressEntries
ae = entries[search_string]
email_address = None

if 'EX' == ae.Type:
    eu = ae.GetExchangeUser()
    email_address = eu.PrimarySmtpAddress

if 'SMTP' == ae.Type:
    email_address = ae.Address

print('Email address: ', email_address)
Tim
  • 3,178
  • 1
  • 13
  • 26