-->

How can I search the Outlook (2010) Global Address

2020-02-29 06:24发布

问题:

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:

  • MSDN - How to create a Global Address List programmatically using Visual Basic

  • Infinitec - How to get the Global Address List programatically

  • Return Boolean True - Downloading the Global Address List from Outlook/Exchange

  • Grokbase - [python-win32] getting global addressbook with extended mapi

  • Stack Overflow - Searching Outlook Global Address

    Another failed attempt at List

  • ActiveStater Code - RE: Email Address Lookup

  • Stack Overflow - Retrieving outlook Contacts via python

    This is where I got the link above

  • Stack Overflow - Fetching Outlook Contacts with Python

    Doesn't run at all

  • Python for Windows - Automating Microsoft Outlook

    Just default address book. Besides I want to search, not list all.

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

回答1:

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)


回答2:

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)


回答3:

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.